const models = require('../../models'); const fetch = require('node-fetch'); const config = require('../../config/app'); /** * curl --location 'https://ark.cn-beijing.volces.com/api/v3/chat/completions' \ --header 'Authorization: Bearer fb8942c2-fe94-4092-80fc-233e252f7090' \ --header 'Content-Type: application/json' \ --data '{ "model": "ep-20250206115552-7qg5c", "messages": [ {"role": "user", "content": [ { "type":"text", "text": "根据图片生成多语言的标题和200字以内的文案描述, 支持语言中文(zh)、英语(en)、西班牙语(es)、葡萄牙语(pt)、日语(ja),以json格式输出,形如: title: {zh:, en:}, copy: {zh: en:}" }, { "type": "image_url", "image_url": { "url": "https://color.jccytech.cn/thumbs/v2/work/320/67a241674f9d65537938e36d.png" } } ]} ] }' */ let apiKey = require('process').env.ARK_API_KEY; const url = "https://ark.cn-beijing.volces.com/api/v3/chat/completions"; let headers = { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' } /** * 从豆包获取图片的标题和文案描述 * @param {*} imageUrl */ async function fetchMetaFromDoubao(imageUrl) { let data = { "model": "ep-20250206115552-7qg5c", // Doubao-1.5...ion-pro-32k 当前最新,贵,响应慢,效果好 // "model": "ep-20250204231910-4phb8", // Doubao-vision-lite-32k 便宜点,相应速度快 "messages": [ { "role": "user", "content": [ { "type": "text", "text": "根据图片生成多语言的标题和描述文案(文案200字左右,尽量不要出现诸如画面中、这幅画这样的废话), 支持语言中文(zh)、英语(en)、西班牙语(es)、葡萄牙语(pt)、日语(ja),以json格式输出,形如: title: {zh:, en:}, copy: {zh: en:}" }, { "type": "image_url", "image_url": { "url": `${imageUrl}` } } ] } ] } const jsonData = JSON.stringify(data); const response = await fetch(url, { method: 'POST', headers, body: jsonData }); let responseJson = await response.json(); console.log(responseJson); return responseJson.choices[0].message.content; } async function run() { let done = 0; let duration = 0; let hour, minute, second; let start = Date.now(); // 筛选出所有已经ready并且还没有title的图 let query = { status: { $gte: 7000 }, $or: [{ title: { $exists: false } }, { title: null }] }; let docs = await models.Art.find(query).sort({ publishTime: 'desc' }); let total = docs.length; console.log('total:', total); for (let doc of docs) { let thumbUrl = `${config.resHost}/thumbs/v2/work/320/${doc._id}.png`; if (doc.hasSpecial) { thumbUrl = `${config.resHost}/thumbs/v2/special/320/${doc._id}.png`; } console.time(doc._id); try { let metaInfo = await fetchMetaFromDoubao(thumbUrl); console.log(metaInfo); let metaInfoJson = JSON.parse(metaInfo); let titleJson = metaInfoJson.title; let descJson = metaInfoJson.copy; let title = JSON.stringify(titleJson); let desc = JSON.stringify(descJson); doc.title = title; doc.desc = desc; await doc.save(); } catch (e) { console.error(e.message); } console.timeEnd(doc._id); done++; duration = (Date.now() - start) / 1000; hour = (Math.floor(duration / 60 / 60)).toString().padStart(2, '0'); minute = (Math.floor(duration / 60) % 60).toString().padStart(2, '0'); second = (Math.floor(duration) % 60).toString().padStart(2, '0'); console.log('progress: ' + Math.floor((100 * done / total)) + '% used time: ' + hour + ':' + minute + ':' + second); } } async function test() { let metaInfo = await fetchMetaFromDoubao("https://color.jccytech.cn/thumbs/v2/work/640/67a254ec4f9d65537938e5c5.png"); console.log(metaInfo); let metaInfoJson = JSON.parse(metaInfo); let titleJson = metaInfoJson.title; let descJson = metaInfoJson.copy; let title = JSON.stringify(titleJson); let desc = JSON.stringify(descJson); console.log(title); console.log(desc); } module.exports = { run } if (require.main == module) { run(); }