@2515097216/jimeng-free-api 0.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +645 -0
- package/dist/chunk-KHOQ4PCS.js +5588 -0
- package/dist/chunk-KHOQ4PCS.js.map +1 -0
- package/dist/index.cjs +5614 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/index.cjs +6102 -0
- package/dist/mcp/index.cjs.map +1 -0
- package/dist/mcp/index.d.cts +1 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.js +528 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/welcome.html +10 -0
- package/package.json +77 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/environment.ts","../src/lib/configs/service-config.ts","../src/lib/util.ts","../src/lib/http-status-codes.ts","../src/lib/configs/system-config.ts","../src/lib/config.ts","../src/lib/logger.ts","../src/lib/browser-service.ts","../src/api/controllers/core.ts","../src/lib/exceptions/Exception.ts","../src/lib/exceptions/APIException.ts","../src/api/consts/exceptions.ts","../src/lib/initialize.ts","../src/lib/server.ts","../src/lib/request/Request.ts","../src/lib/response/Response.ts","../src/lib/response/Body.ts","../src/lib/response/FailureBody.ts","../src/lib/consts/exceptions.ts","../src/api/routes/index.ts","../src/api/routes/images.ts","../src/api/controllers/images.ts","../src/lib/configs/model-config.ts","../src/api/routes/chat.ts","../src/api/controllers/chat.ts","../src/api/controllers/videos.ts","../src/api/routes/ping.ts","../src/api/routes/token.ts","../src/api/routes/models.ts","../src/api/routes/videos.ts","../src/api/routes/video.ts"],"sourcesContent":["import path from 'path';\r\n\r\nimport fs from 'fs-extra';\r\nimport minimist from 'minimist';\r\nimport _ from 'lodash';\r\n\r\nconst cmdArgs = minimist(process.argv.slice(2)); //获取命令行参数\r\nconst envVars = process.env; //获取环境变量\r\n\r\nclass Environment {\r\n\r\n /** 命令行参数 */\r\n cmdArgs: any;\r\n /** 环境变量 */\r\n envVars: any;\r\n /** 环境名称 */\r\n env?: string;\r\n /** 服务名称 */\r\n name?: string;\r\n /** 服务地址 */\r\n host?: string;\r\n /** 服务端口 */\r\n port?: number;\r\n /** 包参数 */\r\n package: any;\r\n\r\n constructor(options: any = {}) {\r\n const { cmdArgs, envVars, package: _package } = options;\r\n this.cmdArgs = cmdArgs;\r\n this.envVars = envVars;\r\n this.env = _.defaultTo(cmdArgs.env || envVars.SERVER_ENV, 'dev');\r\n this.name = cmdArgs.name || envVars.SERVER_NAME || undefined;\r\n this.host = cmdArgs.host || envVars.SERVER_HOST || undefined;\r\n this.port = Number(cmdArgs.port || envVars.SERVER_PORT) ? Number(cmdArgs.port || envVars.SERVER_PORT) : undefined;\r\n this.package = _package;\r\n }\r\n\r\n}\r\n\r\nexport default new Environment({\r\n cmdArgs,\r\n envVars,\r\n package: JSON.parse(fs.readFileSync(path.join(path.resolve(), \"package.json\")).toString())\r\n});","import path from 'path';\r\n\r\nimport fs from 'fs-extra';\r\nimport yaml from 'yaml';\r\nimport _ from 'lodash';\r\n\r\nimport environment from '../environment.ts';\r\nimport util from '../util.ts';\r\n\r\nconst CONFIG_PATH = path.join(path.resolve(), 'configs/', environment.env, \"/service.yml\");\r\n\r\n/**\r\n * 服务配置\r\n */\r\nexport class ServiceConfig {\r\n\r\n /** 服务名称 */\r\n name: string;\r\n /** @type {string} 服务绑定主机地址 */\r\n host;\r\n /** @type {number} 服务绑定端口 */\r\n port;\r\n /** @type {string} 服务路由前缀 */\r\n urlPrefix;\r\n /** @type {string} 服务绑定地址(外部访问地址) */\r\n bindAddress;\r\n\r\n constructor(options?: any) {\r\n const { name, host, port, urlPrefix, bindAddress } = options || {};\r\n this.name = _.defaultTo(name, 'jimeng-free-api');\r\n this.host = _.defaultTo(host, '0.0.0.0');\r\n this.port = _.defaultTo(port, 5566);\r\n this.urlPrefix = _.defaultTo(urlPrefix, '');\r\n this.bindAddress = bindAddress;\r\n }\r\n\r\n get addressHost() {\r\n if(this.bindAddress) return this.bindAddress;\r\n const ipAddresses = util.getIPAddressesByIPv4();\r\n for(let ipAddress of ipAddresses) {\r\n if(ipAddress === this.host)\r\n return ipAddress;\r\n }\r\n return ipAddresses[0] || \"127.0.0.1\";\r\n }\r\n\r\n get address() {\r\n return `${this.addressHost}:${this.port}`;\r\n }\r\n\r\n get pageDirUrl() {\r\n return `http://127.0.0.1:${this.port}/page`;\r\n }\r\n\r\n get publicDirUrl() {\r\n return `http://127.0.0.1:${this.port}/public`;\r\n }\r\n\r\n static load() {\r\n const external = _.pickBy(environment, (v, k) => [\"name\", \"host\", \"port\"].includes(k) && !_.isUndefined(v));\r\n if(!fs.pathExistsSync(CONFIG_PATH)) return new ServiceConfig(external);\r\n const data = yaml.parse(fs.readFileSync(CONFIG_PATH).toString());\r\n return new ServiceConfig({ ...data, ...external });\r\n }\r\n\r\n}\r\n\r\nexport default ServiceConfig.load();","import os from \"os\";\r\nimport path from \"path\";\r\nimport crypto from \"crypto\";\r\nimport { Readable, Writable } from \"stream\";\r\n\r\nimport \"colors\";\r\nimport mime from \"mime\";\r\nimport axios from \"axios\";\r\nimport fs from \"fs-extra\";\r\nimport { v1 as uuid } from \"uuid\";\r\nimport { format as dateFormat } from \"date-fns\";\r\nimport CRC32 from \"crc-32\";\r\nimport randomstring from \"randomstring\";\r\nimport _ from \"lodash\";\r\nimport { CronJob } from \"cron\";\r\n\r\nimport HTTP_STATUS_CODE from \"./http-status-codes.ts\";\r\n\r\nconst autoIdMap = new Map();\r\n\r\nconst util = {\r\n is2DArrays(value: any) {\r\n return (\r\n _.isArray(value) &&\r\n (!value[0] || (_.isArray(value[0]) && _.isArray(value[value.length - 1])))\r\n );\r\n },\r\n\r\n uuid: (separator = true) => (separator ? uuid() : uuid().replace(/\\-/g, \"\")),\r\n\r\n autoId: (prefix = \"\") => {\r\n let index = autoIdMap.get(prefix);\r\n if (index > 999999) index = 0; //超过最大数字则重置为0\r\n autoIdMap.set(prefix, (index || 0) + 1);\r\n return `${prefix}${index || 1}`;\r\n },\r\n\r\n ignoreJSONParse(value: string) {\r\n const result = _.attempt(() => JSON.parse(value));\r\n if (_.isError(result)) return null;\r\n return result;\r\n },\r\n\r\n generateRandomString(options: any): string {\r\n return randomstring.generate(options);\r\n },\r\n\r\n getResponseContentType(value: any): string | null {\r\n return value.headers\r\n ? value.headers[\"content-type\"] || value.headers[\"Content-Type\"]\r\n : null;\r\n },\r\n\r\n mimeToExtension(value: string) {\r\n let extension = mime.getExtension(value);\r\n if (extension == \"mpga\") return \"mp3\";\r\n return extension;\r\n },\r\n\r\n extractURLExtension(value: string) {\r\n const extname = path.extname(new URL(value).pathname);\r\n return extname.substring(1).toLowerCase();\r\n },\r\n\r\n createCronJob(cronPatterns: any, callback?: Function) {\r\n if (!_.isFunction(callback))\r\n throw new Error(\"callback must be an Function\");\r\n return new CronJob(\r\n cronPatterns,\r\n () => callback(),\r\n null,\r\n false,\r\n \"Asia/Shanghai\"\r\n );\r\n },\r\n\r\n getDateString(format = \"yyyy-MM-dd\", date = new Date()) {\r\n return dateFormat(date, format);\r\n },\r\n\r\n getIPAddressesByIPv4(): string[] {\r\n const interfaces = os.networkInterfaces();\r\n const addresses = [];\r\n for (let name in interfaces) {\r\n const networks = interfaces[name];\r\n const results = networks.filter(\r\n (network) =>\r\n network.family === \"IPv4\" &&\r\n network.address !== \"127.0.0.1\" &&\r\n !network.internal\r\n );\r\n if (results[0] && results[0].address) addresses.push(results[0].address);\r\n }\r\n return addresses;\r\n },\r\n\r\n getMACAddressesByIPv4(): string[] {\r\n const interfaces = os.networkInterfaces();\r\n const addresses = [];\r\n for (let name in interfaces) {\r\n const networks = interfaces[name];\r\n const results = networks.filter(\r\n (network) =>\r\n network.family === \"IPv4\" &&\r\n network.address !== \"127.0.0.1\" &&\r\n !network.internal\r\n );\r\n if (results[0] && results[0].mac) addresses.push(results[0].mac);\r\n }\r\n return addresses;\r\n },\r\n\r\n generateSSEData(event?: string, data?: string, retry?: number) {\r\n return `event: ${event || \"message\"}\\ndata: ${(data || \"\")\r\n .replace(/\\n/g, \"\\\\n\")\r\n .replace(/\\s/g, \"\\\\s\")}\\nretry: ${retry || 3000}\\n\\n`;\r\n },\r\n\r\n buildDataBASE64(type, ext, buffer) {\r\n return `data:${type}/${ext.replace(\"jpg\", \"jpeg\")};base64,${buffer.toString(\r\n \"base64\"\r\n )}`;\r\n },\r\n\r\n isLinux() {\r\n return os.platform() !== \"win32\";\r\n },\r\n\r\n isIPAddress(value) {\r\n return (\r\n _.isString(value) &&\r\n (/^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$/.test(\r\n value\r\n ) ||\r\n /\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*/.test(\r\n value\r\n ))\r\n );\r\n },\r\n\r\n isPort(value) {\r\n return _.isNumber(value) && value > 0 && value < 65536;\r\n },\r\n\r\n isReadStream(value): boolean {\r\n return (\r\n value &&\r\n (value instanceof Readable || \"readable\" in value || value.readable)\r\n );\r\n },\r\n\r\n isWriteStream(value): boolean {\r\n return (\r\n value &&\r\n (value instanceof Writable || \"writable\" in value || value.writable)\r\n );\r\n },\r\n\r\n isHttpStatusCode(value) {\r\n return _.isNumber(value) && Object.values(HTTP_STATUS_CODE).includes(value);\r\n },\r\n\r\n isURL(value) {\r\n return !_.isUndefined(value) && /^(http|https)/.test(value);\r\n },\r\n\r\n isSrc(value) {\r\n return !_.isUndefined(value) && /^\\/.+\\.[0-9a-zA-Z]+(\\?.+)?$/.test(value);\r\n },\r\n\r\n isBASE64(value) {\r\n return !_.isUndefined(value) && /^[a-zA-Z0-9\\/\\+]+(=?)+$/.test(value);\r\n },\r\n\r\n isBASE64Data(value) {\r\n return /^data:/.test(value);\r\n },\r\n\r\n extractBASE64DataFormat(value): string | null {\r\n const match = value.trim().match(/^data:(.+);base64,/);\r\n if (!match) return null;\r\n return match[1];\r\n },\r\n\r\n removeBASE64DataHeader(value): string {\r\n return value.replace(/^data:(.+);base64,/, \"\");\r\n },\r\n\r\n isDataString(value): boolean {\r\n return /^(base64|json):/.test(value);\r\n },\r\n\r\n isStringNumber(value) {\r\n return _.isFinite(Number(value));\r\n },\r\n\r\n isUnixTimestamp(value) {\r\n return /^[0-9]{10}$/.test(`${value}`);\r\n },\r\n\r\n isTimestamp(value) {\r\n return /^[0-9]{13}$/.test(`${value}`);\r\n },\r\n\r\n isEmail(value) {\r\n return /^([a-zA-Z0-9]+[_|\\_|\\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\\_|\\.]?)*[a-zA-Z0-9]+\\.[a-zA-Z]{2,3}$/.test(\r\n value\r\n );\r\n },\r\n\r\n isAsyncFunction(value) {\r\n return Object.prototype.toString.call(value) === \"[object AsyncFunction]\";\r\n },\r\n\r\n async isAPNG(filePath) {\r\n let head;\r\n const readStream = fs.createReadStream(filePath, { start: 37, end: 40 });\r\n const readPromise = new Promise((resolve, reject) => {\r\n readStream.once(\"end\", resolve);\r\n readStream.once(\"error\", reject);\r\n });\r\n readStream.once(\"data\", (data) => (head = data));\r\n await readPromise;\r\n return head.compare(Buffer.from([0x61, 0x63, 0x54, 0x4c])) === 0;\r\n },\r\n\r\n unixTimestamp() {\r\n return parseInt(`${Date.now() / 1000}`);\r\n },\r\n\r\n timestamp() {\r\n return Date.now();\r\n },\r\n\r\n urlJoin(...values) {\r\n let url = \"\";\r\n for (let i = 0; i < values.length; i++)\r\n url += `${i > 0 ? \"/\" : \"\"}${values[i]\r\n .replace(/^\\/*/, \"\")\r\n .replace(/\\/*$/, \"\")}`;\r\n return url;\r\n },\r\n\r\n millisecondsToHmss(milliseconds) {\r\n if (_.isString(milliseconds)) return milliseconds;\r\n milliseconds = parseInt(milliseconds);\r\n const sec = Math.floor(milliseconds / 1000);\r\n const hours = Math.floor(sec / 3600);\r\n const minutes = Math.floor((sec - hours * 3600) / 60);\r\n const seconds = sec - hours * 3600 - minutes * 60;\r\n const ms = (milliseconds % 60000) - seconds * 1000;\r\n return `${hours > 9 ? hours : \"0\" + hours}:${\r\n minutes > 9 ? minutes : \"0\" + minutes\r\n }:${seconds > 9 ? seconds : \"0\" + seconds}.${ms}`;\r\n },\r\n\r\n millisecondsToTimeString(milliseconds) {\r\n if (milliseconds < 1000) return `${milliseconds}ms`;\r\n if (milliseconds < 60000)\r\n return `${parseFloat((milliseconds / 1000).toFixed(2))}s`;\r\n return `${Math.floor(milliseconds / 1000 / 60)}m${Math.floor(\r\n (milliseconds / 1000) % 60\r\n )}s`;\r\n },\r\n\r\n rgbToHex(r, g, b): string {\r\n return ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);\r\n },\r\n\r\n hexToRgb(hex) {\r\n const value = parseInt(hex.replace(/^#/, \"\"), 16);\r\n return [(value >> 16) & 255, (value >> 8) & 255, value & 255];\r\n },\r\n\r\n md5(value) {\r\n return crypto.createHash(\"md5\").update(value).digest(\"hex\");\r\n },\r\n\r\n crc32(value) {\r\n return _.isBuffer(value) ? CRC32.buf(value) : CRC32.str(value);\r\n },\r\n\r\n arrayParse(value): any[] {\r\n return _.isArray(value) ? value : [value];\r\n },\r\n\r\n booleanParse(value) {\r\n return value === \"true\" || value === true ? true : false;\r\n },\r\n\r\n encodeBASE64(value) {\r\n return Buffer.from(value).toString(\"base64\");\r\n },\r\n\r\n decodeBASE64(value) {\r\n return Buffer.from(value, \"base64\").toString();\r\n },\r\n\r\n async fetchFileBASE64(url: string) {\r\n const result = await axios.get(url, {\r\n responseType: \"arraybuffer\",\r\n });\r\n return result.data.toString(\"base64\");\r\n },\r\n};\r\n\r\nexport default util;\r\n","export default {\r\n\r\n CONTINUE: 100, //客户端应当继续发送请求。这个临时响应是用来通知客户端它的部分请求已经被服务器接收,且仍未被拒绝。客户端应当继续发送请求的剩余部分,或者如果请求已经完成,忽略这个响应。服务器必须在请求完成后向客户端发送一个最终响应\r\n SWITCHING_PROTOCOLS: 101, //服务器已经理解了客户端的请求,并将通过Upgrade 消息头通知客户端采用不同的协议来完成这个请求。在发送完这个响应最后的空行后,服务器将会切换到在Upgrade 消息头中定义的那些协议。只有在切换新的协议更有好处的时候才应该采取类似措施。例如,切换到新的HTTP 版本比旧版本更有优势,或者切换到一个实时且同步的协议以传送利用此类特性的资源\r\n PROCESSING: 102, //处理将被继续执行\r\n\r\n OK: 200, //请求已成功,请求所希望的响应头或数据体将随此响应返回\r\n CREATED: 201, //请求已经被实现,而且有一个新的资源已经依据请求的需要而建立,且其 URI 已经随Location 头信息返回。假如需要的资源无法及时建立的话,应当返回 '202 Accepted'\r\n ACCEPTED: 202, //服务器已接受请求,但尚未处理。正如它可能被拒绝一样,最终该请求可能会也可能不会被执行。在异步操作的场合下,没有比发送这个状态码更方便的做法了。返回202状态码的响应的目的是允许服务器接受其他过程的请求(例如某个每天只执行一次的基于批处理的操作),而不必让客户端一直保持与服务器的连接直到批处理操作全部完成。在接受请求处理并返回202状态码的响应应当在返回的实体中包含一些指示处理当前状态的信息,以及指向处理状态监视器或状态预测的指针,以便用户能够估计操作是否已经完成\r\n NON_AUTHORITATIVE_INFO: 203, //服务器已成功处理了请求,但返回的实体头部元信息不是在原始服务器上有效的确定集合,而是来自本地或者第三方的拷贝。当前的信息可能是原始版本的子集或者超集。例如,包含资源的元数据可能导致原始服务器知道元信息的超级。使用此状态码不是必须的,而且只有在响应不使用此状态码便会返回200 OK的情况下才是合适的\r\n NO_CONTENT: 204, //服务器成功处理了请求,但不需要返回任何实体内容,并且希望返回更新了的元信息。响应可能通过实体头部的形式,返回新的或更新后的元信息。如果存在这些头部信息,则应当与所请求的变量相呼应。如果客户端是浏览器的话,那么用户浏览器应保留发送了该请求的页面,而不产生任何文档视图上的变化,即使按照规范新的或更新后的元信息应当被应用到用户浏览器活动视图中的文档。由于204响应被禁止包含任何消息体,因此它始终以消息头后的第一个空行结尾\r\n RESET_CONTENT: 205, //服务器成功处理了请求,且没有返回任何内容。但是与204响应不同,返回此状态码的响应要求请求者重置文档视图。该响应主要是被用于接受用户输入后,立即重置表单,以便用户能够轻松地开始另一次输入。与204响应一样,该响应也被禁止包含任何消息体,且以消息头后的第一个空行结束\r\n PARTIAL_CONTENT: 206, //服务器已经成功处理了部分 GET 请求。类似于FlashGet或者迅雷这类的HTTP下载工具都是使用此类响应实现断点续传或者将一个大文档分解为多个下载段同时下载。该请求必须包含 Range 头信息来指示客户端希望得到的内容范围,并且可能包含 If-Range 来作为请求条件。响应必须包含如下的头部域:Content-Range 用以指示本次响应中返回的内容的范围;如果是Content-Type为multipart/byteranges的多段下载,则每一段multipart中都应包含Content-Range域用以指示本段的内容范围。假如响应中包含Content-Length,那么它的数值必须匹配它返回的内容范围的真实字节数。Date和ETag或Content-Location,假如同样的请求本应该返回200响应。Expires, Cache-Control,和/或 Vary,假如其值可能与之前相同变量的其他响应对应的值不同的话。假如本响应请求使用了 If-Range 强缓存验证,那么本次响应不应该包含其他实体头;假如本响应的请求使用了 If-Range 弱缓存验证,那么本次响应禁止包含其他实体头;这避免了缓存的实体内容和更新了的实体头信息之间的不一致。否则,本响应就应当包含所有本应该返回200响应中应当返回的所有实体头部域。假如 ETag 或 Latest-Modified 头部不能精确匹配的话,则客户端缓存应禁止将206响应返回的内容与之前任何缓存过的内容组合在一起。任何不支持 Range 以及 Content-Range 头的缓存都禁止缓存206响应返回的内容\r\n MULTIPLE_STATUS: 207, //代表之后的消息体将是一个XML消息,并且可能依照之前子请求数量的不同,包含一系列独立的响应代码\r\n\r\n MULTIPLE_CHOICES: 300, //被请求的资源有一系列可供选择的回馈信息,每个都有自己特定的地址和浏览器驱动的商议信息。用户或浏览器能够自行选择一个首选的地址进行重定向。除非这是一个HEAD请求,否则该响应应当包括一个资源特性及地址的列表的实体,以便用户或浏览器从中选择最合适的重定向地址。这个实体的格式由Content-Type定义的格式所决定。浏览器可能根据响应的格式以及浏览器自身能力,自动作出最合适的选择。当然,RFC 2616规范并没有规定这样的自动选择该如何进行。如果服务器本身已经有了首选的回馈选择,那么在Location中应当指明这个回馈的 URI;浏览器可能会将这个 Location 值作为自动重定向的地址。此外,除非额外指定,否则这个响应也是可缓存的\r\n MOVED_PERMANENTLY: 301, //被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个URI之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。除非额外指定,否则这个响应也是可缓存的。新的永久性的URI应当在响应的Location域中返回。除非这是一个HEAD请求,否则响应的实体中应当包含指向新的URI的超链接及简短说明。如果这不是一个GET或者HEAD请求,因此浏览器禁止自动进行重定向,除非得到用户的确认,因为请求的条件可能因此发生变化。注意:对于某些使用 HTTP/1.0 协议的浏览器,当它们发送的POST请求得到了一个301响应的话,接下来的重定向请求将会变成GET方式\r\n FOUND: 302, //请求的资源现在临时从不同的URI响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。新的临时性的URI应当在响应的 Location 域中返回。除非这是一个HEAD请求,否则响应的实体中应当包含指向新的URI的超链接及简短说明。如果这不是一个GET或者HEAD请求,那么浏览器禁止自动进行重定向,除非得到用户的确认,因为请求的条件可能因此发生变化。注意:虽然RFC 1945和RFC 2068规范不允许客户端在重定向时改变请求的方法,但是很多现存的浏览器将302响应视作为303响应,并且使用GET方式访问在Location中规定的URI,而无视原先请求的方法。状态码303和307被添加了进来,用以明确服务器期待客户端进行何种反应\r\n SEE_OTHER: 303, //对应当前请求的响应可以在另一个URI上被找到,而且客户端应当采用 GET 的方式访问那个资源。这个方法的存在主要是为了允许由脚本激活的POST请求输出重定向到一个新的资源。这个新的 URI 不是原始资源的替代引用。同时,303响应禁止被缓存。当然,第二个请求(重定向)可能被缓存。新的 URI 应当在响应的Location域中返回。除非这是一个HEAD请求,否则响应的实体中应当包含指向新的URI的超链接及简短说明。注意:许多 HTTP/1.1 版以前的浏览器不能正确理解303状态。如果需要考虑与这些浏览器之间的互动,302状态码应该可以胜任,因为大多数的浏览器处理302响应时的方式恰恰就是上述规范要求客户端处理303响应时应当做的\r\n NOT_MODIFIED: 304, //如果客户端发送了一个带条件的GET请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码。304响应禁止包含消息体,因此始终以消息头后的第一个空行结尾。该响应必须包含以下的头信息:Date,除非这个服务器没有时钟。假如没有时钟的服务器也遵守这些规则,那么代理服务器以及客户端可以自行将Date字段添加到接收到的响应头中去(正如RFC 2068中规定的一样),缓存机制将会正常工作。ETag或 Content-Location,假如同样的请求本应返回200响应。Expires, Cache-Control,和/或Vary,假如其值可能与之前相同变量的其他响应对应的值不同的话。假如本响应请求使用了强缓存验证,那么本次响应不应该包含其他实体头;否则(例如,某个带条件的 GET 请求使用了弱缓存验证),本次响应禁止包含其他实体头;这避免了缓存了的实体内容和更新了的实体头信息之间的不一致。假如某个304响应指明了当前某个实体没有缓存,那么缓存系统必须忽视这个响应,并且重复发送不包含限制条件的请求。假如接收到一个要求更新某个缓存条目的304响应,那么缓存系统必须更新整个条目以反映所有在响应中被更新的字段的值\r\n USE_PROXY: 305, //被请求的资源必须通过指定的代理才能被访问。Location域中将给出指定的代理所在的URI信息,接收者需要重复发送一个单独的请求,通过这个代理才能访问相应资源。只有原始服务器才能建立305响应。注意:RFC 2068中没有明确305响应是为了重定向一个单独的请求,而且只能被原始服务器建立。忽视这些限制可能导致严重的安全后果\r\n UNUSED: 306, //在最新版的规范中,306状态码已经不再被使用\r\n TEMPORARY_REDIRECT: 307, //请求的资源现在临时从不同的URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。新的临时性的URI 应当在响应的Location域中返回。除非这是一个HEAD请求,否则响应的实体中应当包含指向新的URI 的超链接及简短说明。因为部分浏览器不能识别307响应,因此需要添加上述必要信息以便用户能够理解并向新的 URI 发出访问请求。如果这不是一个GET或者HEAD请求,那么浏览器禁止自动进行重定向,除非得到用户的确认,因为请求的条件可能因此发生变化\r\n\r\n BAD_REQUEST: 400, //1.语义有误,当前请求无法被服务器理解。除非进行修改,否则客户端不应该重复提交这个请求 2.请求参数有误\r\n UNAUTHORIZED: 401, //当前请求需要用户验证。该响应必须包含一个适用于被请求资源的 WWW-Authenticate 信息头用以询问用户信息。客户端可以重复提交一个包含恰当的 Authorization 头信息的请求。如果当前请求已经包含了 Authorization 证书,那么401响应代表着服务器验证已经拒绝了那些证书。如果401响应包含了与前一个响应相同的身份验证询问,且浏览器已经至少尝试了一次验证,那么浏览器应当向用户展示响应中包含的实体信息,因为这个实体信息中可能包含了相关诊断信息。参见RFC 2617\r\n PAYMENT_REQUIRED: 402, //该状态码是为了将来可能的需求而预留的\r\n FORBIDDEN: 403, //服务器已经理解请求,但是拒绝执行它。与401响应不同的是,身份验证并不能提供任何帮助,而且这个请求也不应该被重复提交。如果这不是一个HEAD请求,而且服务器希望能够讲清楚为何请求不能被执行,那么就应该在实体内描述拒绝的原因。当然服务器也可以返回一个404响应,假如它不希望让客户端获得任何信息\r\n NOT_FOUND: 404, //请求失败,请求所希望得到的资源未被在服务器上发现。没有信息能够告诉用户这个状况到底是暂时的还是永久的。假如服务器知道情况的话,应当使用410状态码来告知旧资源因为某些内部的配置机制问题,已经永久的不可用,而且没有任何可以跳转的地址。404这个状态码被广泛应用于当服务器不想揭示到底为何请求被拒绝或者没有其他适合的响应可用的情况下\r\n METHOD_NOT_ALLOWED: 405, //请求行中指定的请求方法不能被用于请求相应的资源。该响应必须返回一个Allow 头信息用以表示出当前资源能够接受的请求方法的列表。鉴于PUT,DELETE方法会对服务器上的资源进行写操作,因而绝大部分的网页服务器都不支持或者在默认配置下不允许上述请求方法,对于此类请求均会返回405错误\r\n NO_ACCEPTABLE: 406, //请求的资源的内容特性无法满足请求头中的条件,因而无法生成响应实体。除非这是一个 HEAD 请求,否则该响应就应当返回一个包含可以让用户或者浏览器从中选择最合适的实体特性以及地址列表的实体。实体的格式由Content-Type头中定义的媒体类型决定。浏览器可以根据格式及自身能力自行作出最佳选择。但是,规范中并没有定义任何作出此类自动选择的标准\r\n PROXY_AUTHENTICATION_REQUIRED: 407, //与401响应类似,只不过客户端必须在代理服务器上进行身份验证。代理服务器必须返回一个Proxy-Authenticate用以进行身份询问。客户端可以返回一个Proxy-Authorization信息头用以验证。参见RFC 2617\r\n REQUEST_TIMEOUT: 408, //请求超时。客户端没有在服务器预备等待的时间内完成一个请求的发送。客户端可以随时再次提交这一请求而无需进行任何更改\r\n CONFLICT: 409, //由于和被请求的资源的当前状态之间存在冲突,请求无法完成。这个代码只允许用在这样的情况下才能被使用:用户被认为能够解决冲突,并且会重新提交新的请求。该响应应当包含足够的信息以便用户发现冲突的源头。冲突通常发生于对PUT请求的处理中。例如,在采用版本检查的环境下,某次PUT提交的对特定资源的修改请求所附带的版本信息与之前的某个(第三方)请求向冲突,那么此时服务器就应该返回一个409错误,告知用户请求无法完成。此时,响应实体中很可能会包含两个冲突版本之间的差异比较,以便用户重新提交归并以后的新版本\r\n GONE: 410, //被请求的资源在服务器上已经不再可用,而且没有任何已知的转发地址。这样的状况应当被认为是永久性的。如果可能,拥有链接编辑功能的客户端应当在获得用户许可后删除所有指向这个地址的引用。如果服务器不知道或者无法确定这个状况是否是永久的,那么就应该使用404状态码。除非额外说明,否则这个响应是可缓存的。410响应的目的主要是帮助网站管理员维护网站,通知用户该资源已经不再可用,并且服务器拥有者希望所有指向这个资源的远端连接也被删除。这类事件在限时、增值服务中很普遍。同样,410响应也被用于通知客户端在当前服务器站点上,原本属于某个个人的资源已经不再可用。当然,是否需要把所有永久不可用的资源标记为'410 Gone',以及是否需要保持此标记多长时间,完全取决于服务器拥有者\r\n LENGTH_REQUIRED: 411, //服务器拒绝在没有定义Content-Length头的情况下接受请求。在添加了表明请求消息体长度的有效Content-Length头之后,客户端可以再次提交该请求 \r\n PRECONDITION_FAILED: 412, //服务器在验证在请求的头字段中给出先决条件时,没能满足其中的一个或多个。这个状态码允许客户端在获取资源时在请求的元信息(请求头字段数据)中设置先决条件,以此避免该请求方法被应用到其希望的内容以外的资源上\r\n REQUEST_ENTITY_TOO_LARGE: 413, //服务器拒绝处理当前请求,因为该请求提交的实体数据大小超过了服务器愿意或者能够处理的范围。此种情况下,服务器可以关闭连接以免客户端继续发送此请求。如果这个状况是临时的,服务器应当返回一个 Retry-After 的响应头,以告知客户端可以在多少时间以后重新尝试\r\n REQUEST_URI_TOO_LONG: 414, //请求的URI长度超过了服务器能够解释的长度,因此服务器拒绝对该请求提供服务。这比较少见,通常的情况包括:本应使用POST方法的表单提交变成了GET方法,导致查询字符串(Query String)过长。重定向URI “黑洞”,例如每次重定向把旧的URI作为新的URI的一部分,导致在若干次重定向后URI超长。客户端正在尝试利用某些服务器中存在的安全漏洞攻击服务器。这类服务器使用固定长度的缓冲读取或操作请求的URI,当GET后的参数超过某个数值后,可能会产生缓冲区溢出,导致任意代码被执行[1]。没有此类漏洞的服务器,应当返回414状态码\r\n UNSUPPORTED_MEDIA_TYPE: 415, //对于当前请求的方法和所请求的资源,请求中提交的实体并不是服务器中所支持的格式,因此请求被拒绝\r\n REQUESTED_RANGE_NOT_SATISFIABLE: 416, //如果请求中包含了Range请求头,并且Range中指定的任何数据范围都与当前资源的可用范围不重合,同时请求中又没有定义If-Range请求头,那么服务器就应当返回416状态码。假如Range使用的是字节范围,那么这种情况就是指请求指定的所有数据范围的首字节位置都超过了当前资源的长度。服务器也应当在返回416状态码的同时,包含一个Content-Range实体头,用以指明当前资源的长度。这个响应也被禁止使用multipart/byteranges作为其 Content-Type\r\n EXPECTION_FAILED: 417, //在请求头Expect中指定的预期内容无法被服务器满足,或者这个服务器是一个代理服务器,它有明显的证据证明在当前路由的下一个节点上,Expect的内容无法被满足\r\n TOO_MANY_CONNECTIONS: 421, //从当前客户端所在的IP地址到服务器的连接数超过了服务器许可的最大范围。通常,这里的IP地址指的是从服务器上看到的客户端地址(比如用户的网关或者代理服务器地址)。在这种情况下,连接数的计算可能涉及到不止一个终端用户\r\n UNPROCESSABLE_ENTITY: 422, //请求格式正确,但是由于含有语义错误,无法响应\r\n FAILED_DEPENDENCY: 424, //由于之前的某个请求发生的错误,导致当前请求失败,例如PROPPATCH\r\n UNORDERED_COLLECTION: 425, //在WebDav Advanced Collections 草案中定义,但是未出现在《WebDAV 顺序集协议》(RFC 3658)中\r\n UPGRADE_REQUIRED: 426, //客户端应当切换到TLS/1.0\r\n RETRY_WITH: 449, //由微软扩展,代表请求应当在执行完适当的操作后进行重试\r\n\r\n INTERNAL_SERVER_ERROR: 500, //服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。一般来说,这个问题都会在服务器的程序码出错时出现\r\n NOT_IMPLEMENTED: 501, //服务器不支持当前请求所需要的某个功能。当服务器无法识别请求的方法,并且无法支持其对任何资源的请求\r\n BAD_GATEWAY: 502, //作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应\r\n SERVICE_UNAVAILABLE: 503, //由于临时的服务器维护或者过载,服务器当前无法处理请求。这个状况是临时的,并且将在一段时间以后恢复。如果能够预计延迟时间,那么响应中可以包含一个 Retry-After 头用以标明这个延迟时间。如果没有给出这个 Retry-After 信息,那么客户端应当以处理500响应的方式处理它。注意:503状态码的存在并不意味着服务器在过载的时候必须使用它。某些服务器只不过是希望拒绝客户端的连接\r\n GATEWAY_TIMEOUT: 504, //作为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器(URI标识出的服务器,例如HTTP、FTP、LDAP)或者辅助服务器(例如DNS)收到响应。注意:某些代理服务器在DNS查询超时时会返回400或者500错误\r\n HTTP_VERSION_NOT_SUPPORTED: 505, //服务器不支持,或者拒绝支持在请求中使用的HTTP版本。这暗示着服务器不能或不愿使用与客户端相同的版本。响应中应当包含一个描述了为何版本不被支持以及服务器支持哪些协议的实体\r\n VARIANT_ALSO_NEGOTIATES: 506, //服务器存在内部配置错误:被请求的协商变元资源被配置为在透明内容协商中使用自己,因此在一个协商处理中不是一个合适的重点\r\n INSUFFICIENT_STORAGE: 507, //服务器无法存储完成请求所必须的内容。这个状况被认为是临时的\r\n BANDWIDTH_LIMIT_EXCEEDED: 509, //服务器达到带宽限制。这不是一个官方的状态码,但是仍被广泛使用\r\n NOT_EXTENDED: 510 //获取资源所需要的策略并没有没满足\r\n\r\n};","import path from 'path';\r\n\r\nimport fs from 'fs-extra';\r\nimport yaml from 'yaml';\r\nimport _ from 'lodash';\r\n\r\nimport environment from '../environment.ts';\r\n\r\nconst CONFIG_PATH = path.join(path.resolve(), 'configs/', environment.env, \"/system.yml\");\r\n\r\n/**\r\n * 系统配置\r\n */\r\nexport class SystemConfig {\r\n\r\n /** 是否开启请求日志 */\r\n requestLog: boolean;\r\n /** 临时目录路径 */\r\n tmpDir: string;\r\n /** 日志目录路径 */\r\n logDir: string;\r\n /** 日志写入间隔(毫秒) */\r\n logWriteInterval: number;\r\n /** 日志文件有效期(毫秒) */\r\n logFileExpires: number;\r\n /** 公共目录路径 */\r\n publicDir: string;\r\n /** 临时文件有效期(毫秒) */\r\n tmpFileExpires: number;\r\n /** 请求体配置 */\r\n requestBody: any;\r\n /** 是否调试模式 */\r\n debug: boolean;\r\n\r\n constructor(options?: any) {\r\n const { requestLog, tmpDir, logDir, logWriteInterval, logFileExpires, publicDir, tmpFileExpires, requestBody, debug } = options || {};\r\n this.requestLog = _.defaultTo(requestLog, false);\r\n this.tmpDir = _.defaultTo(tmpDir, './tmp');\r\n this.logDir = _.defaultTo(logDir, './logs');\r\n this.logWriteInterval = _.defaultTo(logWriteInterval, 200);\r\n this.logFileExpires = _.defaultTo(logFileExpires, 2626560000);\r\n this.publicDir = _.defaultTo(publicDir, './public');\r\n this.tmpFileExpires = _.defaultTo(tmpFileExpires, 86400000);\r\n this.requestBody = Object.assign(requestBody || {}, {\r\n enableTypes: ['form', 'text', 'xml'], // 移除 json,由自定义中间件处理\r\n encoding: 'utf-8',\r\n formLimit: '100mb',\r\n jsonLimit: '100mb',\r\n textLimit: '100mb',\r\n xmlLimit: '100mb',\r\n formidable: {\r\n maxFileSize: '100mb'\r\n },\r\n multipart: true,\r\n parsedMethods: ['POST', 'PUT', 'PATCH']\r\n });\r\n this.debug = _.defaultTo(debug, true);\r\n }\r\n\r\n get rootDirPath() {\r\n return path.resolve();\r\n }\r\n\r\n get tmpDirPath() {\r\n return path.resolve(this.tmpDir);\r\n }\r\n\r\n get logDirPath() {\r\n return path.resolve(this.logDir);\r\n }\r\n\r\n get publicDirPath() {\r\n return path.resolve(this.publicDir);\r\n }\r\n\r\n static load() {\r\n if (!fs.pathExistsSync(CONFIG_PATH)) return new SystemConfig();\r\n const data = yaml.parse(fs.readFileSync(CONFIG_PATH).toString());\r\n return new SystemConfig(data);\r\n }\r\n\r\n}\r\n\r\nexport default SystemConfig.load();","import serviceConfig from \"./configs/service-config.ts\";\r\nimport systemConfig from \"./configs/system-config.ts\";\r\n\r\nclass Config {\r\n \r\n /** 服务配置 */\r\n service = serviceConfig;\r\n \r\n /** 系统配置 */\r\n system = systemConfig;\r\n\r\n}\r\n\r\nexport default new Config();","import path from 'path';\r\nimport _util from 'util';\r\n\r\nimport 'colors';\r\nimport _ from 'lodash';\r\nimport fs from 'fs-extra';\r\nimport { format as dateFormat } from 'date-fns';\r\n\r\nimport config from './config.ts';\r\nimport util from './util.ts';\r\n\r\nconst isVercelEnv = process.env.VERCEL;\r\n\r\nclass LogWriter {\r\n\r\n #buffers = [];\r\n\r\n constructor() {\r\n !isVercelEnv && fs.ensureDirSync(config.system.logDirPath);\r\n !isVercelEnv && this.work();\r\n }\r\n\r\n push(content) {\r\n const buffer = Buffer.from(content);\r\n this.#buffers.push(buffer);\r\n }\r\n\r\n writeSync(buffer) {\r\n !isVercelEnv && fs.appendFileSync(path.join(config.system.logDirPath, `/${util.getDateString()}.log`), buffer);\r\n }\r\n\r\n async write(buffer) {\r\n !isVercelEnv && await fs.appendFile(path.join(config.system.logDirPath, `/${util.getDateString()}.log`), buffer);\r\n }\r\n\r\n flush() {\r\n if(!this.#buffers.length) return;\r\n !isVercelEnv && fs.appendFileSync(path.join(config.system.logDirPath, `/${util.getDateString()}.log`), Buffer.concat(this.#buffers));\r\n }\r\n\r\n work() {\r\n if (!this.#buffers.length) return setTimeout(this.work.bind(this), config.system.logWriteInterval);\r\n const buffer = Buffer.concat(this.#buffers);\r\n this.#buffers = [];\r\n this.write(buffer)\r\n .finally(() => setTimeout(this.work.bind(this), config.system.logWriteInterval))\r\n .catch(err => console.error(\"Log write error:\", err));\r\n }\r\n\r\n}\r\n\r\nclass LogText {\r\n\r\n /** @type {string} 日志级别 */\r\n level;\r\n /** @type {string} 日志文本 */\r\n text;\r\n /** @type {string} 日志来源 */\r\n source;\r\n /** @type {Date} 日志发生时间 */\r\n time = new Date();\r\n\r\n constructor(level, ...params) {\r\n this.level = level;\r\n this.text = _util.format.apply(null, params);\r\n this.source = this.#getStackTopCodeInfo();\r\n }\r\n\r\n #getStackTopCodeInfo() {\r\n const unknownInfo = { name: \"unknown\", codeLine: 0, codeColumn: 0 };\r\n const stackArray = new Error().stack.split(\"\\n\");\r\n const text = stackArray[4];\r\n if (!text)\r\n return unknownInfo;\r\n const match = text.match(/at (.+) \\((.+)\\)/) || text.match(/at (.+)/);\r\n if (!match || !_.isString(match[2] || match[1]))\r\n return unknownInfo;\r\n const temp = match[2] || match[1];\r\n const _match = temp.match(/([a-zA-Z0-9_\\-\\.]+)\\:(\\d+)\\:(\\d+)$/);\r\n if (!_match)\r\n return unknownInfo;\r\n const [, scriptPath, codeLine, codeColumn] = _match as any;\r\n return {\r\n name: scriptPath ? scriptPath.replace(/.js$/, \"\") : \"unknown\",\r\n path: scriptPath || null,\r\n codeLine: parseInt(codeLine || 0),\r\n codeColumn: parseInt(codeColumn || 0)\r\n };\r\n }\r\n\r\n toString() {\r\n return `[${dateFormat(this.time, \"yyyy-MM-dd HH:mm:ss.SSS\")}][${this.level}][${this.source.name}<${this.source.codeLine},${this.source.codeColumn}>] ${this.text}`;\r\n }\r\n\r\n}\r\n\r\nclass Logger {\r\n\r\n /** @type {Object} 系统配置 */\r\n config = {};\r\n /** @type {Object} 日志级别映射 */\r\n static Level = {\r\n Success: \"success\",\r\n Info: \"info\",\r\n Log: \"log\",\r\n Debug: \"debug\",\r\n Warning: \"warning\",\r\n Error: \"error\",\r\n Fatal: \"fatal\"\r\n };\r\n /** @type {Object} 日志级别文本颜色樱色 */\r\n static LevelColor = {\r\n [Logger.Level.Success]: \"green\",\r\n [Logger.Level.Info]: \"brightCyan\",\r\n [Logger.Level.Debug]: \"white\",\r\n [Logger.Level.Warning]: \"brightYellow\",\r\n [Logger.Level.Error]: \"brightRed\",\r\n [Logger.Level.Fatal]: \"red\"\r\n };\r\n #writer;\r\n\r\n constructor() {\r\n this.#writer = new LogWriter();\r\n }\r\n\r\n header() {\r\n this.#writer.writeSync(Buffer.from(`\\n\\n===================== LOG START ${dateFormat(new Date(), \"yyyy-MM-dd HH:mm:ss.SSS\")} =====================\\n\\n`));\r\n }\r\n\r\n footer() {\r\n this.#writer.flush(); //将未写入文件的日志缓存写入\r\n this.#writer.writeSync(Buffer.from(`\\n\\n===================== LOG END ${dateFormat(new Date(), \"yyyy-MM-dd HH:mm:ss.SSS\")} =====================\\n\\n`));\r\n }\r\n\r\n success(...params) {\r\n const content = new LogText(Logger.Level.Success, ...params).toString();\r\n console.info(content[Logger.LevelColor[Logger.Level.Success]]);\r\n this.#writer.push(content + \"\\n\");\r\n }\r\n\r\n info(...params) {\r\n const content = new LogText(Logger.Level.Info, ...params).toString();\r\n console.info(content[Logger.LevelColor[Logger.Level.Info]]);\r\n this.#writer.push(content + \"\\n\");\r\n }\r\n\r\n log(...params) {\r\n const content = new LogText(Logger.Level.Log, ...params).toString();\r\n console.log(content[Logger.LevelColor[Logger.Level.Log]]);\r\n this.#writer.push(content + \"\\n\");\r\n }\r\n\r\n debug(...params) {\r\n if(!config.system.debug) return; //非调试模式忽略debug\r\n const content = new LogText(Logger.Level.Debug, ...params).toString();\r\n console.debug(content[Logger.LevelColor[Logger.Level.Debug]]);\r\n this.#writer.push(content + \"\\n\");\r\n }\r\n\r\n warn(...params) {\r\n const content = new LogText(Logger.Level.Warning, ...params).toString();\r\n console.warn(content[Logger.LevelColor[Logger.Level.Warning]]);\r\n this.#writer.push(content + \"\\n\");\r\n }\r\n\r\n error(...params) {\r\n const content = new LogText(Logger.Level.Error, ...params).toString();\r\n console.error(content[Logger.LevelColor[Logger.Level.Error]]);\r\n this.#writer.push(content);\r\n }\r\n\r\n fatal(...params) {\r\n const content = new LogText(Logger.Level.Fatal, ...params).toString();\r\n console.error(content[Logger.LevelColor[Logger.Level.Fatal]]);\r\n this.#writer.push(content);\r\n }\r\n\r\n destory() {\r\n this.#writer.destory();\r\n }\r\n\r\n}\r\n\r\nexport default new Logger();","import { chromium, Browser, BrowserContext, Page } from \"playwright-core\";\r\nimport logger from \"@/lib/logger.ts\";\r\nimport { getCookiesForBrowser } from \"@/api/controllers/core.ts\";\r\n\r\n// bdms SDK 相关脚本的白名单域名\r\nconst SCRIPT_WHITELIST_DOMAINS = [\r\n \"vlabstatic.com\",\r\n \"bytescm.com\",\r\n \"jianying.com\",\r\n \"byteimg.com\",\r\n];\r\n\r\n// 需要屏蔽的资源类型(加速加载、减少内存)\r\nconst BLOCKED_RESOURCE_TYPES = [\"image\", \"font\", \"stylesheet\", \"media\"];\r\n\r\n// 会话空闲超时时间(毫秒)\r\nconst SESSION_IDLE_TIMEOUT = 10 * 60 * 1000;\r\n\r\n// bdms SDK 就绪等待超时(毫秒)\r\nconst BDMS_READY_TIMEOUT = 30000;\r\n\r\ninterface BrowserSession {\r\n context: BrowserContext;\r\n page: Page;\r\n lastUsed: number;\r\n idleTimer: NodeJS.Timeout | null;\r\n}\r\n\r\nclass BrowserService {\r\n private browser: Browser | null = null;\r\n private sessions: Map<string, BrowserSession> = new Map();\r\n private launching: Promise<Browser> | null = null;\r\n\r\n /**\r\n * 懒启动浏览器实例\r\n */\r\n private async ensureBrowser(): Promise<Browser> {\r\n if (this.browser?.isConnected()) {\r\n return this.browser;\r\n }\r\n\r\n // 防止并发启动\r\n if (this.launching) {\r\n return this.launching;\r\n }\r\n\r\n this.launching = (async () => {\r\n logger.info(\"BrowserService: 正在启动 Chromium 浏览器...\");\r\n try {\r\n this.browser = await chromium.launch({\r\n headless: true,\r\n args: [\r\n \"--no-sandbox\",\r\n \"--disable-setuid-sandbox\",\r\n \"--disable-dev-shm-usage\",\r\n \"--disable-gpu\",\r\n \"--no-first-run\",\r\n \"--no-zygote\",\r\n \"--single-process\",\r\n ],\r\n });\r\n\r\n this.browser.on(\"disconnected\", () => {\r\n logger.warn(\"BrowserService: 浏览器已断开连接\");\r\n this.browser = null;\r\n this.sessions.clear();\r\n });\r\n\r\n logger.info(\"BrowserService: Chromium 浏览器启动成功\");\r\n return this.browser;\r\n } finally {\r\n this.launching = null;\r\n }\r\n })();\r\n\r\n return this.launching;\r\n }\r\n\r\n /**\r\n * 获取或创建指定 token 的浏览器会话\r\n */\r\n private async getSession(token: string): Promise<BrowserSession> {\r\n const existing = this.sessions.get(token);\r\n if (existing) {\r\n existing.lastUsed = Date.now();\r\n // 重置空闲计时器\r\n if (existing.idleTimer) {\r\n clearTimeout(existing.idleTimer);\r\n }\r\n existing.idleTimer = setTimeout(() => this.closeSession(token), SESSION_IDLE_TIMEOUT);\r\n return existing;\r\n }\r\n\r\n return this.createSession(token);\r\n }\r\n\r\n /**\r\n * 创建新的浏览器会话\r\n */\r\n private async createSession(token: string): Promise<BrowserSession> {\r\n const browser = await this.ensureBrowser();\r\n\r\n logger.info(`BrowserService: 为 token ${token.substring(0, 8)}... 创建新会话`);\r\n\r\n const context = await browser.newContext({\r\n userAgent:\r\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36\",\r\n viewport: { width: 1920, height: 1080 },\r\n locale: \"zh-CN\",\r\n });\r\n\r\n // 注入 cookies\r\n const cookies = getCookiesForBrowser(token);\r\n await context.addCookies(cookies);\r\n\r\n // 配置资源拦截\r\n await context.route(\"**/*\", (route) => {\r\n const request = route.request();\r\n const resourceType = request.resourceType();\r\n const url = request.url();\r\n\r\n // 屏蔽不需要的资源类型\r\n if (BLOCKED_RESOURCE_TYPES.includes(resourceType)) {\r\n return route.abort();\r\n }\r\n\r\n // 对于脚本资源,只允许白名单域名\r\n if (resourceType === \"script\") {\r\n const isWhitelisted = SCRIPT_WHITELIST_DOMAINS.some((domain) =>\r\n url.includes(domain)\r\n );\r\n if (!isWhitelisted) {\r\n return route.abort();\r\n }\r\n }\r\n\r\n return route.continue();\r\n });\r\n\r\n const page = await context.newPage();\r\n\r\n // 导航到即梦页面,让 bdms SDK 加载\r\n logger.info(\"BrowserService: 正在导航到 jimeng.jianying.com ...\");\r\n await page.goto(\"https://jimeng.jianying.com\", {\r\n waitUntil: \"domcontentloaded\",\r\n timeout: 30000,\r\n });\r\n\r\n // 等待 bdms SDK 就绪\r\n logger.info(\"BrowserService: 等待 bdms SDK 就绪...\");\r\n try {\r\n await page.waitForFunction(\r\n () => {\r\n // bdms SDK 会替换 window.fetch,检测其是否被替换\r\n // 也可以检测 window.bdms 或 window.byted_acrawler\r\n return (\r\n (window as any).bdms?.init ||\r\n (window as any).byted_acrawler ||\r\n // 检测 fetch 是否被替换(bdms 会替换原生 fetch)\r\n window.fetch.toString().indexOf(\"native code\") === -1\r\n );\r\n },\r\n { timeout: BDMS_READY_TIMEOUT }\r\n );\r\n logger.info(\"BrowserService: bdms SDK 已就绪\");\r\n } catch (err) {\r\n logger.warn(\r\n \"BrowserService: bdms SDK 等待超时,可能未完全加载,继续尝试...\"\r\n );\r\n }\r\n\r\n const session: BrowserSession = {\r\n context,\r\n page,\r\n lastUsed: Date.now(),\r\n idleTimer: setTimeout(() => this.closeSession(token), SESSION_IDLE_TIMEOUT),\r\n };\r\n\r\n this.sessions.set(token, session);\r\n return session;\r\n }\r\n\r\n /**\r\n * 关闭指定 token 的会话\r\n */\r\n private async closeSession(token: string) {\r\n const session = this.sessions.get(token);\r\n if (!session) return;\r\n\r\n logger.info(`BrowserService: 关闭空闲会话 ${token.substring(0, 8)}...`);\r\n if (session.idleTimer) {\r\n clearTimeout(session.idleTimer);\r\n }\r\n\r\n try {\r\n await session.context.close();\r\n } catch (err) {\r\n // 忽略关闭错误\r\n }\r\n\r\n this.sessions.delete(token);\r\n }\r\n\r\n /**\r\n * 通过浏览器代理发送 fetch 请求\r\n * bdms SDK 会自动拦截 fetch 并注入 a_bogus 签名\r\n *\r\n * @param token sessionid\r\n * @param url 完整的请求 URL\r\n * @param options fetch 选项 (method, headers, body)\r\n * @returns 解析后的 JSON 响应\r\n */\r\n async fetch(\r\n token: string,\r\n url: string,\r\n options: { method?: string; headers?: Record<string, string>; body?: string }\r\n ): Promise<any> {\r\n const session = await this.getSession(token);\r\n\r\n logger.info(`BrowserService: 代理请求 ${options.method || \"GET\"} ${url.substring(0, 100)}...`);\r\n\r\n try {\r\n const result = await session.page.evaluate(\r\n async ({ url, options }) => {\r\n try {\r\n const res = await fetch(url, {\r\n method: options.method || \"GET\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n ...(options.headers || {}),\r\n },\r\n body: options.body,\r\n credentials: \"include\",\r\n });\r\n const text = await res.text();\r\n return { ok: res.ok, status: res.status, text };\r\n } catch (err: any) {\r\n return { ok: false, status: 0, text: \"\", error: err.message };\r\n }\r\n },\r\n { url, options }\r\n );\r\n\r\n if (result.error) {\r\n throw new Error(`浏览器 fetch 失败: ${result.error}`);\r\n }\r\n\r\n logger.info(`BrowserService: 响应状态 ${result.status}`);\r\n\r\n try {\r\n return JSON.parse(result.text);\r\n } catch {\r\n logger.warn(`BrowserService: 响应不是有效 JSON: ${result.text.substring(0, 200)}`);\r\n return result.text;\r\n }\r\n } catch (err) {\r\n // 如果执行失败(页面崩溃等),清理会话以便下次重建\r\n logger.error(`BrowserService: 请求执行失败: ${(err as Error).message}`);\r\n await this.closeSession(token);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * 关闭所有会话和浏览器实例\r\n */\r\n async close() {\r\n logger.info(\"BrowserService: 正在关闭所有会话和浏览器...\");\r\n\r\n for (const [token] of this.sessions) {\r\n await this.closeSession(token);\r\n }\r\n\r\n if (this.browser) {\r\n try {\r\n await this.browser.close();\r\n } catch (err) {\r\n // 忽略关闭错误\r\n }\r\n this.browser = null;\r\n }\r\n\r\n logger.info(\"BrowserService: 已关闭\");\r\n }\r\n}\r\n\r\n// 单例导出\r\nconst browserService = new BrowserService();\r\nexport default browserService;\r\n","import { PassThrough } from \"stream\";\r\nimport path from \"path\";\r\nimport _ from \"lodash\";\r\nimport mime from \"mime\";\r\nimport axios, { AxiosRequestConfig, AxiosResponse } from \"axios\";\r\n\r\nimport APIException from \"@/lib/exceptions/APIException.ts\";\r\nimport EX from \"@/api/consts/exceptions.ts\";\r\nimport { createParser } from \"eventsource-parser\";\r\nimport logger from \"@/lib/logger.ts\";\r\nimport util from \"@/lib/util.ts\";\r\n\r\n// 模型名称\r\nconst MODEL_NAME = \"jimeng\";\r\n// 默认的AgentID\r\nexport const DEFAULT_ASSISTANT_ID = 513695;\r\n// 版本号\r\nconst VERSION_CODE = \"8.4.0\";\r\n// 平台代码\r\nconst PLATFORM_CODE = \"7\";\r\n// 设备ID\r\nconst DEVICE_ID = Math.random() * 999999999999999999 + 7000000000000000000;\r\n// WebID\r\nexport const WEB_ID = Math.random() * 999999999999999999 + 7000000000000000000;\r\n// 用户ID\r\nexport const USER_ID = util.uuid(false);\r\n// 最大重试次数\r\nconst MAX_RETRY_COUNT = 3;\r\n// 重试延迟\r\nconst RETRY_DELAY = 5000;\r\n// 伪装headers\r\nconst FAKE_HEADERS = {\r\n Accept: \"application/json, text/plain, */*\",\r\n \"Accept-Encoding\": \"gzip, deflate, br, zstd\",\r\n \"Accept-language\": \"zh-CN,zh;q=0.9\",\r\n \"App-Sdk-Version\": \"48.0.0\",\r\n \"Cache-control\": \"no-cache\",\r\n Appid: DEFAULT_ASSISTANT_ID,\r\n Appvr: VERSION_CODE,\r\n Lan: \"zh-Hans\",\r\n Loc: \"cn\",\r\n Origin: \"https://jimeng.jianying.com\",\r\n Pragma: \"no-cache\",\r\n Priority: \"u=1, i\",\r\n Referer: \"https://jimeng.jianying.com\",\r\n Pf: PLATFORM_CODE,\r\n \"Sec-Ch-Ua\":\r\n '\"Google Chrome\";v=\"132\", \"Chromium\";v=\"132\", \"Not_A Brand\";v=\"8\"',\r\n \"Sec-Ch-Ua-Mobile\": \"?0\",\r\n \"Sec-Ch-Ua-Platform\": '\"Windows\"',\r\n \"Sec-Fetch-Dest\": \"empty\",\r\n \"Sec-Fetch-Mode\": \"cors\",\r\n \"Sec-Fetch-Site\": \"same-origin\",\r\n \"User-Agent\":\r\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36\",\r\n};\r\n// 文件最大大小\r\nconst FILE_MAX_SIZE = 100 * 1024 * 1024;\r\n\r\n/**\r\n * 获取缓存中的access_token\r\n *\r\n * 目前jimeng的access_token是固定的,暂无刷新功能\r\n *\r\n * @param refreshToken 用于刷新access_token的refresh_token\r\n */\r\nexport async function acquireToken(refreshToken: string): Promise<string> {\r\n return refreshToken;\r\n}\r\n\r\n/**\r\n * 生成cookie\r\n */\r\nexport function generateCookie(refreshToken: string) {\r\n return [\r\n `_tea_web_id=${WEB_ID}`,\r\n `is_staff_user=false`,\r\n `store-region=cn-gd`,\r\n `store-region-src=uid`,\r\n `sid_guard=${refreshToken}%7C${util.unixTimestamp()}%7C5184000%7CMon%2C+03-Feb-2025+08%3A17%3A09+GMT`,\r\n `uid_tt=${USER_ID}`,\r\n `uid_tt_ss=${USER_ID}`,\r\n `sid_tt=${refreshToken}`,\r\n `sessionid=${refreshToken}`,\r\n `sessionid_ss=${refreshToken}`,\r\n `sid_tt=${refreshToken}`\r\n ].join(\"; \");\r\n}\r\n\r\n/**\r\n * 获取浏览器格式的cookie数组(用于Playwright context.addCookies)\r\n */\r\nexport function getCookiesForBrowser(refreshToken: string) {\r\n const domain = \".jianying.com\";\r\n return [\r\n { name: \"_tea_web_id\", value: String(WEB_ID), domain, path: \"/\" },\r\n { name: \"is_staff_user\", value: \"false\", domain, path: \"/\" },\r\n { name: \"store-region\", value: \"cn-gd\", domain, path: \"/\" },\r\n { name: \"store-region-src\", value: \"uid\", domain, path: \"/\" },\r\n { name: \"uid_tt\", value: USER_ID, domain, path: \"/\" },\r\n { name: \"uid_tt_ss\", value: USER_ID, domain, path: \"/\" },\r\n { name: \"sid_tt\", value: refreshToken, domain, path: \"/\" },\r\n { name: \"sessionid\", value: refreshToken, domain, path: \"/\" },\r\n { name: \"sessionid_ss\", value: refreshToken, domain, path: \"/\" },\r\n ];\r\n}\r\n\r\n/**\r\n * 获取积分信息\r\n *\r\n * @param refreshToken 用于刷新access_token的refresh_token\r\n */\r\nexport async function getCredit(refreshToken: string) {\r\n const {\r\n credit: { gift_credit, purchase_credit, vip_credit }\r\n } = await request(\"POST\", \"/commerce/v1/benefits/user_credit\", refreshToken, {\r\n data: {},\r\n headers: {\r\n // Cookie: 'x-web-secsdk-uid=ef44bd0d-0cf6-448c-b517-fd1b5a7267ba; s_v_web_id=verify_m4b1lhlu_DI8qKRlD_7mJJ_4eqx_9shQ_s8eS2QLAbc4n; passport_csrf_token=86f3619c0c4a9c13f24117f71dc18524; passport_csrf_token_default=86f3619c0c4a9c13f24117f71dc18524; n_mh=9-mIeuD4wZnlYrrOvfzG3MuT6aQmCUtmr8FxV8Kl8xY; sid_guard=a7eb745aec44bb3186dbc2083ea9e1a6%7C1733386629%7C5184000%7CMon%2C+03-Feb-2025+08%3A17%3A09+GMT; uid_tt=59a46c7d3f34bda9588b93590cca2e12; uid_tt_ss=59a46c7d3f34bda9588b93590cca2e12; sid_tt=a7eb745aec44bb3186dbc2083ea9e1a6; sessionid=a7eb745aec44bb3186dbc2083ea9e1a6; sessionid_ss=a7eb745aec44bb3186dbc2083ea9e1a6; is_staff_user=false; sid_ucp_v1=1.0.0-KGRiOGY2ODQyNWU1OTk3NzRhYTE2ZmZhYmFjNjdmYjY3NzRmZGRiZTgKHgjToPCw0cwbEIXDxboGGJ-tHyAMMITDxboGOAhAJhoCaGwiIGE3ZWI3NDVhZWM0NGJiMzE4NmRiYzIwODNlYTllMWE2; ssid_ucp_v1=1.0.0-KGRiOGY2ODQyNWU1OTk3NzRhYTE2ZmZhYmFjNjdmYjY3NzRmZGRiZTgKHgjToPCw0cwbEIXDxboGGJ-tHyAMMITDxboGOAhAJhoCaGwiIGE3ZWI3NDVhZWM0NGJiMzE4NmRiYzIwODNlYTllMWE2; store-region=cn-gd; store-region-src=uid; user_spaces_idc={\"7444764277623653426\":\"lf\"}; ttwid=1|cxHJViEev1mfkjntdMziir8SwbU8uPNVSaeh9QpEUs8|1733966961|d8d52f5f56607427691be4ac44253f7870a34d25dd05a01b4d89b8a7c5ea82ad; _tea_web_id=7444838473275573797; fpk1=fa6c6a4d9ba074b90003896f36b6960066521c1faec6a60bdcb69ec8ddf85e8360b4c0704412848ec582b2abca73d57a; odin_tt=efe9dc150207879b88509e651a1c4af4e7ffb4cfcb522425a75bd72fbf894eda570bbf7ffb551c8b1de0aa2bfa0bd1be6c4157411ecdcf4464fcaf8dd6657d66',\r\n Referer: \"https://jimeng.jianying.com/ai-tool/image/generate\",\r\n // \"Device-Time\": 1733966964,\r\n // Sign: \"f3dbb824b378abea7c03cbb152b3a365\"\r\n }\r\n });\r\n logger.info(`\\n积分信息: \\n赠送积分: ${gift_credit}, 购买积分: ${purchase_credit}, VIP积分: ${vip_credit}`);\r\n return {\r\n giftCredit: gift_credit,\r\n purchaseCredit: purchase_credit,\r\n vipCredit: vip_credit,\r\n totalCredit: gift_credit + purchase_credit + vip_credit\r\n }\r\n}\r\n\r\n/**\r\n * 接收今日积分\r\n *\r\n * @param refreshToken 用于刷新access_token的refresh_token\r\n */\r\nexport async function receiveCredit(refreshToken: string) {\r\n logger.info(\"正在收取今日积分...\")\r\n const { cur_total_credits, receive_quota } = await request(\"POST\", \"/commerce/v1/benefits/credit_receive\", refreshToken, {\r\n data: {\r\n time_zone: \"Asia/Shanghai\"\r\n },\r\n headers: {\r\n Referer: \"https://jimeng.jianying.com/ai-tool/image/generate\"\r\n }\r\n });\r\n logger.info(`\\n今日${receive_quota}积分收取成功\\n剩余积分: ${cur_total_credits}`);\r\n return cur_total_credits;\r\n}\r\n\r\n/**\r\n * 请求jimeng\r\n *\r\n * @param method 请求方法\r\n * @param uri 请求路径\r\n * @param params 请求参数\r\n * @param headers 请求头\r\n */\r\nexport async function request(\r\n method: string,\r\n uri: string,\r\n refreshToken: string,\r\n options: AxiosRequestConfig = {}\r\n) {\r\n const token = await acquireToken(refreshToken);\r\n const deviceTime = util.unixTimestamp();\r\n const sign = util.md5(\r\n `9e2c|${uri.slice(-7)}|${PLATFORM_CODE}|${VERSION_CODE}|${deviceTime}||11ac`\r\n );\r\n \r\n const fullUrl = `https://jimeng.jianying.com${uri}`;\r\n const requestParams = {\r\n aid: DEFAULT_ASSISTANT_ID,\r\n device_platform: \"web\",\r\n region: \"cn\",\r\n webId: WEB_ID,\r\n da_version: \"3.3.2\",\r\n web_component_open_flag: 1,\r\n web_version: \"7.5.0\",\r\n aigc_features: \"app_lip_sync\",\r\n ...(options.params || {}),\r\n };\r\n \r\n const headers = {\r\n ...FAKE_HEADERS,\r\n Cookie: generateCookie(token),\r\n \"Device-Time\": deviceTime,\r\n Sign: sign,\r\n \"Sign-Ver\": \"1\",\r\n ...(options.headers || {}),\r\n };\r\n \r\n logger.info(`发送请求: ${method.toUpperCase()} ${fullUrl}`);\r\n logger.info(`请求参数: ${JSON.stringify(requestParams)}`);\r\n logger.info(`请求数据: ${JSON.stringify(options.data || {})}`);\r\n \r\n // 添加重试逻辑\r\n let retries = 0;\r\n const maxRetries = 3; // 最大重试次数\r\n let lastError = null;\r\n \r\n while (retries <= maxRetries) {\r\n try {\r\n if (retries > 0) {\r\n logger.info(`第 ${retries} 次重试请求: ${method.toUpperCase()} ${fullUrl}`);\r\n // 重试前等待一段时间\r\n await new Promise(resolve => setTimeout(resolve, 1000 * retries));\r\n }\r\n \r\n const response = await axios.request({\r\n method,\r\n url: fullUrl,\r\n params: requestParams,\r\n headers: headers,\r\n timeout: 45000, // 增加超时时间到45秒\r\n validateStatus: () => true, // 允许任何状态码\r\n ..._.omit(options, \"params\", \"headers\"),\r\n });\r\n \r\n // 记录响应状态和头信息\r\n logger.info(`响应状态: ${response.status} ${response.statusText}`);\r\n \r\n // 流式响应直接返回response\r\n if (options.responseType == \"stream\") return response;\r\n \r\n // 记录响应数据摘要\r\n const responseDataSummary = JSON.stringify(response.data).substring(0, 500) + \r\n (JSON.stringify(response.data).length > 500 ? \"...\" : \"\");\r\n logger.info(`响应数据摘要: ${responseDataSummary}`);\r\n \r\n // 检查HTTP状态码\r\n if (response.status >= 400) {\r\n logger.warn(`HTTP错误: ${response.status} ${response.statusText}`);\r\n if (retries < maxRetries) {\r\n retries++;\r\n continue;\r\n }\r\n }\r\n \r\n return checkResult(response);\r\n }\r\n catch (error) {\r\n lastError = error;\r\n logger.error(`请求失败 (尝试 ${retries + 1}/${maxRetries + 1}): ${error.message}`);\r\n \r\n // 如果是网络错误或超时,尝试重试\r\n if ((error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || \r\n error.message.includes('timeout') || error.message.includes('network')) && \r\n retries < maxRetries) {\r\n retries++;\r\n continue;\r\n }\r\n \r\n // 其他错误直接抛出\r\n break;\r\n }\r\n }\r\n \r\n // 所有重试都失败了,抛出最后一个错误\r\n logger.error(`请求失败,已重试 ${retries} 次: ${lastError.message}`);\r\n if (lastError.response) {\r\n logger.error(`响应状态: ${lastError.response.status}`);\r\n logger.error(`响应数据: ${JSON.stringify(lastError.response.data)}`);\r\n }\r\n throw lastError;\r\n }\r\n \r\n /**\r\n * 预检查文件URL有效性\r\n *\r\n * @param fileUrl 文件URL\r\n */\r\n export async function checkFileUrl(fileUrl: string) {\r\n if (util.isBASE64Data(fileUrl)) return;\r\n const result = await axios.head(fileUrl, {\r\n timeout: 15000,\r\n validateStatus: () => true,\r\n });\r\n if (result.status >= 400)\r\n throw new APIException(\r\n EX.API_FILE_URL_INVALID,\r\n `File ${fileUrl} is not valid: [${result.status}] ${result.statusText}`\r\n );\r\n // 检查文件大小\r\n if (result.headers && result.headers[\"content-length\"]) {\r\n const fileSize = parseInt(result.headers[\"content-length\"], 10);\r\n if (fileSize > FILE_MAX_SIZE)\r\n throw new APIException(\r\n EX.API_FILE_EXECEEDS_SIZE,\r\n `File ${fileUrl} is not valid`\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * 上传文件\r\n *\r\n * @param refreshToken 用于刷新access_token的refresh_token\r\n * @param fileUrl 文件URL或BASE64数据\r\n * @param isVideoImage 是否是用于视频图像\r\n * @returns 上传结果,包含image_uri\r\n */\r\nexport async function uploadFile(\r\n refreshToken: string,\r\n fileUrl: string,\r\n isVideoImage: boolean = false\r\n) {\r\n try {\r\n logger.info(`开始上传文件: ${fileUrl}, 视频图像模式: ${isVideoImage}`);\r\n \r\n // 预检查远程文件URL可用性\r\n await checkFileUrl(fileUrl);\r\n\r\n let filename, fileData, mimeType;\r\n // 如果是BASE64数据则直接转换为Buffer\r\n if (util.isBASE64Data(fileUrl)) {\r\n mimeType = util.extractBASE64DataFormat(fileUrl);\r\n const ext = mime.getExtension(mimeType);\r\n filename = `${util.uuid()}.${ext}`;\r\n fileData = Buffer.from(util.removeBASE64DataHeader(fileUrl), \"base64\");\r\n logger.info(`处理BASE64数据,文件名: ${filename}, 类型: ${mimeType}, 大小: ${fileData.length}字节`);\r\n }\r\n // 下载文件到内存,如果您的服务器内存很小,建议考虑改造为流直传到下一个接口上,避免停留占用内存\r\n else {\r\n filename = path.basename(fileUrl);\r\n logger.info(`开始下载远程文件: ${fileUrl}`);\r\n ({ data: fileData } = await axios.get(fileUrl, {\r\n responseType: \"arraybuffer\",\r\n // 100M限制\r\n maxContentLength: FILE_MAX_SIZE,\r\n // 60秒超时\r\n timeout: 60000,\r\n }));\r\n logger.info(`文件下载完成,文件名: ${filename}, 大小: ${fileData.length}字节`);\r\n }\r\n\r\n // 获取文件的MIME类型\r\n mimeType = mimeType || mime.getType(filename);\r\n logger.info(`文件MIME类型: ${mimeType}`);\r\n \r\n // 构建FormData\r\n const formData = new FormData();\r\n const blob = new Blob([fileData], { type: mimeType });\r\n formData.append('file', blob, filename);\r\n \r\n // 获取上传凭证\r\n logger.info(`请求上传凭证,场景: ${isVideoImage ? 'video_cover' : 'aigc_image'}`);\r\n const uploadProofUrl = 'https://imagex.bytedanceapi.com/';\r\n const proofResult = await request(\r\n 'POST',\r\n '/mweb/v1/get_upload_image_proof',\r\n refreshToken,\r\n {\r\n data: {\r\n scene: isVideoImage ? 'video_cover' : 'aigc_image',\r\n file_name: filename,\r\n file_size: fileData.length,\r\n }\r\n }\r\n );\r\n \r\n if (!proofResult || !proofResult.proof_info) {\r\n logger.error(`获取上传凭证失败: ${JSON.stringify(proofResult)}`);\r\n throw new APIException(EX.API_REQUEST_FAILED, '获取上传凭证失败');\r\n }\r\n \r\n logger.info(`获取上传凭证成功`);\r\n \r\n // 上传文件\r\n const { proof_info } = proofResult;\r\n logger.info(`开始上传文件到: ${uploadProofUrl}`);\r\n \r\n const uploadResult = await axios.post(\r\n uploadProofUrl,\r\n formData,\r\n {\r\n headers: {\r\n ...proof_info.headers,\r\n 'Content-Type': 'multipart/form-data',\r\n },\r\n params: proof_info.query_params,\r\n timeout: 60000,\r\n validateStatus: () => true, // 允许任何状态码以便详细处理\r\n }\r\n );\r\n \r\n logger.info(`上传响应状态: ${uploadResult.status}`);\r\n \r\n if (!uploadResult || uploadResult.status !== 200) {\r\n logger.error(`上传文件失败: 状态码 ${uploadResult?.status}, 响应: ${JSON.stringify(uploadResult?.data)}`);\r\n throw new APIException(EX.API_REQUEST_FAILED, `上传文件失败: 状态码 ${uploadResult?.status}`);\r\n }\r\n \r\n // 验证 proof_info.image_uri 是否存在\r\n if (!proof_info.image_uri) {\r\n logger.error(`上传凭证中缺少 image_uri: ${JSON.stringify(proof_info)}`);\r\n throw new APIException(EX.API_REQUEST_FAILED, '上传凭证中缺少 image_uri');\r\n }\r\n \r\n logger.info(`文件上传成功: ${proof_info.image_uri}`);\r\n \r\n // 返回上传结果\r\n return {\r\n image_uri: proof_info.image_uri,\r\n uri: proof_info.image_uri,\r\n }\r\n } catch (error) {\r\n logger.error(`文件上传过程中发生错误: ${error.message}`);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * 检查请求结果\r\n *\r\n * @param result 结果\r\n */\r\nexport function checkResult(result: AxiosResponse) {\r\n const { ret, errmsg, data } = result.data;\r\n if (!_.isFinite(Number(ret))) return result.data;\r\n if (ret === '0') return data;\r\n if (ret === '5000')\r\n throw new APIException(EX.API_IMAGE_GENERATION_INSUFFICIENT_POINTS, `[无法生成图像]: 即梦积分可能不足,${errmsg}`);\r\n throw new APIException(EX.API_REQUEST_FAILED, `[请求jimeng失败]: ${errmsg}`);\r\n}\r\n\r\n/**\r\n * Token切分\r\n *\r\n * @param authorization 认证字符串\r\n */\r\nexport function tokenSplit(authorization: string) {\r\n return authorization.replace(\"Bearer \", \"\").split(\",\");\r\n}\r\n\r\n/**\r\n * 获取Token存活状态\r\n */\r\nexport async function getTokenLiveStatus(refreshToken: string) {\r\n const result = await request(\r\n \"POST\",\r\n \"/passport/account/info/v2\",\r\n refreshToken,\r\n {\r\n params: {\r\n account_sdk_source: \"web\",\r\n },\r\n }\r\n );\r\n try {\r\n const { user_id } = checkResult(result);\r\n return !!user_id;\r\n } catch (err) {\r\n return false;\r\n }\r\n}","import assert from 'assert';\r\n\r\nimport _ from 'lodash';\r\n\r\nexport default class Exception extends Error {\r\n\r\n /** 错误码 */\r\n errcode: number;\r\n /** 错误消息 */\r\n errmsg: string;\r\n /** 数据 */\r\n data: any;\r\n /** HTTP状态码 */\r\n httpStatusCode: number;\r\n\r\n /**\r\n * 构造异常\r\n * \r\n * @param exception 异常\r\n * @param _errmsg 异常消息\r\n */\r\n constructor(exception: (string | number)[], _errmsg?: string) {\r\n assert(_.isArray(exception), 'Exception must be Array');\r\n const [errcode, errmsg] = exception as [number, string];\r\n assert(_.isFinite(errcode), 'Exception errcode invalid');\r\n assert(_.isString(errmsg), 'Exception errmsg invalid');\r\n super(_errmsg || errmsg);\r\n this.errcode = errcode;\r\n this.errmsg = _errmsg || errmsg;\r\n }\r\n\r\n compare(exception: (string | number)[]) {\r\n const [errcode] = exception as [number, string];\r\n return this.errcode == errcode;\r\n }\r\n\r\n setHTTPStatusCode(value: number) {\r\n this.httpStatusCode = value;\r\n return this;\r\n }\r\n\r\n setData(value: any) {\r\n this.data = _.defaultTo(value, null);\r\n return this;\r\n }\r\n\r\n}","import Exception from './Exception.js';\r\n\r\nexport default class APIException extends Exception {\r\n\r\n /**\r\n * 构造异常\r\n * \r\n * @param {[number, string]} exception 异常\r\n */\r\n constructor(exception: (string | number)[], errmsg?: string) {\r\n super(exception, errmsg);\r\n }\r\n\r\n}","export default {\r\n API_TEST: [-9999, 'API异常错误'],\r\n API_REQUEST_PARAMS_INVALID: [-2000, '请求参数非法'],\r\n API_REQUEST_FAILED: [-2001, '请求失败'],\r\n API_TOKEN_EXPIRES: [-2002, 'Token已失效'],\r\n API_FILE_URL_INVALID: [-2003, '远程文件URL非法'],\r\n API_FILE_EXECEEDS_SIZE: [-2004, '远程文件超出大小'],\r\n API_CHAT_STREAM_PUSHING: [-2005, '已有对话流正在输出'],\r\n API_CONTENT_FILTERED: [-2006, '内容由于合规问题已被阻止生成'],\r\n API_IMAGE_GENERATION_FAILED: [-2007, '图像生成失败'],\r\n API_VIDEO_GENERATION_FAILED: [-2008, '视频生成失败'],\r\n API_IMAGE_GENERATION_INSUFFICIENT_POINTS: [-2009, '即梦积分不足'],\r\n}","import logger from './logger.js';\r\nimport browserService from './browser-service.js';\r\n\r\n// 允许无限量的监听器\r\nprocess.setMaxListeners(Infinity);\r\n// 输出未捕获异常\r\nprocess.on(\"uncaughtException\", (err, origin) => {\r\n logger.error(`An unhandled error occurred: ${origin}`, err);\r\n});\r\n// 输出未处理的Promise.reject\r\nprocess.on(\"unhandledRejection\", (_, promise) => {\r\n promise.catch(err => logger.error(\"An unhandled rejection occurred:\", err));\r\n});\r\n// 输出系统警告信息\r\nprocess.on(\"warning\", warning => logger.warn(\"System warning: \", warning));\r\n// 进程退出监听\r\nprocess.on(\"exit\", () => {\r\n logger.info(\"Service exit\");\r\n logger.footer();\r\n});\r\n// 进程被kill\r\nprocess.on(\"SIGTERM\", () => {\r\n logger.warn(\"received kill signal\");\r\n browserService.close().finally(() => process.exit(2));\r\n});\r\n// Ctrl-C进程退出\r\nprocess.on(\"SIGINT\", () => {\r\n browserService.close().finally(() => process.exit(0));\r\n});","import Koa from 'koa';\r\nimport KoaRouter from 'koa-router';\r\nimport koaRange from 'koa-range';\r\nimport koaCors from \"koa2-cors\";\r\nimport koaBody from 'koa-body';\r\nimport _ from 'lodash';\r\n\r\nimport Exception from './exceptions/Exception.ts';\r\nimport Request from './request/Request.ts';\r\nimport Response from './response/Response.js';\r\nimport FailureBody from './response/FailureBody.ts';\r\nimport EX from './consts/exceptions.ts';\r\nimport logger from './logger.ts';\r\nimport config from './config.ts';\r\n\r\nclass Server {\r\n\r\n app;\r\n router;\r\n koaBodyMiddleware;\r\n\r\n constructor() {\r\n this.app = new Koa();\r\n this.app.use(koaCors());\r\n // 范围请求支持\r\n this.app.use(koaRange);\r\n this.router = new KoaRouter({ prefix: config.service.urlPrefix });\r\n\r\n // 预先创建 koa-body 中间件,支持 multipart 文件上传\r\n this.koaBodyMiddleware = koaBody({\r\n multipart: true,\r\n formidable: {\r\n maxFileSize: 100 * 1024 * 1024, // 100MB\r\n keepExtensions: true,\r\n },\r\n formLimit: '100mb',\r\n jsonLimit: '100mb',\r\n textLimit: '100mb',\r\n parsedMethods: ['POST', 'PUT', 'PATCH'],\r\n });\r\n\r\n // 前置处理异常拦截\r\n this.app.use(async (ctx: any, next: Function) => {\r\n if(ctx.request.type === \"application/xml\" || ctx.request.type === \"application/ssml+xml\")\r\n ctx.req.headers[\"content-type\"] = \"text/xml\";\r\n try { await next() }\r\n catch (err) {\r\n logger.error(err);\r\n const failureBody = new FailureBody(err);\r\n new Response(failureBody).injectTo(ctx);\r\n }\r\n });\r\n // 自定义 JSON 解析中间件\r\n this.app.use(async (ctx: any, next: Function) => {\r\n // 跳过 multipart 请求,让 koa-body 处理\r\n if (ctx.is('multipart')) {\r\n await next();\r\n return;\r\n }\r\n if (ctx.is('application/json') && ['POST', 'PUT', 'PATCH'].includes(ctx.method)) {\r\n logger.debug('开始自定义 JSON 解析');\r\n const chunks: Buffer[] = [];\r\n\r\n await new Promise((resolve, reject) => {\r\n ctx.req.on('data', (chunk: Buffer) => {\r\n chunks.push(chunk);\r\n });\r\n\r\n ctx.req.on('end', () => {\r\n resolve(null);\r\n });\r\n\r\n ctx.req.on('error', reject);\r\n });\r\n\r\n const body = Buffer.concat(chunks).toString('utf8');\r\n\r\n // 清理问题字符\r\n let cleanedBody = body\r\n .replace(/\\r\\n/g, '\\n')\r\n .replace(/\\r/g, '\\n')\r\n .replace(/\\u00A0/g, ' ')\r\n .replace(/[\\u2000-\\u200B]/g, ' ')\r\n .replace(/\\uFEFF/g, '')\r\n .trim();\r\n\r\n const parsedBody = JSON.parse(cleanedBody);\r\n\r\n logger.debug('JSON 解析成功,跳过 koa-body');\r\n\r\n ctx.request.body = parsedBody;\r\n ctx.request.rawBody = cleanedBody;\r\n\r\n // 标记已处理,避免 koa-body 再次处理\r\n ctx._jsonProcessed = true;\r\n }\r\n await next();\r\n });\r\n\r\n // 载荷解析器支持(只处理未被自定义解析器处理的请求)\r\n this.app.use(async (ctx: any, next: Function) => {\r\n if (!ctx._jsonProcessed) {\r\n await this.koaBodyMiddleware(ctx, next);\r\n } else {\r\n await next();\r\n }\r\n });\r\n this.app.on(\"error\", (err: any) => {\r\n // 忽略连接重试、中断、管道、取消错误\r\n if ([\"ECONNRESET\", \"ECONNABORTED\", \"EPIPE\", \"ECANCELED\"].includes(err.code)) return;\r\n logger.error(err);\r\n });\r\n logger.success(\"Server initialized\");\r\n }\r\n\r\n /**\r\n * 附加路由\r\n * \r\n * @param routes 路由列表\r\n */\r\n attachRoutes(routes: any[]) {\r\n routes.forEach((route: any) => {\r\n const prefix = route.prefix || \"\";\r\n for (let method in route) {\r\n if(method === \"prefix\") continue;\r\n if (!_.isObject(route[method])) {\r\n logger.warn(`Router ${prefix} ${method} invalid`);\r\n continue;\r\n }\r\n for (let uri in route[method]) {\r\n this.router[method](`${prefix}${uri}`, async ctx => {\r\n const { request, response } = await this.#requestProcessing(ctx, route[method][uri]);\r\n if(response != null && config.system.requestLog)\r\n logger.info(`<- ${request.method} ${request.url} ${response.time - request.time}ms`);\r\n });\r\n }\r\n }\r\n logger.info(`Route ${config.service.urlPrefix || \"\"}${prefix} attached`);\r\n });\r\n this.app.use(this.router.routes());\r\n this.app.use((ctx: any) => {\r\n const request = new Request(ctx);\r\n logger.debug(`-> ${ctx.request.method} ${ctx.request.url} request is not supported - ${request.remoteIP || \"unknown\"}`);\r\n // const failureBody = new FailureBody(new Exception(EX.SYSTEM_NOT_ROUTE_MATCHING, \"Request is not supported\"));\r\n // const response = new Response(failureBody);\r\n const message = `[请求有误]: 正确请求为 POST -> /v1/chat/completions,当前请求为 ${ctx.request.method} -> ${ctx.request.url} 请纠正`;\r\n logger.warn(message);\r\n const failureBody = new FailureBody(new Error(message));\r\n const response = new Response(failureBody);\r\n response.injectTo(ctx);\r\n if(config.system.requestLog)\r\n logger.info(`<- ${request.method} ${request.url} ${response.time - request.time}ms`);\r\n });\r\n }\r\n\r\n /**\r\n * 请求处理\r\n * \r\n * @param ctx 上下文\r\n * @param routeFn 路由方法\r\n */\r\n #requestProcessing(ctx: any, routeFn: Function): Promise<any> {\r\n return new Promise(resolve => {\r\n const request = new Request(ctx);\r\n try {\r\n if(config.system.requestLog)\r\n logger.info(`-> ${request.method} ${request.url}`);\r\n routeFn(request)\r\n .then(response => {\r\n try {\r\n if(!Response.isInstance(response)) {\r\n const _response = new Response(response);\r\n _response.injectTo(ctx);\r\n return resolve({ request, response: _response });\r\n }\r\n response.injectTo(ctx);\r\n resolve({ request, response });\r\n }\r\n catch(err) {\r\n logger.error(err);\r\n const failureBody = new FailureBody(err);\r\n const response = new Response(failureBody);\r\n response.injectTo(ctx);\r\n resolve({ request, response });\r\n }\r\n })\r\n .catch(err => {\r\n try {\r\n logger.error(err);\r\n const failureBody = new FailureBody(err);\r\n const response = new Response(failureBody);\r\n response.injectTo(ctx);\r\n resolve({ request, response });\r\n }\r\n catch(err) {\r\n logger.error(err);\r\n const failureBody = new FailureBody(err);\r\n const response = new Response(failureBody);\r\n response.injectTo(ctx);\r\n resolve({ request, response });\r\n }\r\n });\r\n }\r\n catch(err) {\r\n logger.error(err);\r\n const failureBody = new FailureBody(err);\r\n const response = new Response(failureBody);\r\n response.injectTo(ctx);\r\n resolve({ request, response });\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * 监听端口\r\n */\r\n async listen() {\r\n const host = config.service.host;\r\n const port = config.service.port;\r\n await Promise.all([\r\n new Promise((resolve, reject) => {\r\n if(host === \"0.0.0.0\" || host === \"localhost\" || host === \"127.0.0.1\")\r\n return resolve(null);\r\n this.app.listen(port, \"localhost\", err => {\r\n if(err) return reject(err);\r\n resolve(null);\r\n });\r\n }),\r\n new Promise((resolve, reject) => {\r\n this.app.listen(port, host, err => {\r\n if(err) return reject(err);\r\n resolve(null);\r\n });\r\n })\r\n ]);\r\n logger.success(`Server listening on port ${port} (${host})`);\r\n }\r\n\r\n}\r\n\r\nexport default new Server();","import _ from 'lodash';\r\n\r\nimport APIException from '@/lib/exceptions/APIException.ts';\r\nimport EX from '@/api/consts/exceptions.ts';\r\nimport logger from '@/lib/logger.ts';\r\nimport util from '@/lib/util.ts';\r\n\r\nexport interface RequestOptions {\r\n time?: number;\r\n}\r\n\r\nexport default class Request {\r\n\r\n /** 请求方法 */\r\n method: string;\r\n /** 请求URL */\r\n url: string;\r\n /** 请求路径 */\r\n path: string;\r\n /** 请求载荷类型 */\r\n type: string;\r\n /** 请求headers */\r\n headers: any;\r\n /** 请求原始查询字符串 */\r\n search: string;\r\n /** 请求查询参数 */\r\n query: any;\r\n /** 请求URL参数 */\r\n params: any;\r\n /** 请求载荷 */\r\n body: any;\r\n /** 上传的文件 */\r\n files: any[];\r\n /** 客户端IP地址 */\r\n remoteIP: string | null;\r\n /** 请求接受时间戳(毫秒) */\r\n time: number;\r\n\r\n constructor(ctx, options: RequestOptions = {}) {\r\n const { time } = options;\r\n this.method = ctx.request.method;\r\n this.url = ctx.request.url;\r\n this.path = ctx.request.path;\r\n this.type = ctx.request.type;\r\n this.headers = ctx.request.headers || {};\r\n this.search = ctx.request.search;\r\n this.query = ctx.query || {};\r\n this.params = ctx.params || {};\r\n this.body = ctx.request.body || {};\r\n // koa-body 的 files 可能是对象 { files: [File, File] } 或 { files: File }\r\n // 需要统一转换为数组格式\r\n const rawFiles = ctx.request.files;\r\n if (rawFiles) {\r\n if (Array.isArray(rawFiles)) {\r\n this.files = rawFiles;\r\n } else if (typeof rawFiles === 'object') {\r\n // 遍历对象,提取所有文件\r\n const filesArray: any[] = [];\r\n for (const key in rawFiles) {\r\n const fileOrFiles = rawFiles[key];\r\n if (Array.isArray(fileOrFiles)) {\r\n filesArray.push(...fileOrFiles);\r\n } else if (fileOrFiles) {\r\n filesArray.push(fileOrFiles);\r\n }\r\n }\r\n this.files = filesArray;\r\n } else {\r\n this.files = [];\r\n }\r\n } else {\r\n this.files = [];\r\n }\r\n this.remoteIP = this.headers[\"X-Real-IP\"] || this.headers[\"x-real-ip\"] || this.headers[\"X-Forwarded-For\"] || this.headers[\"x-forwarded-for\"] || ctx.ip || null;\r\n this.time = Number(_.defaultTo(time, util.timestamp()));\r\n }\r\n\r\n validate(key: string, fn?: Function, message?: string) {\r\n try {\r\n const value = _.get(this, key);\r\n if (fn) {\r\n if (fn(value) === false)\r\n throw `[Mismatch] -> ${fn}`;\r\n }\r\n else if (_.isUndefined(value))\r\n throw '[Undefined]';\r\n }\r\n catch (err) {\r\n logger.warn(`Params ${key} invalid:`, err);\r\n throw new APIException(EX.API_REQUEST_PARAMS_INVALID, message || `Params ${key} invalid`);\r\n }\r\n return this;\r\n }\r\n\r\n}","import mime from 'mime';\r\nimport _ from 'lodash';\r\n\r\nimport Body from './Body.ts';\r\nimport util from '../util.ts';\r\n\r\nexport interface ResponseOptions {\r\n statusCode?: number;\r\n type?: string;\r\n headers?: Record<string, any>;\r\n redirect?: string;\r\n body?: any;\r\n size?: number;\r\n time?: number;\r\n}\r\n\r\nexport default class Response {\r\n\r\n /** 响应HTTP状态码 */\r\n statusCode: number;\r\n /** 响应内容类型 */\r\n type: string;\r\n /** 响应headers */\r\n headers: Record<string, any>;\r\n /** 重定向目标 */\r\n redirect: string;\r\n /** 响应载荷 */\r\n body: any;\r\n /** 响应载荷大小 */\r\n size: number;\r\n /** 响应时间戳 */\r\n time: number;\r\n\r\n constructor(body: any, options: ResponseOptions = {}) {\r\n const { statusCode, type, headers, redirect, size, time } = options;\r\n this.statusCode = Number(_.defaultTo(statusCode, Body.isInstance(body) ? body.statusCode : undefined))\r\n this.type = type;\r\n this.headers = headers;\r\n this.redirect = redirect;\r\n this.size = size;\r\n this.time = Number(_.defaultTo(time, util.timestamp()));\r\n this.body = body;\r\n }\r\n\r\n injectTo(ctx) {\r\n this.redirect && ctx.redirect(this.redirect);\r\n this.statusCode && (ctx.status = this.statusCode);\r\n this.type && (ctx.type = mime.getType(this.type) || this.type);\r\n const headers = this.headers || {};\r\n if(this.size && !headers[\"Content-Length\"] && !headers[\"content-length\"])\r\n headers[\"Content-Length\"] = this.size;\r\n ctx.set(headers);\r\n if(Body.isInstance(this.body))\r\n ctx.body = this.body.toObject();\r\n else\r\n ctx.body = this.body;\r\n }\r\n\r\n static isInstance(value) {\r\n return value instanceof Response;\r\n }\r\n\r\n}","import _ from 'lodash';\r\n\r\nexport interface BodyOptions {\r\n code?: number;\r\n message?: string;\r\n data?: any;\r\n statusCode?: number;\r\n}\r\n\r\nexport default class Body {\r\n\r\n /** 状态码 */\r\n code: number;\r\n /** 状态消息 */\r\n message: string;\r\n /** 载荷 */\r\n data: any;\r\n /** HTTP状态码 */\r\n statusCode: number;\r\n\r\n constructor(options: BodyOptions = {}) {\r\n const { code, message, data, statusCode } = options;\r\n this.code = Number(_.defaultTo(code, 0));\r\n this.message = _.defaultTo(message, 'OK');\r\n this.data = _.defaultTo(data, null);\r\n this.statusCode = Number(_.defaultTo(statusCode, 200));\r\n }\r\n\r\n toObject() {\r\n return {\r\n code: this.code,\r\n message: this.message,\r\n data: this.data\r\n };\r\n }\r\n\r\n static isInstance(value) {\r\n return value instanceof Body;\r\n }\r\n\r\n}","import _ from 'lodash';\r\n\r\nimport Body from './Body.ts';\r\nimport Exception from '../exceptions/Exception.ts';\r\nimport APIException from '../exceptions/APIException.ts';\r\nimport EX from '../consts/exceptions.ts';\r\nimport HTTP_STATUS_CODES from '../http-status-codes.ts';\r\n\r\nexport default class FailureBody extends Body {\r\n \r\n constructor(error: APIException | Exception | Error, _data?: any) {\r\n let errcode, errmsg, data = _data, httpStatusCode = HTTP_STATUS_CODES.OK;;\r\n if(_.isString(error))\r\n error = new Exception(EX.SYSTEM_ERROR, error);\r\n else if(error instanceof APIException || error instanceof Exception)\r\n ({ errcode, errmsg, data, httpStatusCode } = error);\r\n else if(_.isError(error))\r\n ({ errcode, errmsg, data, httpStatusCode } = new Exception(EX.SYSTEM_ERROR, error.message));\r\n super({\r\n code: errcode || -1,\r\n message: errmsg || 'Internal error',\r\n data,\r\n statusCode: httpStatusCode\r\n });\r\n }\r\n\r\n static isInstance(value) {\r\n return value instanceof FailureBody;\r\n }\r\n\r\n}","export default {\r\n SYSTEM_ERROR: [-1000, '系统异常'],\r\n SYSTEM_REQUEST_VALIDATION_ERROR: [-1001, '请求参数校验错误'],\r\n SYSTEM_NOT_ROUTE_MATCHING: [-1002, '无匹配的路由']\r\n} as Record<string, [number, string]>","import fs from 'fs-extra';\r\n\r\nimport Response from '@/lib/response/Response.ts';\r\nimport images from \"./images.ts\";\r\nimport chat from \"./chat.ts\";\r\nimport ping from \"./ping.ts\";\r\nimport token from './token.js';\r\nimport models from './models.ts';\r\nimport videos from './videos.ts';\r\nimport video from './video.ts';\r\n\r\nexport default [\r\n {\r\n get: {\r\n '/': async () => {\r\n const content = await fs.readFile('public/welcome.html');\r\n return new Response(content, {\r\n type: 'html',\r\n headers: {\r\n Expires: '-1'\r\n }\r\n });\r\n }\r\n }\r\n },\r\n images,\r\n chat,\r\n ping,\r\n token,\r\n models,\r\n videos,\r\n video\r\n];","import fs from \"fs\";\r\nimport _ from \"lodash\";\r\n\r\nimport Request from \"@/lib/request/Request.ts\";\r\nimport { generateImages, generateImageComposition } from \"@/api/controllers/images.ts\";\r\nimport { tokenSplit } from \"@/api/controllers/core.ts\";\r\nimport util from \"@/lib/util.ts\";\r\n\r\nexport default {\r\n prefix: \"/v1/images\",\r\n\r\n post: {\r\n \"/generations\": async (request: Request) => {\r\n // 检查是否使用了不支持的参数\r\n const unsupportedParams = ['size', 'width', 'height'];\r\n const bodyKeys = Object.keys(request.body);\r\n const foundUnsupported = unsupportedParams.filter(param => bodyKeys.includes(param));\r\n\r\n if (foundUnsupported.length > 0) {\r\n throw new Error(`不支持的参数: ${foundUnsupported.join(', ')}。请使用 ratio 和 resolution 参数控制图像尺寸。`);\r\n }\r\n\r\n const contentType = request.headers['content-type'] || '';\r\n const isMultiPart = contentType.startsWith('multipart/form-data');\r\n\r\n // 根据请求类型进行不同的参数验证\r\n if (isMultiPart) {\r\n request\r\n .validate(\"body.model\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"body.prompt\", _.isString)\r\n .validate(\"body.negative_prompt\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"body.ratio\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"body.resolution\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"body.intelligent_ratio\", v => _.isUndefined(v) || (typeof v === 'string' && (v === 'true' || v === 'false')) || _.isBoolean(v))\r\n .validate(\"body.sample_strength\", v => _.isUndefined(v) || (typeof v === 'string' && !isNaN(parseFloat(v))) || _.isFinite(v))\r\n .validate(\"body.response_format\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"headers.authorization\", _.isString);\r\n } else {\r\n request\r\n .validate(\"body.model\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"body.prompt\", _.isString)\r\n .validate(\"body.images\", v => _.isUndefined(v) || _.isArray(v))\r\n .validate(\"body.negative_prompt\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"body.ratio\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"body.resolution\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"body.intelligent_ratio\", v => _.isUndefined(v) || _.isBoolean(v))\r\n .validate(\"body.sample_strength\", v => _.isUndefined(v) || _.isFinite(v))\r\n .validate(\"body.response_format\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"headers.authorization\", _.isString);\r\n }\r\n\r\n // 处理图片数据(如果提供)\r\n let images: (string | Buffer)[] | null = null;\r\n if (isMultiPart) {\r\n const files = (request.files as any)?.images;\r\n if (files) {\r\n const imageFiles = Array.isArray(files) ? files : [files];\r\n if (imageFiles.length > 0) {\r\n if (imageFiles.length > 10) {\r\n throw new Error(\"最多支持10张输入图片\");\r\n }\r\n images = imageFiles.map((file: any) => fs.readFileSync(file.filepath));\r\n }\r\n }\r\n } else {\r\n const bodyImages = request.body.images;\r\n if (bodyImages && Array.isArray(bodyImages) && bodyImages.length > 0) {\r\n if (bodyImages.length > 10) {\r\n throw new Error(\"最多支持10张输入图片\");\r\n }\r\n bodyImages.forEach((image: any, index: number) => {\r\n if (!_.isString(image) && !_.isObject(image)) {\r\n throw new Error(`图片 ${index + 1} 格式不正确:应为URL字符串或包含url字段的对象`);\r\n }\r\n if (_.isObject(image) && !(image as any).url) {\r\n throw new Error(`图片 ${index + 1} 缺少url字段`);\r\n }\r\n });\r\n images = bodyImages.map((image: any) => _.isString(image) ? image : (image as any).url);\r\n }\r\n }\r\n\r\n // refresh_token切分\r\n const tokens = tokenSplit(request.headers.authorization);\r\n // 随机挑选一个refresh_token\r\n const token = _.sample(tokens);\r\n\r\n const {\r\n model,\r\n prompt,\r\n negative_prompt: negativePrompt,\r\n ratio,\r\n resolution,\r\n intelligent_ratio: intelligentRatio,\r\n sample_strength: sampleStrength,\r\n response_format,\r\n } = request.body;\r\n\r\n // 如果是 multipart/form-data,需要将字符串转换为数字和布尔值\r\n const finalSampleStrength = isMultiPart && typeof sampleStrength === 'string'\r\n ? parseFloat(sampleStrength)\r\n : sampleStrength;\r\n\r\n const finalIntelligentRatio = isMultiPart && typeof intelligentRatio === 'string'\r\n ? intelligentRatio === 'true'\r\n : intelligentRatio;\r\n\r\n const responseFormat = _.defaultTo(response_format, \"url\");\r\n\r\n // 根据是否有图片数据决定调用文生图还是图生图\r\n let imageUrls: string[];\r\n let resultData: any = {\r\n created: util.unixTimestamp(),\r\n };\r\n\r\n if (images && images.length > 0) {\r\n // 图生图模式\r\n imageUrls = await generateImageComposition(model, prompt, images, {\r\n ratio,\r\n resolution,\r\n sampleStrength: finalSampleStrength,\r\n negativePrompt,\r\n intelligentRatio: finalIntelligentRatio,\r\n }, token);\r\n resultData.input_images = images.length;\r\n resultData.composition_type = \"multi_image_synthesis\";\r\n } else {\r\n // 文生图模式\r\n imageUrls = await generateImages(model, prompt, {\r\n ratio,\r\n resolution,\r\n sampleStrength: finalSampleStrength,\r\n negativePrompt,\r\n intelligentRatio: finalIntelligentRatio,\r\n }, token);\r\n }\r\n\r\n let data = [];\r\n if (responseFormat == \"b64_json\") {\r\n data = (\r\n await Promise.all(imageUrls.map((url) => util.fetchFileBASE64(url)))\r\n ).map((b64) => ({ b64_json: b64 }));\r\n } else {\r\n data = imageUrls.map((url) => ({\r\n url,\r\n }));\r\n }\r\n\r\n resultData.data = data;\r\n return resultData;\r\n },\r\n\r\n // 图片合成路由(图生图)\r\n \"/compositions\": async (request: Request) => {\r\n // 检查是否使用了不支持的参数\r\n const unsupportedParams = ['size', 'width', 'height'];\r\n const bodyKeys = Object.keys(request.body);\r\n const foundUnsupported = unsupportedParams.filter(param => bodyKeys.includes(param));\r\n\r\n if (foundUnsupported.length > 0) {\r\n throw new Error(`不支持的参数: ${foundUnsupported.join(', ')}。请使用 ratio 和 resolution 参数控制图像尺寸。`);\r\n }\r\n\r\n const contentType = request.headers['content-type'] || '';\r\n const isMultiPart = contentType.startsWith('multipart/form-data');\r\n\r\n if (isMultiPart) {\r\n request\r\n .validate(\"body.model\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"body.prompt\", _.isString)\r\n .validate(\"body.negative_prompt\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"body.ratio\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"body.resolution\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"body.intelligent_ratio\", v => _.isUndefined(v) || (typeof v === 'string' && (v === 'true' || v === 'false')) || _.isBoolean(v))\r\n .validate(\"body.sample_strength\", v => _.isUndefined(v) || (typeof v === 'string' && !isNaN(parseFloat(v))) || _.isFinite(v))\r\n .validate(\"body.response_format\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"headers.authorization\", _.isString);\r\n } else {\r\n request\r\n .validate(\"body.model\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"body.prompt\", _.isString)\r\n .validate(\"body.images\", _.isArray)\r\n .validate(\"body.negative_prompt\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"body.ratio\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"body.resolution\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"body.intelligent_ratio\", v => _.isUndefined(v) || _.isBoolean(v))\r\n .validate(\"body.sample_strength\", v => _.isUndefined(v) || _.isFinite(v))\r\n .validate(\"body.response_format\", v => _.isUndefined(v) || _.isString(v))\r\n .validate(\"headers.authorization\", _.isString);\r\n }\r\n\r\n let images: (string | Buffer)[] = [];\r\n if (isMultiPart) {\r\n const files = (request.files as any)?.images;\r\n if (!files) {\r\n throw new Error(\"在form-data中缺少 'images' 字段\");\r\n }\r\n const imageFiles = Array.isArray(files) ? files : [files];\r\n if (imageFiles.length === 0) {\r\n throw new Error(\"至少需要提供1张输入图片\");\r\n }\r\n if (imageFiles.length > 10) {\r\n throw new Error(\"最多支持10张输入图片\");\r\n }\r\n images = imageFiles.map((file: any) => fs.readFileSync(file.filepath));\r\n } else {\r\n const bodyImages = request.body.images;\r\n if (!bodyImages || bodyImages.length === 0) {\r\n throw new Error(\"至少需要提供1张输入图片\");\r\n }\r\n if (bodyImages.length > 10) {\r\n throw new Error(\"最多支持10张输入图片\");\r\n }\r\n bodyImages.forEach((image: any, index: number) => {\r\n if (!_.isString(image) && !_.isObject(image)) {\r\n throw new Error(`图片 ${index + 1} 格式不正确:应为URL字符串或包含url字段的对象`);\r\n }\r\n if (_.isObject(image) && !(image as any).url) {\r\n throw new Error(`图片 ${index + 1} 缺少url字段`);\r\n }\r\n });\r\n images = bodyImages.map((image: any) => _.isString(image) ? image : (image as any).url);\r\n }\r\n\r\n // refresh_token切分\r\n const tokens = tokenSplit(request.headers.authorization);\r\n // 随机挑选一个refresh_token\r\n const token = _.sample(tokens);\r\n\r\n const {\r\n model,\r\n prompt,\r\n negative_prompt: negativePrompt,\r\n ratio,\r\n resolution,\r\n intelligent_ratio: intelligentRatio,\r\n sample_strength: sampleStrength,\r\n response_format,\r\n } = request.body;\r\n\r\n // 如果是 multipart/form-data,需要将字符串转换为数字和布尔值\r\n const finalSampleStrength = isMultiPart && typeof sampleStrength === 'string'\r\n ? parseFloat(sampleStrength)\r\n : sampleStrength;\r\n\r\n const finalIntelligentRatio = isMultiPart && typeof intelligentRatio === 'string'\r\n ? intelligentRatio === 'true'\r\n : intelligentRatio;\r\n\r\n const responseFormat = _.defaultTo(response_format, \"url\");\r\n const resultUrls = await generateImageComposition(model, prompt, images, {\r\n ratio,\r\n resolution,\r\n sampleStrength: finalSampleStrength,\r\n negativePrompt,\r\n intelligentRatio: finalIntelligentRatio,\r\n }, token);\r\n\r\n let data = [];\r\n if (responseFormat == \"b64_json\") {\r\n data = (\r\n await Promise.all(resultUrls.map((url) => util.fetchFileBASE64(url)))\r\n ).map((b64) => ({ b64_json: b64 }));\r\n } else {\r\n data = resultUrls.map((url) => ({\r\n url,\r\n }));\r\n }\r\n\r\n return {\r\n created: util.unixTimestamp(),\r\n data,\r\n input_images: images.length,\r\n composition_type: \"multi_image_synthesis\",\r\n };\r\n },\r\n },\r\n};\r\n","import _ from \"lodash\";\r\nimport crypto from \"crypto\";\r\n\r\nimport APIException from \"@/lib/exceptions/APIException.ts\";\r\nimport EX from \"@/api/consts/exceptions.ts\";\r\nimport util from \"@/lib/util.ts\";\r\nimport { getCredit, receiveCredit, request } from \"./core.ts\";\r\nimport logger from \"@/lib/logger.ts\";\r\nimport { getModelConfig } from \"@/lib/configs/model-config.ts\";\r\n\r\nconst DEFAULT_ASSISTANT_ID = 513695;\r\nexport const DEFAULT_MODEL = \"jimeng-4.5\";\r\nconst DRAFT_VERSION = \"3.3.4\";\r\nconst DRAFT_MIN_VERSION = \"3.0.2\";\r\n\r\n// 支持的图片比例和分辨率配置\r\nconst RESOLUTION_OPTIONS: {\r\n [resolution: string]: {\r\n [ratio: string]: { width: number; height: number; ratio: number };\r\n };\r\n} = {\r\n \"1k\": {\r\n \"1:1\": { width: 1024, height: 1024, ratio: 1 },\r\n \"4:3\": { width: 768, height: 1024, ratio: 4 },\r\n \"3:4\": { width: 1024, height: 768, ratio: 2 },\r\n \"16:9\": { width: 1024, height: 576, ratio: 3 },\r\n \"9:16\": { width: 576, height: 1024, ratio: 5 },\r\n \"3:2\": { width: 1024, height: 682, ratio: 7 },\r\n \"2:3\": { width: 682, height: 1024, ratio: 6 },\r\n \"21:9\": { width: 1195, height: 512, ratio: 8 },\r\n },\r\n \"2k\": {\r\n \"1:1\": { width: 2048, height: 2048, ratio: 1 },\r\n \"4:3\": { width: 2304, height: 1728, ratio: 4 },\r\n \"3:4\": { width: 1728, height: 2304, ratio: 2 },\r\n \"16:9\": { width: 2560, height: 1440, ratio: 3 },\r\n \"9:16\": { width: 1440, height: 2560, ratio: 5 },\r\n \"3:2\": { width: 2496, height: 1664, ratio: 7 },\r\n \"2:3\": { width: 1664, height: 2496, ratio: 6 },\r\n \"21:9\": { width: 3024, height: 1296, ratio: 8 },\r\n },\r\n \"4k\": {\r\n \"1:1\": { width: 4096, height: 4096, ratio: 101 },\r\n \"4:3\": { width: 4608, height: 3456, ratio: 104 },\r\n \"3:4\": { width: 3456, height: 4608, ratio: 102 },\r\n \"16:9\": { width: 5120, height: 2880, ratio: 103 },\r\n \"9:16\": { width: 2880, height: 5120, ratio: 105 },\r\n \"3:2\": { width: 4992, height: 3328, ratio: 107 },\r\n \"2:3\": { width: 3328, height: 4992, ratio: 106 },\r\n \"21:9\": { width: 6048, height: 2592, ratio: 108 },\r\n },\r\n};\r\n\r\n// 解析分辨率参数\r\nfunction resolveResolution(\r\n resolution: string = \"2k\",\r\n ratio: string = \"1:1\"\r\n): { width: number; height: number; imageRatio: number; resolutionType: string } {\r\n const resolutionGroup = RESOLUTION_OPTIONS[resolution];\r\n if (!resolutionGroup) {\r\n const supportedResolutions = Object.keys(RESOLUTION_OPTIONS).join(\", \");\r\n throw new Error(`不支持的分辨率 \"${resolution}\"。支持的分辨率: ${supportedResolutions}`);\r\n }\r\n\r\n const ratioConfig = resolutionGroup[ratio];\r\n if (!ratioConfig) {\r\n const supportedRatios = Object.keys(resolutionGroup).join(\", \");\r\n throw new Error(`在 \"${resolution}\" 分辨率下,不支持的比例 \"${ratio}\"。支持的比例: ${supportedRatios}`);\r\n }\r\n\r\n return {\r\n width: ratioConfig.width,\r\n height: ratioConfig.height,\r\n imageRatio: ratioConfig.ratio,\r\n resolutionType: resolution,\r\n };\r\n}\r\n\r\n// 模型特定的版本配置\r\nconst MODEL_DRAFT_VERSIONS: { [key: string]: string } = {\r\n \"jimeng-5.0\": \"3.3.9\",\r\n \"jimeng-4.6\": \"3.3.9\",\r\n \"jimeng-4.5\": \"3.3.4\",\r\n \"jimeng-4.1\": \"3.3.4\",\r\n \"jimeng-4.0\": \"3.3.4\",\r\n \"jimeng-3.1\": \"3.0.2\",\r\n \"jimeng-3.0\": \"3.0.2\",\r\n \"jimeng-2.1\": \"3.0.2\",\r\n \"jimeng-2.0-pro\": \"3.0.2\",\r\n \"jimeng-2.0\": \"3.0.2\",\r\n \"jimeng-1.4\": \"3.0.2\",\r\n \"jimeng-xl-pro\": \"3.0.2\",\r\n};\r\n\r\n// 获取模型对应的draft版本\r\nfunction getDraftVersion(model: string): string {\r\n try {\r\n const config = getModelConfig(model);\r\n return config.draftVersion;\r\n } catch (e) {\r\n // 如果配置中没有,使用旧的映射\r\n return MODEL_DRAFT_VERSIONS[model] || DRAFT_VERSION;\r\n }\r\n}\r\nconst MODEL_MAP = {\r\n \"jimeng-5.0\": \"high_aes_general_v50\",\r\n \"jimeng-4.6\": \"high_aes_general_v42\",\r\n \"jimeng-4.5\": \"high_aes_general_v40l\",\r\n \"jimeng-4.1\": \"high_aes_general_v41\",\r\n \"jimeng-4.0\": \"high_aes_general_v40\",\r\n \"jimeng-3.1\": \"high_aes_general_v30l_art_fangzhou:general_v3.0_18b\",\r\n \"jimeng-3.0\": \"high_aes_general_v30l:general_v3.0_18b\",\r\n \"jimeng-2.1\": \"high_aes_general_v21_L:general_v2.1_L\",\r\n \"jimeng-2.0-pro\": \"high_aes_general_v20_L:general_v2.0_L\",\r\n \"jimeng-2.0\": \"high_aes_general_v20:general_v2.0\",\r\n \"jimeng-1.4\": \"high_aes_general_v14:general_v1.4\",\r\n \"jimeng-xl-pro\": \"text2img_xl_sft\",\r\n};\r\n\r\n// 向后兼容的函数\r\nexport function getModel(model: string) {\r\n try {\r\n const config = getModelConfig(model);\r\n return config.internalModel;\r\n } catch (e) {\r\n // 如果配置中没有,使用旧的映射\r\n return MODEL_MAP[model] || MODEL_MAP[DEFAULT_MODEL];\r\n }\r\n}\r\n\r\n\r\n// AWS4-HMAC-SHA256 签名生成函数\r\nfunction createSignature(\r\n method: string,\r\n url: string,\r\n headers: { [key: string]: string },\r\n accessKeyId: string,\r\n secretAccessKey: string,\r\n sessionToken?: string,\r\n payload: string = ''\r\n) {\r\n const urlObj = new URL(url);\r\n const pathname = urlObj.pathname || '/';\r\n const search = urlObj.search;\r\n \r\n // 创建规范请求\r\n const timestamp = headers['x-amz-date'];\r\n const date = timestamp.substr(0, 8);\r\n const region = 'cn-north-1';\r\n const service = 'imagex';\r\n \r\n // 规范化查询参数 - 手动处理以确保正确的顺序\r\n const queryParams: Array<[string, string]> = [];\r\n const searchParams = new URLSearchParams(search);\r\n searchParams.forEach((value, key) => {\r\n queryParams.push([key, value]);\r\n });\r\n \r\n // 按键名排序 - 大小写敏感,先大写字母,后小写字母\r\n queryParams.sort(([a], [b]) => {\r\n // AWS要求大小写敏感的ASCII排序\r\n if (a < b) return -1;\r\n if (a > b) return 1;\r\n return 0;\r\n });\r\n \r\n // 构建规范查询字符串(不进行额外编码,因为URL中已经编码)\r\n const canonicalQueryString = queryParams\r\n .map(([key, value]) => `${key}=${value}`)\r\n .join('&');\r\n \r\n // 规范化头部 - 只包含必要的头部\r\n const headersToSign: { [key: string]: string } = {\r\n 'x-amz-date': timestamp\r\n };\r\n \r\n // 添加 session token\r\n if (sessionToken) {\r\n headersToSign['x-amz-security-token'] = sessionToken;\r\n }\r\n \r\n // 如果是POST请求且包含payload,添加content-sha256头\r\n let payloadHash = crypto.createHash('sha256').update('').digest('hex'); // 默认空payload\r\n if (method.toUpperCase() === 'POST' && payload) {\r\n payloadHash = crypto.createHash('sha256').update(payload, 'utf8').digest('hex');\r\n headersToSign['x-amz-content-sha256'] = payloadHash;\r\n }\r\n \r\n const signedHeaders = Object.keys(headersToSign)\r\n .map(key => key.toLowerCase())\r\n .sort()\r\n .join(';');\r\n \r\n const canonicalHeaders = Object.keys(headersToSign)\r\n .sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))\r\n .map(key => `${key.toLowerCase()}:${headersToSign[key].trim()}\\n`)\r\n .join('');\r\n \r\n // 创建规范请求\r\n const canonicalRequest = [\r\n method.toUpperCase(),\r\n pathname,\r\n canonicalQueryString,\r\n canonicalHeaders,\r\n signedHeaders,\r\n payloadHash\r\n ].join('\\n');\r\n \r\n // 调试输出\r\n logger.debug(`规范请求:\r\nMethod: ${method.toUpperCase()}\r\nPath: ${pathname}\r\nQuery: ${canonicalQueryString}\r\nHeaders: ${canonicalHeaders}\r\nSignedHeaders: ${signedHeaders}\r\nPayloadHash: ${payloadHash}\r\n---完整规范请求---\r\n${canonicalRequest}\r\n---结束---`);\r\n \r\n // 创建待签名字符串\r\n const credentialScope = `${date}/${region}/${service}/aws4_request`;\r\n const stringToSign = [\r\n 'AWS4-HMAC-SHA256',\r\n timestamp,\r\n credentialScope,\r\n crypto.createHash('sha256').update(canonicalRequest, 'utf8').digest('hex')\r\n ].join('\\n');\r\n \r\n logger.debug(`待签名字符串:\r\n${stringToSign}`);\r\n \r\n // 生成签名\r\n const kDate = crypto.createHmac('sha256', `AWS4${secretAccessKey}`).update(date).digest();\r\n const kRegion = crypto.createHmac('sha256', kDate).update(region).digest();\r\n const kService = crypto.createHmac('sha256', kRegion).update(service).digest();\r\n const kSigning = crypto.createHmac('sha256', kService).update('aws4_request').digest();\r\n const signature = crypto.createHmac('sha256', kSigning).update(stringToSign, 'utf8').digest('hex');\r\n \r\n return `AWS4-HMAC-SHA256 Credential=${accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;\r\n}\r\n\r\n// 计算文件的CRC32值\r\nfunction calculateCRC32(buffer: ArrayBuffer): string {\r\n const crcTable = [];\r\n for (let i = 0; i < 256; i++) {\r\n let crc = i;\r\n for (let j = 0; j < 8; j++) {\r\n crc = (crc & 1) ? (0xEDB88320 ^ (crc >>> 1)) : (crc >>> 1);\r\n }\r\n crcTable[i] = crc;\r\n }\r\n \r\n let crc = 0 ^ (-1);\r\n const bytes = new Uint8Array(buffer);\r\n for (let i = 0; i < bytes.length; i++) {\r\n crc = (crc >>> 8) ^ crcTable[(crc ^ bytes[i]) & 0xFF];\r\n }\r\n return ((crc ^ (-1)) >>> 0).toString(16).padStart(8, '0');\r\n}\r\n\r\n// 图片上传功能:将外部图片URL上传到即梦系统\r\nasync function uploadImageFromUrl(imageUrl: string, refreshToken: string): Promise<string> {\r\n try {\r\n logger.info(`开始上传图片: ${imageUrl}`);\r\n \r\n // 第一步:获取上传令牌\r\n const tokenResult = await request(\"post\", \"/mweb/v1/get_upload_token\", refreshToken, {\r\n data: {\r\n scene: 2, // AIGC 图片上传场景\r\n },\r\n });\r\n \r\n const { access_key_id, secret_access_key, session_token, service_id } = tokenResult;\r\n if (!access_key_id || !secret_access_key || !session_token) {\r\n throw new Error(\"获取上传令牌失败\");\r\n }\r\n \r\n // 使用固定的service_id\r\n const actualServiceId = service_id || \"tb4s082cfz\";\r\n \r\n logger.info(`获取上传令牌成功: service_id=${actualServiceId}`);\r\n \r\n // 下载图片数据\r\n const imageResponse = await fetch(imageUrl);\r\n if (!imageResponse.ok) {\r\n throw new Error(`下载图片失败: ${imageResponse.status}`);\r\n }\r\n \r\n const imageBuffer = await imageResponse.arrayBuffer();\r\n const fileSize = imageBuffer.byteLength;\r\n const crc32 = calculateCRC32(imageBuffer);\r\n \r\n logger.info(`图片下载完成: 大小=${fileSize}字节, CRC32=${crc32}`);\r\n \r\n // 第二步:申请图片上传权限\r\n // 使用UTC时间格式 YYYYMMDD'T'HHMMSS'Z'\r\n const now = new Date();\r\n const timestamp = now.toISOString().replace(/[:\\-]/g, '').replace(/\\.\\d{3}Z$/, 'Z');\r\n \r\n // 生成随机字符串作为签名参数\r\n const randomStr = Math.random().toString(36).substring(2, 12);\r\n // 保持原始的参数顺序(这是API期望的顺序)\r\n const applyUrl = `https://imagex.bytedanceapi.com/?Action=ApplyImageUpload&Version=2018-08-01&ServiceId=${actualServiceId}&FileSize=${fileSize}&s=${randomStr}`;\r\n \r\n logger.debug(`原始URL: ${applyUrl}`);\r\n \r\n // 构建AWS签名所需的头部\r\n const requestHeaders = {\r\n 'x-amz-date': timestamp,\r\n 'x-amz-security-token': session_token\r\n };\r\n \r\n // 生成AWS签名\r\n const authorization = createSignature('GET', applyUrl, requestHeaders, access_key_id, secret_access_key, session_token);\r\n \r\n // 调试日志\r\n logger.info(`AWS签名调试信息:\r\n URL: ${applyUrl}\r\n AccessKeyId: ${access_key_id}\r\n SessionToken: ${session_token ? '存在' : '不存在'}\r\n Timestamp: ${timestamp}\r\n Authorization: ${authorization}\r\n `);\r\n \r\n const applyResponse = await fetch(applyUrl, {\r\n method: 'GET',\r\n headers: {\r\n 'accept': '*/*',\r\n 'accept-language': 'zh-CN,zh;q=0.9',\r\n 'authorization': authorization,\r\n 'origin': 'https://jimeng.jianying.com',\r\n 'referer': 'https://jimeng.jianying.com/ai-tool/generate',\r\n 'sec-ch-ua': '\"Not A(Brand\";v=\"8\", \"Chromium\";v=\"132\", \"Google Chrome\";v=\"132\"',\r\n 'sec-ch-ua-mobile': '?0',\r\n 'sec-ch-ua-platform': '\"Windows\"',\r\n 'sec-fetch-dest': 'empty',\r\n 'sec-fetch-mode': 'cors',\r\n 'sec-fetch-site': 'cross-site',\r\n 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',\r\n 'x-amz-date': timestamp,\r\n 'x-amz-security-token': session_token,\r\n },\r\n });\r\n \r\n if (!applyResponse.ok) {\r\n const errorText = await applyResponse.text();\r\n throw new Error(`申请上传权限失败: ${applyResponse.status} - ${errorText}`);\r\n }\r\n \r\n const applyResult = await applyResponse.json();\r\n \r\n // 检查是否有错误\r\n if (applyResult?.ResponseMetadata?.Error) {\r\n throw new Error(`申请上传权限失败: ${JSON.stringify(applyResult.ResponseMetadata.Error)}`);\r\n }\r\n \r\n logger.info(`申请上传权限成功`);\r\n \r\n // 解析上传信息\r\n const uploadAddress = applyResult?.Result?.UploadAddress;\r\n if (!uploadAddress || !uploadAddress.StoreInfos || !uploadAddress.UploadHosts) {\r\n throw new Error(`获取上传地址失败: ${JSON.stringify(applyResult)}`);\r\n }\r\n \r\n const storeInfo = uploadAddress.StoreInfos[0];\r\n const uploadHost = uploadAddress.UploadHosts[0];\r\n const auth = storeInfo.Auth;\r\n \r\n // 构建上传URL \r\n const uploadUrl = `https://${uploadHost}/upload/v1/${storeInfo.StoreUri}`;\r\n \r\n // 提取图片ID (StoreUri最后一个斜杠后的部分)\r\n const imageId = storeInfo.StoreUri.split('/').pop();\r\n \r\n logger.info(`准备上传图片: imageId=${imageId}, uploadUrl=${uploadUrl}`);\r\n \r\n // 第三步:上传图片文件\r\n const uploadResponse = await fetch(uploadUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Accept': '*/*',\r\n 'Accept-Language': 'zh-CN,zh;q=0.9',\r\n 'Authorization': auth,\r\n 'Connection': 'keep-alive',\r\n 'Content-CRC32': crc32,\r\n 'Content-Disposition': 'attachment; filename=\"undefined\"',\r\n 'Content-Type': 'application/octet-stream',\r\n 'Origin': 'https://jimeng.jianying.com',\r\n 'Referer': 'https://jimeng.jianying.com/ai-tool/generate',\r\n 'Sec-Fetch-Dest': 'empty',\r\n 'Sec-Fetch-Mode': 'cors',\r\n 'Sec-Fetch-Site': 'cross-site',\r\n 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',\r\n 'X-Storage-U': '704135154117550', // 用户ID,可以从token或其他地方获取\r\n },\r\n body: imageBuffer,\r\n });\r\n \r\n if (!uploadResponse.ok) {\r\n const errorText = await uploadResponse.text();\r\n throw new Error(`图片上传失败: ${uploadResponse.status} - ${errorText}`);\r\n }\r\n \r\n logger.info(`图片文件上传成功`);\r\n \r\n // 第四步:提交上传\r\n const commitUrl = `https://imagex.bytedanceapi.com/?Action=CommitImageUpload&Version=2018-08-01&ServiceId=${actualServiceId}`;\r\n \r\n const commitTimestamp = new Date().toISOString().replace(/[:\\-]/g, '').replace(/\\.\\d{3}Z$/, 'Z');\r\n const commitPayload = JSON.stringify({\r\n SessionKey: uploadAddress.SessionKey,\r\n SuccessActionStatus: \"200\"\r\n });\r\n \r\n // 计算payload的SHA256哈希值\r\n const payloadHash = crypto.createHash('sha256').update(commitPayload, 'utf8').digest('hex');\r\n \r\n // 构建AWS签名所需的头部\r\n const commitRequestHeaders = {\r\n 'x-amz-date': commitTimestamp,\r\n 'x-amz-security-token': session_token,\r\n 'x-amz-content-sha256': payloadHash\r\n };\r\n \r\n // 生成AWS签名\r\n const commitAuthorization = createSignature('POST', commitUrl, commitRequestHeaders, access_key_id, secret_access_key, session_token, commitPayload);\r\n \r\n const commitResponse = await fetch(commitUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'accept': '*/*',\r\n 'accept-language': 'zh-CN,zh;q=0.9',\r\n 'authorization': commitAuthorization,\r\n 'content-type': 'application/json',\r\n 'origin': 'https://jimeng.jianying.com',\r\n 'referer': 'https://jimeng.jianying.com/ai-tool/generate',\r\n 'sec-ch-ua': '\"Not A(Brand\";v=\"8\", \"Chromium\";v=\"132\", \"Google Chrome\";v=\"132\"',\r\n 'sec-ch-ua-mobile': '?0',\r\n 'sec-ch-ua-platform': '\"Windows\"',\r\n 'sec-fetch-dest': 'empty',\r\n 'sec-fetch-mode': 'cors',\r\n 'sec-fetch-site': 'cross-site',\r\n 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',\r\n 'x-amz-date': commitTimestamp,\r\n 'x-amz-security-token': session_token,\r\n 'x-amz-content-sha256': payloadHash,\r\n },\r\n body: commitPayload,\r\n });\r\n \r\n if (!commitResponse.ok) {\r\n const errorText = await commitResponse.text();\r\n throw new Error(`提交上传失败: ${commitResponse.status} - ${errorText}`);\r\n }\r\n \r\n const commitResult = await commitResponse.json();\r\n \r\n // 检查提交结果\r\n if (commitResult?.ResponseMetadata?.Error) {\r\n throw new Error(`提交上传失败: ${JSON.stringify(commitResult.ResponseMetadata.Error)}`);\r\n }\r\n \r\n if (!commitResult?.Result?.Results || commitResult.Result.Results.length === 0) {\r\n throw new Error(`提交上传响应缺少结果: ${JSON.stringify(commitResult)}`);\r\n }\r\n \r\n const uploadResult = commitResult.Result.Results[0];\r\n if (uploadResult.UriStatus !== 2000) {\r\n throw new Error(`图片上传状态异常: UriStatus=${uploadResult.UriStatus}`);\r\n }\r\n \r\n // 获取完整的URI(包含前缀)\r\n const fullImageUri = uploadResult.Uri; // 如: \"tos-cn-i-tb4s082cfz/bab623359bd9410da0c1f07897b16fec\"\r\n \r\n // 验证图片信息\r\n const pluginResult = commitResult.Result?.PluginResult?.[0];\r\n if (pluginResult) {\r\n logger.info(`图片上传成功详情:`, {\r\n imageUri: pluginResult.ImageUri,\r\n sourceUri: pluginResult.SourceUri,\r\n size: `${pluginResult.ImageWidth}x${pluginResult.ImageHeight}`,\r\n format: pluginResult.ImageFormat,\r\n fileSize: pluginResult.ImageSize,\r\n md5: pluginResult.ImageMd5\r\n });\r\n \r\n // 优先使用PluginResult中的ImageUri,因为它可能是最准确的\r\n if (pluginResult.ImageUri) {\r\n logger.info(`图片上传完成: ${pluginResult.ImageUri}`);\r\n return pluginResult.ImageUri; // 返回完整的URI\r\n }\r\n }\r\n \r\n logger.info(`图片上传完成: ${fullImageUri}`);\r\n return fullImageUri; // 返回完整的URI\r\n\r\n } catch (error) {\r\n logger.error(`图片上传失败: ${error.message}`);\r\n throw error;\r\n }\r\n}\r\n\r\n// 从Buffer上传图片\r\nasync function uploadImageBuffer(buffer: Buffer, refreshToken: string): Promise<string> {\r\n try {\r\n logger.info(`开始从Buffer上传图片,大小: ${buffer.length}字节`);\r\n\r\n // 获取上传凭证\r\n const proofResult = await request(\r\n 'POST',\r\n '/mweb/v1/get_upload_image_proof',\r\n refreshToken,\r\n {\r\n data: {\r\n scene: 'aigc_image',\r\n file_name: `${util.uuid()}.jpg`,\r\n file_size: buffer.length,\r\n }\r\n }\r\n );\r\n\r\n if (!proofResult || !proofResult.proof_info) {\r\n logger.error(`获取上传凭证失败: ${JSON.stringify(proofResult)}`);\r\n throw new APIException(EX.API_REQUEST_FAILED, '获取上传凭证失败');\r\n }\r\n\r\n logger.info(`获取上传凭证成功`);\r\n\r\n // 上传文件\r\n const { proof_info } = proofResult;\r\n const uploadProofUrl = 'https://imagex.bytedanceapi.com/';\r\n\r\n const formData = new FormData();\r\n const blob = new Blob([buffer], { type: 'image/jpeg' });\r\n formData.append('file', blob, `${util.uuid()}.jpg`);\r\n\r\n const uploadResult = await fetch(uploadProofUrl + '?' + new URLSearchParams(proof_info.query_params).toString(), {\r\n method: 'POST',\r\n headers: proof_info.headers,\r\n body: formData,\r\n });\r\n\r\n if (!uploadResult.ok) {\r\n logger.error(`上传文件失败: 状态码 ${uploadResult.status}`);\r\n throw new APIException(EX.API_REQUEST_FAILED, `上传文件失败: 状态码 ${uploadResult.status}`);\r\n }\r\n\r\n // 验证 proof_info.image_uri 是否存在\r\n if (!proof_info.image_uri) {\r\n logger.error(`上传凭证中缺少 image_uri: ${JSON.stringify(proof_info)}`);\r\n throw new APIException(EX.API_REQUEST_FAILED, '上传凭证中缺少 image_uri');\r\n }\r\n\r\n logger.info(`Buffer图片上传成功: ${proof_info.image_uri}`);\r\n return proof_info.image_uri;\r\n } catch (error) {\r\n logger.error(`Buffer图片上传失败: ${error.message}`);\r\n throw error;\r\n }\r\n}\r\n\r\n// 图片合成功能:先上传图片,然后进行图生图\r\nexport async function generateImageComposition(\r\n _model: string,\r\n prompt: string,\r\n imageUrls: (string | Buffer)[],\r\n {\r\n ratio = \"1:1\",\r\n resolution = \"2k\",\r\n sampleStrength = 0.5,\r\n negativePrompt = \"\",\r\n intelligentRatio = false,\r\n }: {\r\n ratio?: string;\r\n resolution?: string;\r\n sampleStrength?: number;\r\n negativePrompt?: string;\r\n intelligentRatio?: boolean;\r\n },\r\n refreshToken: string\r\n) {\r\n const model = getModel(_model);\r\n const draftVersion = getDraftVersion(_model);\r\n const imageCount = imageUrls.length;\r\n\r\n // 解析分辨率\r\n const resolutionResult = resolveResolution(resolution, ratio);\r\n const { width, height, imageRatio, resolutionType } = resolutionResult;\r\n\r\n logger.info(`使用模型: ${_model} 映射模型: ${model} 图生图功能 ${imageCount}张图片 ${width}x${height} (${ratio}@${resolution}) 精细度: ${sampleStrength}`);\r\n\r\n const { totalCredit } = await getCredit(refreshToken);\r\n if (totalCredit <= 0)\r\n await receiveCredit(refreshToken);\r\n\r\n // 上传所有输入图片\r\n const uploadedImageIds: string[] = [];\r\n for (let i = 0; i < imageUrls.length; i++) {\r\n try {\r\n const image = imageUrls[i];\r\n let imageId: string;\r\n if (typeof image === 'string') {\r\n logger.info(`正在处理第 ${i + 1}/${imageCount} 张图片 (URL)...`);\r\n imageId = await uploadImageFromUrl(image, refreshToken);\r\n } else {\r\n logger.info(`正在处理第 ${i + 1}/${imageCount} 张图片 (Buffer)...`);\r\n imageId = await uploadImageBuffer(image, refreshToken);\r\n }\r\n uploadedImageIds.push(imageId);\r\n logger.info(`图片 ${i + 1}/${imageCount} 上传成功: ${imageId}`);\r\n } catch (error) {\r\n logger.error(`图片 ${i + 1}/${imageCount} 上传失败: ${error.message}`);\r\n throw new APIException(EX.API_IMAGE_GENERATION_FAILED, `图片上传失败: ${error.message}`);\r\n }\r\n }\r\n\r\n logger.info(`所有图片上传完成,开始图生图: ${uploadedImageIds.join(', ')}`);\r\n\r\n const componentId = util.uuid();\r\n const submitId = util.uuid();\r\n\r\n // 构建图生图的 sceneOptions(不包含 benefitCount 以避免扣积分)\r\n // 注意:sceneOptions 需要是对象,在 metrics_extra 中会被 JSON.stringify\r\n const sceneOption = {\r\n type: \"image\",\r\n scene: \"ImageBasicGenerate\",\r\n modelReqKey: _model,\r\n resolutionType,\r\n abilityList: uploadedImageIds.map(() => ({\r\n abilityName: \"byte_edit\",\r\n strength: sampleStrength,\r\n source: {\r\n imageUrl: `blob:https://jimeng.jianying.com/${util.uuid()}`\r\n }\r\n })),\r\n reportParams: {\r\n enterSource: \"generate\",\r\n vipSource: \"generate\",\r\n extraVipFunctionKey: `${_model}-${resolutionType}`,\r\n useVipFunctionDetailsReporterHoc: true,\r\n },\r\n };\r\n\r\n const { aigc_data } = await request(\r\n \"post\",\r\n \"/mweb/v1/aigc_draft/generate\",\r\n refreshToken,\r\n {\r\n data: {\r\n extend: {\r\n root_model: model,\r\n },\r\n submit_id: submitId,\r\n metrics_extra: JSON.stringify({\r\n promptSource: \"custom\",\r\n generateCount: 1,\r\n enterFrom: \"click\",\r\n sceneOptions: JSON.stringify([sceneOption]),\r\n generateId: submitId,\r\n isRegenerate: false\r\n }),\r\n draft_content: JSON.stringify({\r\n type: \"draft\",\r\n id: util.uuid(),\r\n min_version: \"3.2.9\",\r\n min_features: [],\r\n is_from_tsn: true,\r\n version: \"3.2.9\",\r\n main_component_id: componentId,\r\n component_list: [\r\n {\r\n type: \"image_base_component\",\r\n id: componentId,\r\n min_version: \"3.0.2\",\r\n aigc_mode: \"workbench\",\r\n metadata: {\r\n type: \"\",\r\n id: util.uuid(),\r\n created_platform: 3,\r\n created_platform_version: \"\",\r\n created_time_in_ms: Date.now().toString(),\r\n created_did: \"\",\r\n },\r\n generate_type: \"blend\",\r\n abilities: {\r\n type: \"\",\r\n id: util.uuid(),\r\n blend: {\r\n type: \"\",\r\n id: util.uuid(),\r\n min_version: \"3.2.9\",\r\n min_features: [],\r\n core_param: {\r\n type: \"\",\r\n id: util.uuid(),\r\n model,\r\n prompt: `${'#'.repeat(imageCount * 2)}${prompt}`,\r\n sample_strength: sampleStrength,\r\n image_ratio: imageRatio,\r\n large_image_info: {\r\n type: \"\",\r\n id: util.uuid(),\r\n height,\r\n width,\r\n resolution_type: resolutionType\r\n },\r\n intelligent_ratio: intelligentRatio,\r\n },\r\n ability_list: uploadedImageIds.map((imageId) => ({\r\n type: \"\",\r\n id: util.uuid(),\r\n name: \"byte_edit\",\r\n image_uri_list: [imageId],\r\n image_list: [{\r\n type: \"image\",\r\n id: util.uuid(),\r\n source_from: \"upload\",\r\n platform_type: 1,\r\n name: \"\",\r\n image_uri: imageId,\r\n width: 0,\r\n height: 0,\r\n format: \"\",\r\n uri: imageId\r\n }],\r\n strength: 0.5\r\n })),\r\n prompt_placeholder_info_list: uploadedImageIds.map((_, index) => ({\r\n type: \"\",\r\n id: util.uuid(),\r\n ability_index: index\r\n })),\r\n postedit_param: {\r\n type: \"\",\r\n id: util.uuid(),\r\n generate_type: 0\r\n }\r\n },\r\n },\r\n },\r\n ],\r\n }),\r\n http_common_info: {\r\n aid: DEFAULT_ASSISTANT_ID,\r\n },\r\n },\r\n }\r\n );\r\n\r\n const historyId = aigc_data?.history_record_id;\r\n if (!historyId)\r\n throw new APIException(EX.API_IMAGE_GENERATION_FAILED, \"记录ID不存在\");\r\n\r\n logger.info(`图生图任务已提交,history_id: ${historyId},等待生成完成...`);\r\n \r\n let status = 20, failCode, item_list = [];\r\n let pollCount = 0;\r\n const maxPollCount = 600; // 最多轮询10分钟\r\n\r\n while (pollCount < maxPollCount) {\r\n await new Promise((resolve) => setTimeout(resolve, 1000));\r\n pollCount++;\r\n \r\n if (pollCount % 30 === 0) {\r\n logger.info(`图生图进度: 第 ${pollCount} 次轮询 (history_id: ${historyId}),当前状态: ${status},已生成: ${item_list.length} 张图片...`);\r\n }\r\n\r\n const result = await request(\"post\", \"/mweb/v1/get_history_by_ids\", refreshToken, {\r\n data: {\r\n history_ids: [historyId],\r\n image_info: {\r\n width: 2048,\r\n height: 2048,\r\n format: \"webp\",\r\n image_scene_list: [\r\n {\r\n scene: \"smart_crop\",\r\n width: 360,\r\n height: 360,\r\n uniq_key: \"smart_crop-w:360-h:360\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"smart_crop\",\r\n width: 480,\r\n height: 480,\r\n uniq_key: \"smart_crop-w:480-h:480\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"smart_crop\",\r\n width: 720,\r\n height: 720,\r\n uniq_key: \"smart_crop-w:720-h:720\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"smart_crop\",\r\n width: 720,\r\n height: 480,\r\n uniq_key: \"smart_crop-w:720-h:480\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"normal\",\r\n width: 2400,\r\n height: 2400,\r\n uniq_key: \"2400\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"normal\",\r\n width: 1080,\r\n height: 1080,\r\n uniq_key: \"1080\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"normal\",\r\n width: 720,\r\n height: 720,\r\n uniq_key: \"720\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"normal\",\r\n width: 480,\r\n height: 480,\r\n uniq_key: \"480\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"normal\",\r\n width: 360,\r\n height: 360,\r\n uniq_key: \"360\",\r\n format: \"webp\",\r\n },\r\n ],\r\n },\r\n http_common_info: {\r\n aid: DEFAULT_ASSISTANT_ID,\r\n },\r\n },\r\n });\r\n\r\n if (!result[historyId])\r\n throw new APIException(EX.API_IMAGE_GENERATION_FAILED, \"记录不存在\");\r\n\r\n status = result[historyId].status;\r\n failCode = result[historyId].fail_code;\r\n item_list = result[historyId].item_list || [];\r\n\r\n // 检查是否已生成图片\r\n if (item_list.length > 0) {\r\n logger.info(`图生图完成: 状态=${status}, 已生成 ${item_list.length} 张图片`);\r\n break;\r\n }\r\n \r\n // 记录详细状态\r\n if (pollCount % 60 === 0) {\r\n logger.info(`图生图详细状态: status=${status}, item_list.length=${item_list.length}, failCode=${failCode || 'none'}`);\r\n }\r\n \r\n // 如果状态是完成但图片数量为0,记录并继续等待\r\n if (status === 10 && item_list.length === 0 && pollCount % 30 === 0) {\r\n logger.info(`图生图状态已完成但无图片生成: 状态=${status}, 继续等待...`);\r\n }\r\n }\r\n\r\n if (pollCount >= maxPollCount) {\r\n logger.warn(`图生图超时: 轮询了 ${pollCount} 次,当前状态: ${status},已生成图片数: ${item_list.length}`);\r\n }\r\n\r\n if (status === 30) {\r\n if (failCode === '2038')\r\n throw new APIException(EX.API_CONTENT_FILTERED);\r\n else\r\n throw new APIException(EX.API_IMAGE_GENERATION_FAILED, `图生图失败,错误代码: ${failCode}`);\r\n }\r\n\r\n const resultImageUrls = item_list.map((item) => {\r\n if(!item?.image?.large_images?.[0]?.image_url)\r\n return item?.common_attr?.cover_url || null;\r\n return item.image.large_images[0].image_url;\r\n }).filter(url => url !== null);\r\n\r\n logger.info(`图生图结果: 成功生成 ${resultImageUrls.length} 张图片`);\r\n return resultImageUrls;\r\n}\r\n\r\n// 多图生成函数(支持jimeng-4.0及以上版本)\r\nasync function generateMultiImages(\r\n _model: string,\r\n prompt: string,\r\n {\r\n ratio = \"1:1\",\r\n resolution = \"2k\",\r\n sampleStrength = 0.5,\r\n negativePrompt = \"\",\r\n intelligentRatio = false,\r\n }: {\r\n ratio?: string;\r\n resolution?: string;\r\n sampleStrength?: number;\r\n negativePrompt?: string;\r\n intelligentRatio?: boolean;\r\n },\r\n refreshToken: string\r\n) {\r\n const model = getModel(_model);\r\n\r\n // 解析分辨率\r\n const resolutionResult = resolveResolution(resolution, ratio);\r\n const { width, height, imageRatio, resolutionType } = resolutionResult;\r\n\r\n // 从prompt中提取图片数量,默认为4张\r\n const targetImageCount = prompt.match(/(\\d+)张/) ? parseInt(prompt.match(/(\\d+)张/)[1]) : 4;\r\n\r\n logger.info(`使用 ${_model} 多图生成: ${targetImageCount}张图片 ${width}x${height} (${ratio}@${resolution}) 精细度: ${sampleStrength}`);\r\n\r\n const componentId = util.uuid();\r\n const submitId = util.uuid();\r\n\r\n // 构建多图模式的 sceneOptions(不包含 benefitCount 以避免扣积分)\r\n const sceneOption = {\r\n type: \"image\",\r\n scene: \"ImageMultiGenerate\",\r\n modelReqKey: _model,\r\n resolutionType,\r\n abilityList: [],\r\n reportParams: {\r\n enterSource: \"generate\",\r\n vipSource: \"generate\",\r\n extraVipFunctionKey: `${_model}-${resolutionType}`,\r\n useVipFunctionDetailsReporterHoc: true,\r\n },\r\n };\r\n\r\n const { aigc_data } = await request(\r\n \"post\",\r\n \"/mweb/v1/aigc_draft/generate\",\r\n refreshToken,\r\n {\r\n data: {\r\n extend: {\r\n root_model: model,\r\n },\r\n submit_id: submitId,\r\n metrics_extra: JSON.stringify({\r\n promptSource: \"custom\",\r\n generateCount: 1,\r\n enterFrom: \"click\",\r\n sceneOptions: JSON.stringify([sceneOption]),\r\n generateId: submitId,\r\n isRegenerate: false,\r\n templateId: \"\",\r\n templateSource: \"\",\r\n lastRequestId: \"\",\r\n originRequestId: \"\",\r\n }),\r\n draft_content: JSON.stringify({\r\n type: \"draft\",\r\n id: util.uuid(),\r\n min_version: DRAFT_MIN_VERSION,\r\n min_features: [],\r\n is_from_tsn: true,\r\n version: DRAFT_VERSION,\r\n main_component_id: componentId,\r\n component_list: [\r\n {\r\n type: \"image_base_component\",\r\n id: componentId,\r\n min_version: DRAFT_MIN_VERSION,\r\n aigc_mode: \"workbench\",\r\n metadata: {\r\n type: \"\",\r\n id: util.uuid(),\r\n created_platform: 3,\r\n created_platform_version: \"\",\r\n created_time_in_ms: Date.now().toString(),\r\n created_did: \"\",\r\n },\r\n generate_type: \"generate\",\r\n abilities: {\r\n type: \"\",\r\n id: util.uuid(),\r\n generate: {\r\n type: \"\",\r\n id: util.uuid(),\r\n core_param: {\r\n type: \"\",\r\n id: util.uuid(),\r\n model,\r\n prompt,\r\n negative_prompt: negativePrompt,\r\n seed: Math.floor(Math.random() * 100000000) + 2500000000,\r\n sample_strength: sampleStrength,\r\n image_ratio: imageRatio,\r\n large_image_info: {\r\n type: \"\",\r\n id: util.uuid(),\r\n min_version: DRAFT_MIN_VERSION,\r\n height,\r\n width,\r\n resolution_type: resolutionType,\r\n },\r\n intelligent_ratio: intelligentRatio,\r\n },\r\n gen_option: {\r\n type: \"\",\r\n id: util.uuid(),\r\n generate_all: false,\r\n },\r\n },\r\n },\r\n },\r\n ],\r\n }),\r\n http_common_info: {\r\n aid: DEFAULT_ASSISTANT_ID,\r\n },\r\n },\r\n }\r\n );\r\n\r\n const historyId = aigc_data?.history_record_id;\r\n if (!historyId)\r\n throw new APIException(EX.API_IMAGE_GENERATION_FAILED, \"记录ID不存在\");\r\n\r\n logger.info(`多图生成任务已提交,submit_id: ${submitId}, history_id: ${historyId},等待生成 ${targetImageCount} 张图片...`);\r\n\r\n // 直接使用 history_id 轮询生成结果(增加轮询时间)\r\n let status = 20, failCode, item_list = [];\r\n let pollCount = 0;\r\n const maxPollCount = 600; // 最多轮询10分钟(600次 * 1秒)\r\n\r\n while (pollCount < maxPollCount) {\r\n await new Promise((resolve) => setTimeout(resolve, 1000)); // 每1秒轮询一次\r\n pollCount++;\r\n \r\n if (pollCount % 30 === 0) {\r\n logger.info(`多图生成进度: 第 ${pollCount} 次轮询 (history_id: ${historyId}),当前状态: ${status},已生成: ${item_list.length}/${targetImageCount} 张图片...`);\r\n }\r\n\r\n const result = await request(\"post\", \"/mweb/v1/get_history_by_ids\", refreshToken, {\r\n data: {\r\n history_ids: [historyId],\r\n image_info: {\r\n width: 2048,\r\n height: 2048,\r\n format: \"webp\",\r\n image_scene_list: [\r\n {\r\n scene: \"smart_crop\",\r\n width: 360,\r\n height: 360,\r\n uniq_key: \"smart_crop-w:360-h:360\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"smart_crop\",\r\n width: 480,\r\n height: 480,\r\n uniq_key: \"smart_crop-w:480-h:480\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"smart_crop\",\r\n width: 720,\r\n height: 720,\r\n uniq_key: \"smart_crop-w:720-h:720\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"smart_crop\",\r\n width: 720,\r\n height: 480,\r\n uniq_key: \"smart_crop-w:720-h:480\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"normal\",\r\n width: 2400,\r\n height: 2400,\r\n uniq_key: \"2400\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"normal\",\r\n width: 1080,\r\n height: 1080,\r\n uniq_key: \"1080\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"normal\",\r\n width: 720,\r\n height: 720,\r\n uniq_key: \"720\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"normal\",\r\n width: 480,\r\n height: 480,\r\n uniq_key: \"480\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"normal\",\r\n width: 360,\r\n height: 360,\r\n uniq_key: \"360\",\r\n format: \"webp\",\r\n },\r\n ],\r\n },\r\n http_common_info: {\r\n aid: DEFAULT_ASSISTANT_ID,\r\n },\r\n },\r\n });\r\n\r\n if (!result[historyId])\r\n throw new APIException(EX.API_IMAGE_GENERATION_FAILED, \"记录不存在\");\r\n\r\n status = result[historyId].status;\r\n failCode = result[historyId].fail_code;\r\n item_list = result[historyId].item_list || [];\r\n\r\n // 检查是否已生成足够的图片\r\n if (item_list.length >= targetImageCount) {\r\n logger.info(`多图生成完成: 状态=${status}, 已生成 ${item_list.length} 张图片`);\r\n break;\r\n }\r\n \r\n // 记录详细状态\r\n if (pollCount % 60 === 0) {\r\n logger.info(`jimeng-4.0 详细状态: status=${status}, item_list.length=${item_list.length}, failCode=${failCode || 'none'}`);\r\n }\r\n \r\n // 如果状态是完成但图片数量不够,记录并继续等待\r\n if (status === 10 && item_list.length < targetImageCount && pollCount % 30 === 0) {\r\n logger.info(`jimeng-4.0 状态已完成但图片数量不足: 状态=${status}, 已生成 ${item_list.length}/${targetImageCount} 张图片,继续等待...`);\r\n }\r\n }\r\n\r\n if (pollCount >= maxPollCount) {\r\n logger.warn(`多图生成超时: 轮询了 ${pollCount} 次,当前状态: ${status},已生成图片数: ${item_list.length}`);\r\n }\r\n\r\n if (status === 30) {\r\n if (failCode === '2038')\r\n throw new APIException(EX.API_CONTENT_FILTERED);\r\n else\r\n throw new APIException(EX.API_IMAGE_GENERATION_FAILED, `生成失败,错误代码: ${failCode}`);\r\n }\r\n\r\n const imageUrls = item_list.map((item) => {\r\n if(!item?.image?.large_images?.[0]?.image_url)\r\n return item?.common_attr?.cover_url || null;\r\n return item.image.large_images[0].image_url;\r\n }).filter(url => url !== null);\r\n\r\n logger.info(`多图生成结果: 成功生成 ${imageUrls.length} 张图片`);\r\n return imageUrls;\r\n}\r\n\r\nexport async function generateImages(\r\n _model: string,\r\n prompt: string,\r\n {\r\n ratio = \"1:1\",\r\n resolution = \"2k\",\r\n sampleStrength = 0.5,\r\n negativePrompt = \"\",\r\n intelligentRatio = false,\r\n }: {\r\n ratio?: string;\r\n resolution?: string;\r\n sampleStrength?: number;\r\n negativePrompt?: string;\r\n intelligentRatio?: boolean;\r\n },\r\n refreshToken: string\r\n) {\r\n const model = getModel(_model);\r\n\r\n // 解析分辨率\r\n const resolutionResult = resolveResolution(resolution, ratio);\r\n const { width, height, imageRatio, resolutionType } = resolutionResult;\r\n\r\n logger.info(`使用模型: ${_model} 映射模型: ${model} ${width}x${height} (${ratio}@${resolution}) 精细度: ${sampleStrength}`);\r\n\r\n\r\n const { totalCredit } = await getCredit(refreshToken);\r\n if (totalCredit <= 0)\r\n await receiveCredit(refreshToken);\r\n\r\n // 检测是否为多图生成请求\r\n const isMultiImageRequest = (/jimeng-[45]\\.[0-9]/.test(_model)) && (\r\n prompt.includes(\"连续\") ||\r\n prompt.includes(\"绘本\") ||\r\n prompt.includes(\"故事\") ||\r\n /\\d+张/.test(prompt)\r\n );\r\n\r\n // 如果是多图请求,使用专门的处理逻辑\r\n if (isMultiImageRequest) {\r\n return await generateMultiImages(_model, prompt, { ratio, resolution, sampleStrength, negativePrompt, intelligentRatio }, refreshToken);\r\n }\r\n\r\n const componentId = util.uuid();\r\n const submitId = util.uuid();\r\n\r\n // 构建 sceneOptions 用于 metrics_extra(不包含 benefitCount 以避免扣积分)\r\n const sceneOption = {\r\n type: \"image\",\r\n scene: \"ImageBasicGenerate\",\r\n modelReqKey: _model,\r\n resolutionType,\r\n abilityList: [],\r\n reportParams: {\r\n enterSource: \"generate\",\r\n vipSource: \"generate\",\r\n extraVipFunctionKey: `${_model}-${resolutionType}`,\r\n useVipFunctionDetailsReporterHoc: true,\r\n },\r\n };\r\n\r\n const { aigc_data } = await request(\r\n \"post\",\r\n \"/mweb/v1/aigc_draft/generate\",\r\n refreshToken,\r\n {\r\n data: {\r\n extend: {\r\n root_model: model,\r\n },\r\n submit_id: submitId,\r\n metrics_extra: JSON.stringify({\r\n promptSource: \"custom\",\r\n generateCount: 1,\r\n enterFrom: \"click\",\r\n sceneOptions: JSON.stringify([sceneOption]),\r\n generateId: submitId,\r\n isRegenerate: false,\r\n }),\r\n draft_content: JSON.stringify({\r\n type: \"draft\",\r\n id: util.uuid(),\r\n min_version: DRAFT_MIN_VERSION,\r\n min_features: [],\r\n is_from_tsn: true,\r\n version: DRAFT_VERSION,\r\n main_component_id: componentId,\r\n component_list: [\r\n {\r\n type: \"image_base_component\",\r\n id: componentId,\r\n min_version: DRAFT_MIN_VERSION,\r\n aigc_mode: \"workbench\",\r\n metadata: {\r\n type: \"\",\r\n id: util.uuid(),\r\n created_platform: 3,\r\n created_platform_version: \"\",\r\n created_time_in_ms: Date.now().toString(),\r\n created_did: \"\",\r\n },\r\n generate_type: \"generate\",\r\n abilities: {\r\n type: \"\",\r\n id: util.uuid(),\r\n generate: {\r\n type: \"\",\r\n id: util.uuid(),\r\n core_param: {\r\n type: \"\",\r\n id: util.uuid(),\r\n model,\r\n prompt,\r\n negative_prompt: negativePrompt,\r\n seed: Math.floor(Math.random() * 100000000) + 2500000000,\r\n sample_strength: sampleStrength,\r\n image_ratio: imageRatio,\r\n large_image_info: {\r\n type: \"\",\r\n id: util.uuid(),\r\n min_version: DRAFT_MIN_VERSION,\r\n height,\r\n width,\r\n resolution_type: resolutionType,\r\n },\r\n intelligent_ratio: intelligentRatio,\r\n },\r\n gen_option: {\r\n type: \"\",\r\n id: util.uuid(),\r\n generate_all: false,\r\n },\r\n },\r\n },\r\n },\r\n ],\r\n }),\r\n http_common_info: {\r\n aid: DEFAULT_ASSISTANT_ID,\r\n },\r\n },\r\n }\r\n );\r\n const historyId = aigc_data.history_record_id;\r\n if (!historyId)\r\n throw new APIException(EX.API_IMAGE_GENERATION_FAILED, \"记录ID不存在\");\r\n\r\n logger.info(`文生图任务已提交,submit_id: ${submitId}, history_id: ${historyId},等待生成完成...`);\r\n\r\n let status = 20, failCode, item_list = [];\r\n let pollCount = 0;\r\n const maxPollCount = 600; // 最多轮询10分钟\r\n\r\n while (pollCount < maxPollCount) {\r\n await new Promise((resolve) => setTimeout(resolve, 1000));\r\n pollCount++;\r\n\r\n if (pollCount % 30 === 0) {\r\n logger.info(`文生图进度: 第 ${pollCount} 次轮询 (history_id: ${historyId}),当前状态: ${status},已生成: ${item_list.length} 张图片...`);\r\n }\r\n\r\n const result = await request(\"post\", \"/mweb/v1/get_history_by_ids\", refreshToken, {\r\n data: {\r\n history_ids: [historyId],\r\n image_info: {\r\n width: 2048,\r\n height: 2048,\r\n format: \"webp\",\r\n image_scene_list: [\r\n {\r\n scene: \"smart_crop\",\r\n width: 360,\r\n height: 360,\r\n uniq_key: \"smart_crop-w:360-h:360\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"smart_crop\",\r\n width: 480,\r\n height: 480,\r\n uniq_key: \"smart_crop-w:480-h:480\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"smart_crop\",\r\n width: 720,\r\n height: 720,\r\n uniq_key: \"smart_crop-w:720-h:720\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"smart_crop\",\r\n width: 720,\r\n height: 480,\r\n uniq_key: \"smart_crop-w:720-h:480\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"smart_crop\",\r\n width: 360,\r\n height: 240,\r\n uniq_key: \"smart_crop-w:360-h:240\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"smart_crop\",\r\n width: 240,\r\n height: 320,\r\n uniq_key: \"smart_crop-w:240-h:320\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"smart_crop\",\r\n width: 480,\r\n height: 640,\r\n uniq_key: \"smart_crop-w:480-h:640\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"normal\",\r\n width: 2400,\r\n height: 2400,\r\n uniq_key: \"2400\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"normal\",\r\n width: 1080,\r\n height: 1080,\r\n uniq_key: \"1080\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"normal\",\r\n width: 720,\r\n height: 720,\r\n uniq_key: \"720\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"normal\",\r\n width: 480,\r\n height: 480,\r\n uniq_key: \"480\",\r\n format: \"webp\",\r\n },\r\n {\r\n scene: \"normal\",\r\n width: 360,\r\n height: 360,\r\n uniq_key: \"360\",\r\n format: \"webp\",\r\n },\r\n ],\r\n },\r\n http_common_info: {\r\n aid: DEFAULT_ASSISTANT_ID,\r\n },\r\n },\r\n });\r\n if (!result[historyId])\r\n throw new APIException(EX.API_IMAGE_GENERATION_FAILED, \"记录不存在\");\r\n\r\n status = result[historyId].status;\r\n failCode = result[historyId].fail_code;\r\n item_list = result[historyId].item_list || [];\r\n\r\n // 检查是否已生成图片\r\n if (item_list.length > 0) {\r\n logger.info(`文生图完成: 状态=${status}, 已生成 ${item_list.length} 张图片`);\r\n break;\r\n }\r\n\r\n // 记录详细状态\r\n if (pollCount % 60 === 0) {\r\n logger.info(`文生图详细状态: status=${status}, item_list.length=${item_list.length}, failCode=${failCode || 'none'}`);\r\n }\r\n\r\n // 如果状态是完成但图片数量为0,记录并继续等待\r\n if (status === 10 && item_list.length === 0 && pollCount % 30 === 0) {\r\n logger.info(`文生图状态已完成但无图片生成: 状态=${status}, 继续等待...`);\r\n }\r\n }\r\n\r\n if (pollCount >= maxPollCount) {\r\n logger.warn(`文生图超时: 轮询了 ${pollCount} 次,当前状态: ${status},已生成图片数: ${item_list.length}`);\r\n }\r\n\r\n if (status === 30) {\r\n if (failCode === '2038')\r\n throw new APIException(EX.API_CONTENT_FILTERED);\r\n else\r\n throw new APIException(EX.API_IMAGE_GENERATION_FAILED);\r\n }\r\n\r\n const imageUrls = item_list.map((item) => {\r\n if(!item?.image?.large_images?.[0]?.image_url)\r\n return item?.common_attr?.cover_url || null;\r\n return item.image.large_images[0].image_url;\r\n }).filter(url => url !== null);\r\n\r\n logger.info(`文生图结果: 成功生成 ${imageUrls.length} 张图片`);\r\n return imageUrls;\r\n}\r\n\r\nexport default {\r\n generateImages,\r\n generateImageComposition,\r\n};\r\n","/**\r\n * 模型配置文件\r\n * 定义不同模型的特定参数和配置\r\n */\r\n\r\nexport interface ModelConfig {\r\n // 模型内部名称\r\n internalModel: string;\r\n // draft版本\r\n draftVersion: string;\r\n // 支持的功能\r\n features: {\r\n // 是否支持多图生成\r\n multiImage: boolean;\r\n // 是否支持图生图\r\n imageToImage: boolean;\r\n // 是否支持视频生成\r\n videoGeneration: boolean;\r\n };\r\n // 默认参数\r\n defaultParams: {\r\n // 默认宽度\r\n width: number;\r\n // 默认高度\r\n height: number;\r\n // 支持的分辨率列表\r\n resolutions: Array<{ width: number; height: number }>;\r\n // 采样强度范围\r\n sampleStrengthRange: [number, number];\r\n };\r\n // 特殊配置\r\n specialConfig?: {\r\n // 是否需要特定的头部信息\r\n specialHeaders?: Record<string, string>;\r\n // 是否有特殊的参数要求\r\n extraParams?: Record<string, any>;\r\n };\r\n}\r\n\r\n// 模型配置映射\r\nexport const MODEL_CONFIGS: Record<string, ModelConfig> = {\r\n \"jimeng-5.0\": {\r\n internalModel: \"high_aes_general_v50\",\r\n draftVersion: \"3.3.9\",\r\n features: {\r\n multiImage: true,\r\n imageToImage: true,\r\n videoGeneration: false,\r\n },\r\n defaultParams: {\r\n width: 2048,\r\n height: 2048,\r\n resolutions: [\r\n { width: 1024, height: 1024 },\r\n { width: 768, height: 1024 },\r\n { width: 1024, height: 768 },\r\n { width: 1024, height: 576 },\r\n { width: 576, height: 1024 },\r\n { width: 1024, height: 682 },\r\n { width: 682, height: 1024 },\r\n { width: 1195, height: 512 },\r\n { width: 2048, height: 2048 },\r\n { width: 2304, height: 1728 },\r\n { width: 1728, height: 2304 },\r\n { width: 2560, height: 1440 },\r\n { width: 1440, height: 2560 },\r\n { width: 2496, height: 1664 },\r\n { width: 1664, height: 2496 },\r\n { width: 3024, height: 1296 },\r\n ],\r\n sampleStrengthRange: [0.1, 1.0],\r\n },\r\n },\r\n \"jimeng-4.6\": {\r\n internalModel: \"high_aes_general_v42\",\r\n draftVersion: \"3.3.9\",\r\n features: {\r\n multiImage: true,\r\n imageToImage: true,\r\n videoGeneration: false,\r\n },\r\n defaultParams: {\r\n width: 2048,\r\n height: 2048,\r\n resolutions: [\r\n { width: 1024, height: 1024 },\r\n { width: 768, height: 1024 },\r\n { width: 1024, height: 768 },\r\n { width: 1024, height: 576 },\r\n { width: 576, height: 1024 },\r\n { width: 1024, height: 682 },\r\n { width: 682, height: 1024 },\r\n { width: 1195, height: 512 },\r\n { width: 2048, height: 2048 },\r\n { width: 2304, height: 1728 },\r\n { width: 1728, height: 2304 },\r\n { width: 2560, height: 1440 },\r\n { width: 1440, height: 2560 },\r\n { width: 2496, height: 1664 },\r\n { width: 1664, height: 2496 },\r\n { width: 3024, height: 1296 },\r\n ],\r\n sampleStrengthRange: [0.1, 1.0],\r\n },\r\n },\r\n \"jimeng-video-3.5-pro\": {\r\n internalModel: \"dreamina_ic_generate_video_model_vgfm_3.5_pro\",\r\n draftVersion: \"3.3.4\",\r\n features: {\r\n multiImage: false,\r\n imageToImage: true,\r\n videoGeneration: true,\r\n },\r\n defaultParams: {\r\n width: 1280,\r\n height: 720,\r\n resolutions: [\r\n { width: 1280, height: 720 },\r\n { width: 720, height: 1280 },\r\n { width: 1080, height: 1080 },\r\n { width: 1920, height: 1080 },\r\n { width: 1080, height: 1920 },\r\n ],\r\n sampleStrengthRange: [0.1, 1.0],\r\n },\r\n },\r\n \"jimeng-4.5\": {\r\n internalModel: \"high_aes_general_v40l\",\r\n draftVersion: \"3.3.4\",\r\n features: {\r\n multiImage: true,\r\n imageToImage: true,\r\n videoGeneration: false,\r\n },\r\n defaultParams: {\r\n width: 2048,\r\n height: 2048,\r\n resolutions: [\r\n { width: 1024, height: 1024 },\r\n { width: 768, height: 1024 },\r\n { width: 1024, height: 768 },\r\n { width: 1024, height: 576 },\r\n { width: 576, height: 1024 },\r\n { width: 1024, height: 682 },\r\n { width: 682, height: 1024 },\r\n { width: 1195, height: 512 },\r\n { width: 2048, height: 2048 },\r\n { width: 2304, height: 1728 },\r\n { width: 1728, height: 2304 },\r\n { width: 2560, height: 1440 },\r\n { width: 1440, height: 2560 },\r\n { width: 2496, height: 1664 },\r\n { width: 1664, height: 2496 },\r\n { width: 3024, height: 1296 },\r\n ],\r\n sampleStrengthRange: [0.1, 1.0],\r\n },\r\n },\r\n \"jimeng-4.1\": {\r\n internalModel: \"high_aes_general_v41\",\r\n draftVersion: \"3.3.4\",\r\n features: {\r\n multiImage: true,\r\n imageToImage: true,\r\n videoGeneration: false,\r\n },\r\n defaultParams: {\r\n width: 2048,\r\n height: 2048,\r\n resolutions: [\r\n { width: 1024, height: 1024 },\r\n { width: 768, height: 1024 },\r\n { width: 1024, height: 768 },\r\n { width: 1024, height: 576 },\r\n { width: 576, height: 1024 },\r\n { width: 1024, height: 682 },\r\n { width: 682, height: 1024 },\r\n { width: 1195, height: 512 },\r\n { width: 2048, height: 2048 },\r\n { width: 2304, height: 1728 },\r\n { width: 1728, height: 2304 },\r\n { width: 2560, height: 1440 },\r\n { width: 1440, height: 2560 },\r\n { width: 2496, height: 1664 },\r\n { width: 1664, height: 2496 },\r\n { width: 3024, height: 1296 },\r\n ],\r\n sampleStrengthRange: [0.1, 1.0],\r\n },\r\n },\r\n \"jimeng-4.0\": {\r\n internalModel: \"high_aes_general_v40\",\r\n draftVersion: \"3.3.4\",\r\n features: {\r\n multiImage: true,\r\n imageToImage: true,\r\n videoGeneration: false,\r\n },\r\n defaultParams: {\r\n width: 2048,\r\n height: 2048,\r\n resolutions: [\r\n { width: 1024, height: 1024 },\r\n { width: 768, height: 1024 },\r\n { width: 1024, height: 768 },\r\n { width: 1024, height: 576 },\r\n { width: 576, height: 1024 },\r\n { width: 1024, height: 682 },\r\n { width: 682, height: 1024 },\r\n { width: 1195, height: 512 },\r\n { width: 2048, height: 2048 },\r\n { width: 2304, height: 1728 },\r\n { width: 1728, height: 2304 },\r\n { width: 2560, height: 1440 },\r\n { width: 1440, height: 2560 },\r\n { width: 2496, height: 1664 },\r\n { width: 1664, height: 2496 },\r\n { width: 3024, height: 1296 },\r\n ],\r\n sampleStrengthRange: [0.1, 1.0],\r\n },\r\n },\r\n \"jimeng-3.1\": {\r\n internalModel: \"high_aes_general_v30l_art_fangzhou:general_v3.0_18b\",\r\n draftVersion: \"3.0.2\",\r\n features: {\r\n multiImage: false,\r\n imageToImage: true,\r\n videoGeneration: false,\r\n },\r\n defaultParams: {\r\n width: 1024,\r\n height: 1024,\r\n resolutions: [\r\n { width: 512, height: 512 },\r\n { width: 768, height: 768 },\r\n { width: 1024, height: 1024 },\r\n ],\r\n sampleStrengthRange: [0.1, 0.8],\r\n },\r\n },\r\n \"jimeng-3.0\": {\r\n internalModel: \"high_aes_general_v30l:general_v3.0_18b\",\r\n draftVersion: \"3.0.2\",\r\n features: {\r\n multiImage: false,\r\n imageToImage: true,\r\n videoGeneration: false,\r\n },\r\n defaultParams: {\r\n width: 1024,\r\n height: 1024,\r\n resolutions: [\r\n { width: 512, height: 512 },\r\n { width: 768, height: 768 },\r\n { width: 1024, height: 1024 },\r\n ],\r\n sampleStrengthRange: [0.1, 0.8],\r\n },\r\n },\r\n \"jimeng-2.1\": {\r\n internalModel: \"high_aes_general_v21_L:general_v2.1_L\",\r\n draftVersion: \"3.0.2\",\r\n features: {\r\n multiImage: false,\r\n imageToImage: true,\r\n videoGeneration: false,\r\n },\r\n defaultParams: {\r\n width: 512,\r\n height: 512,\r\n resolutions: [\r\n { width: 512, height: 512 },\r\n { width: 768, height: 768 },\r\n ],\r\n sampleStrengthRange: [0.1, 0.7],\r\n },\r\n },\r\n \"jimeng-2.0-pro\": {\r\n internalModel: \"high_aes_general_v20_L:general_v2.0_L\",\r\n draftVersion: \"3.0.2\",\r\n features: {\r\n multiImage: false,\r\n imageToImage: true,\r\n videoGeneration: false,\r\n },\r\n defaultParams: {\r\n width: 512,\r\n height: 512,\r\n resolutions: [\r\n { width: 512, height: 512 },\r\n { width: 768, height: 768 },\r\n ],\r\n sampleStrengthRange: [0.1, 0.7],\r\n },\r\n },\r\n \"jimeng-2.0\": {\r\n internalModel: \"high_aes_general_v20\",\r\n draftVersion: \"3.0.2\",\r\n features: {\r\n multiImage: false,\r\n imageToImage: true,\r\n videoGeneration: false,\r\n },\r\n defaultParams: {\r\n width: 512,\r\n height: 512,\r\n resolutions: [\r\n { width: 512, height: 512 },\r\n { width: 768, height: 768 },\r\n ],\r\n sampleStrengthRange: [0.1, 0.7],\r\n },\r\n },\r\n \"jimeng-1.4\": {\r\n internalModel: \"high_aes_general_v14:general_v1.4\",\r\n draftVersion: \"3.0.2\",\r\n features: {\r\n multiImage: false,\r\n imageToImage: true,\r\n videoGeneration: false,\r\n },\r\n defaultParams: {\r\n width: 512,\r\n height: 512,\r\n resolutions: [\r\n { width: 512, height: 512 },\r\n { width: 768, height: 768 },\r\n ],\r\n sampleStrengthRange: [0.1, 0.6],\r\n },\r\n },\r\n \"jimeng-xl-pro\": {\r\n internalModel: \"text2img_xl_sft\",\r\n draftVersion: \"3.0.2\",\r\n features: {\r\n multiImage: false,\r\n imageToImage: true,\r\n videoGeneration: false,\r\n },\r\n defaultParams: {\r\n width: 1024,\r\n height: 1024,\r\n resolutions: [\r\n { width: 1024, height: 1024 },\r\n { width: 1280, height: 720 },\r\n { width: 720, height: 1280 },\r\n ],\r\n sampleStrengthRange: [0.1, 0.8],\r\n },\r\n },\r\n};\r\n\r\n// 获取模型配置\r\nexport function getModelConfig(modelName: string): ModelConfig {\r\n const config = MODEL_CONFIGS[modelName];\r\n if (!config) {\r\n throw new Error(`Unsupported model: ${modelName}`);\r\n }\r\n return config;\r\n}\r\n\r\n// 获取所有支持的图像生成模型\r\nexport function getSupportedImageModels(): string[] {\r\n return Object.keys(MODEL_CONFIGS);\r\n}\r\n\r\n// 检查模型是否支持特定功能\r\nexport function doesModelSupport(modelName: string, feature: keyof ModelConfig['features']): boolean {\r\n const config = getModelConfig(modelName);\r\n return config.features[feature];\r\n}\r\n\r\n// 验证参数是否在模型支持的范围内\r\nexport function validateModelParams(modelName: string, params: {\r\n width?: number;\r\n height?: number;\r\n sampleStrength?: number;\r\n}): { isValid: boolean; errors: string[] } {\r\n const config = getModelConfig(modelName);\r\n const errors: string[] = [];\r\n\r\n // 验证分辨率\r\n if (params.width && params.height) {\r\n const isValidResolution = config.defaultParams.resolutions.some(\r\n res => res.width === params.width && res.height === params.height\r\n );\r\n if (!isValidResolution) {\r\n errors.push(\r\n `Unsupported resolution ${params.width}x${params.height}. Supported resolutions: ${config.defaultParams.resolutions.map(r => `${r.width}x${r.height}`).join(', ')}`\r\n );\r\n }\r\n }\r\n\r\n // 验证采样强度\r\n if (params.sampleStrength !== undefined) {\r\n const [min, max] = config.defaultParams.sampleStrengthRange;\r\n if (params.sampleStrength < min || params.sampleStrength > max) {\r\n errors.push(`Sample strength must be between ${min} and ${max}`);\r\n }\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}","import _ from 'lodash';\r\n\r\nimport Request from '@/lib/request/Request.ts';\r\nimport Response from '@/lib/response/Response.ts';\r\nimport { tokenSplit } from '@/api/controllers/core.ts';\r\nimport { createCompletion, createCompletionStream } from '@/api/controllers/chat.ts';\r\n\r\nexport default {\r\n\r\n prefix: '/v1/chat',\r\n\r\n post: {\r\n\r\n '/completions': async (request: Request) => {\r\n request\r\n .validate('body.model', v => _.isUndefined(v) || _.isString(v))\r\n .validate('body.messages', _.isArray)\r\n .validate('headers.authorization', _.isString)\r\n // refresh_token切分\r\n const tokens = tokenSplit(request.headers.authorization);\r\n // 随机挑选一个refresh_token\r\n const token = _.sample(tokens);\r\n const { model, messages, stream } = request.body;\r\n if (stream) {\r\n const stream = await createCompletionStream(messages, token, model);\r\n return new Response(stream, {\r\n type: \"text/event-stream\"\r\n });\r\n }\r\n else\r\n return await createCompletion(messages, token, model);\r\n }\r\n\r\n }\r\n\r\n}","import _ from \"lodash\";\r\nimport { PassThrough } from \"stream\";\r\n\r\nimport APIException from \"@/lib/exceptions/APIException.ts\";\r\nimport EX from \"@/api/consts/exceptions.ts\";\r\nimport logger from \"@/lib/logger.ts\";\r\nimport util from \"@/lib/util.ts\";\r\nimport { generateImages, DEFAULT_MODEL } from \"./images.ts\";\r\nimport { generateVideo, generateSeedanceVideo, isSeedanceModel, DEFAULT_MODEL as DEFAULT_VIDEO_MODEL } from \"./videos.ts\";\r\n\r\n// 最大重试次数\r\nconst MAX_RETRY_COUNT = 3;\r\n// 重试延迟\r\nconst RETRY_DELAY = 5000;\r\n\r\n/**\r\n * 解析模型\r\n *\r\n * @param model 模型名称\r\n * @returns 模型信息\r\n */\r\nfunction parseModel(model: string) {\r\n const [_model, size] = model.split(\":\");\r\n const [_, width, height] = /(\\d+)[\\W\\w](\\d+)/.exec(size) ?? [];\r\n return {\r\n model: _model,\r\n width: size ? Math.ceil(parseInt(width) / 2) * 2 : 1024,\r\n height: size ? Math.ceil(parseInt(height) / 2) * 2 : 1024,\r\n };\r\n}\r\n\r\n/**\r\n * 检测是否为视频生成请求\r\n *\r\n * @param model 模型名称\r\n * @returns 是否为视频生成请求\r\n */\r\nfunction isVideoModel(model: string) {\r\n return model.startsWith(\"jimeng-video\") || model.startsWith(\"seedance-\");\r\n}\r\n\r\n/**\r\n * 同步对话补全\r\n *\r\n * @param messages 参考gpt系列消息格式,多轮对话请完整提供上下文\r\n * @param refreshToken 用于刷新access_token的refresh_token\r\n * @param assistantId 智能体ID,默认使用jimeng原版\r\n * @param retryCount 重试次数\r\n */\r\nexport async function createCompletion(\r\n messages: any[],\r\n refreshToken: string,\r\n _model = DEFAULT_MODEL,\r\n retryCount = 0\r\n) {\r\n return (async () => {\r\n if (messages.length === 0)\r\n throw new APIException(EX.API_REQUEST_PARAMS_INVALID, \"消息不能为空\");\r\n\r\n const { model, width, height } = parseModel(_model);\r\n logger.info(messages);\r\n\r\n // 检查是否为视频生成请求\r\n if (isVideoModel(_model)) {\r\n try {\r\n // 视频生成\r\n logger.info(`开始生成视频,模型: ${_model}`);\r\n\r\n let videoUrl: string;\r\n\r\n // 判断是否为 Seedance 模型\r\n if (isSeedanceModel(_model)) {\r\n // Seedance 模型需要图片,在 chat 模式下不支持图片上传\r\n // 返回友好提示\r\n return {\r\n id: util.uuid(),\r\n model: _model,\r\n object: \"chat.completion\",\r\n choices: [\r\n {\r\n index: 0,\r\n message: {\r\n role: \"assistant\",\r\n content: `Seedance 2.0 是多图智能视频生成模型,需要上传图片才能生成视频。\\n\\n请使用 POST /v1/videos/generations API 接口:\\n\\n\\`\\`\\`bash\\ncurl -X POST http://localhost:3000/v1/videos/generations \\\\\\n -H \"Authorization: your_token\" \\\\\\n -F \"model=jimeng-video-seedance-2.0\" \\\\\\n -F \"prompt=@1 图片中的人物开始跳舞\" \\\\\\n -F \"ratio=4:3\" \\\\\\n -F \"duration=4\" \\\\\\n -F \"files=@/path/to/image1.jpg\" \\\\\\n -F \"files=@/path/to/image2.jpg\"\\n\\`\\`\\`\\n\\n**参数说明:**\\n- \\`model\\`: jimeng-video-seedance-2.0(推荐)、jimeng-video-seedance-2.0-fast(快速版)或 seedance-2.0(兼容)\\n- \\`prompt\\`: 提示词,使用 @1, @2 等引用上传的图片\\n- \\`ratio\\`: 视频比例 (默认 4:3)\\n- \\`duration\\`: 视频时长 4-15 秒 (默认 4 秒)\\n- \\`files\\`: 上传的图片文件(支持多张)`,\r\n },\r\n finish_reason: \"stop\",\r\n },\r\n ],\r\n usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 },\r\n created: util.unixTimestamp(),\r\n };\r\n }\r\n\r\n videoUrl = await generateVideo(\r\n _model,\r\n messages[messages.length - 1].content,\r\n {\r\n ratio: \"16:9\",\r\n resolution: \"720p\", // 默认分辨率\r\n },\r\n refreshToken\r\n );\r\n \r\n logger.info(`视频生成成功,URL: ${videoUrl}`);\r\n return {\r\n id: util.uuid(),\r\n model: _model,\r\n object: \"chat.completion\",\r\n choices: [\r\n {\r\n index: 0,\r\n message: {\r\n role: \"assistant\",\r\n content: `\\n`,\r\n },\r\n finish_reason: \"stop\",\r\n },\r\n ],\r\n usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 },\r\n created: util.unixTimestamp(),\r\n };\r\n } catch (error) {\r\n logger.error(`视频生成失败: ${error.message}`);\r\n // 如果是积分不足等特定错误,直接抛出\r\n if (error instanceof APIException) {\r\n throw error;\r\n }\r\n \r\n // 其他错误返回友好提示\r\n return {\r\n id: util.uuid(),\r\n model: _model,\r\n object: \"chat.completion\",\r\n choices: [\r\n {\r\n index: 0,\r\n message: {\r\n role: \"assistant\",\r\n content: `生成视频失败: ${error.message}\\n\\n如果您在即梦官网看到已生成的视频,可能是获取结果时出现了问题,请前往即梦官网查看。`,\r\n },\r\n finish_reason: \"stop\",\r\n },\r\n ],\r\n usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 },\r\n created: util.unixTimestamp(),\r\n };\r\n }\r\n } else {\r\n // 图像生成\r\n const imageUrls = await generateImages(\r\n model,\r\n messages[messages.length - 1].content,\r\n {\r\n width,\r\n height,\r\n },\r\n refreshToken\r\n );\r\n\r\n return {\r\n id: util.uuid(),\r\n model: _model || model,\r\n object: \"chat.completion\",\r\n choices: [\r\n {\r\n index: 0,\r\n message: {\r\n role: \"assistant\",\r\n content: imageUrls.reduce(\r\n (acc, url, i) => acc + `\\n`,\r\n \"\"\r\n ),\r\n },\r\n finish_reason: \"stop\",\r\n },\r\n ],\r\n usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 },\r\n created: util.unixTimestamp(),\r\n };\r\n }\r\n })().catch((err) => {\r\n if (retryCount < MAX_RETRY_COUNT) {\r\n logger.error(`Response error: ${err.stack}`);\r\n logger.warn(`Try again after ${RETRY_DELAY / 1000}s...`);\r\n return (async () => {\r\n await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY));\r\n return createCompletion(messages, refreshToken, _model, retryCount + 1);\r\n })();\r\n }\r\n throw err;\r\n });\r\n}\r\n\r\n/**\r\n * 流式对话补全\r\n *\r\n * @param messages 参考gpt系列消息格式,多轮对话请完整提供上下文\r\n * @param refreshToken 用于刷新access_token的refresh_token\r\n * @param assistantId 智能体ID,默认使用jimeng原版\r\n * @param retryCount 重试次数\r\n */\r\nexport async function createCompletionStream(\r\n messages: any[],\r\n refreshToken: string,\r\n _model = DEFAULT_MODEL,\r\n retryCount = 0\r\n) {\r\n return (async () => {\r\n const { model, width, height } = parseModel(_model);\r\n logger.info(messages);\r\n\r\n const stream = new PassThrough();\r\n\r\n if (messages.length === 0) {\r\n logger.warn(\"消息为空,返回空流\");\r\n stream.end(\"data: [DONE]\\n\\n\");\r\n return stream;\r\n }\r\n\r\n // 检查是否为视频生成请求\r\n if (isVideoModel(_model)) {\r\n // 视频生成\r\n stream.write(\r\n \"data: \" +\r\n JSON.stringify({\r\n id: util.uuid(),\r\n model: _model,\r\n object: \"chat.completion.chunk\",\r\n choices: [\r\n {\r\n index: 0,\r\n delta: { role: \"assistant\", content: \"🎬 视频生成中,请稍候...\\n这可能需要1-2分钟,请耐心等待\" },\r\n finish_reason: null,\r\n },\r\n ],\r\n }) +\r\n \"\\n\\n\"\r\n );\r\n\r\n // 视频生成\r\n logger.info(`开始生成视频,提示词: ${messages[messages.length - 1].content}`);\r\n \r\n // 进度更新定时器\r\n const progressInterval = setInterval(() => {\r\n stream.write(\r\n \"data: \" +\r\n JSON.stringify({\r\n id: util.uuid(),\r\n model: _model,\r\n object: \"chat.completion.chunk\",\r\n choices: [\r\n {\r\n index: 0,\r\n delta: { role: \"assistant\", content: \".\" },\r\n finish_reason: null,\r\n },\r\n ],\r\n }) +\r\n \"\\n\\n\"\r\n );\r\n }, 5000);\r\n \r\n // 设置超时,防止无限等待\r\n const timeoutId = setTimeout(() => {\r\n clearInterval(progressInterval);\r\n logger.warn(`视频生成超时(2分钟),提示用户前往即梦官网查看`);\r\n stream.write(\r\n \"data: \" +\r\n JSON.stringify({\r\n id: util.uuid(),\r\n model: _model,\r\n object: \"chat.completion.chunk\",\r\n choices: [\r\n {\r\n index: 1,\r\n delta: {\r\n role: \"assistant\",\r\n content: \"\\n\\n视频生成时间较长(已等待2分钟),但视频可能仍在生成中。\\n\\n请前往即梦官网查看您的视频:\\n1. 访问 https://jimeng.jianying.com/ai-tool/video/generate\\n2. 登录后查看您的创作历史\\n3. 如果视频已生成,您可以直接在官网下载或分享\\n\\n您也可以继续等待,系统将在后台继续尝试获取视频(最长约20分钟)。\",\r\n },\r\n finish_reason: \"stop\",\r\n },\r\n ],\r\n }) +\r\n \"\\n\\n\"\r\n );\r\n // 注意:这里不结束流,让后台继续尝试获取视频\r\n // stream.end(\"data: [DONE]\\n\\n\");\r\n }, 2 * 60 * 1000);\r\n\r\n logger.info(`开始生成视频,模型: ${_model}, 提示词: ${messages[messages.length - 1].content.substring(0, 50)}...`);\r\n \r\n // 先给用户一个初始提示\r\n stream.write(\r\n \"data: \" +\r\n JSON.stringify({\r\n id: util.uuid(),\r\n model: _model,\r\n object: \"chat.completion.chunk\",\r\n choices: [\r\n {\r\n index: 0,\r\n delta: {\r\n role: \"assistant\",\r\n content: \"\\n\\n🎬 视频生成已开始,这可能需要几分钟时间...\",\r\n },\r\n finish_reason: null,\r\n },\r\n ],\r\n }) +\r\n \"\\n\\n\"\r\n );\r\n \r\n generateVideo(\r\n _model,\r\n messages[messages.length - 1].content,\r\n { ratio: \"16:9\", resolution: \"720p\" },\r\n refreshToken\r\n )\r\n .then((videoUrl) => {\r\n clearInterval(progressInterval);\r\n clearTimeout(timeoutId);\r\n \r\n logger.info(`视频生成成功,URL: ${videoUrl}`);\r\n \r\n stream.write(\r\n \"data: \" +\r\n JSON.stringify({\r\n id: util.uuid(),\r\n model: _model,\r\n object: \"chat.completion.chunk\",\r\n choices: [\r\n {\r\n index: 1,\r\n delta: {\r\n role: \"assistant\",\r\n content: `\\n\\n✅ 视频生成完成!\\n\\n\\n\\n您可以:\\n1. 直接查看上方视频\\n2. 使用以下链接下载或分享:${videoUrl}`,\r\n },\r\n finish_reason: null,\r\n },\r\n ],\r\n }) +\r\n \"\\n\\n\"\r\n );\r\n \r\n stream.write(\r\n \"data: \" +\r\n JSON.stringify({\r\n id: util.uuid(),\r\n model: _model,\r\n object: \"chat.completion.chunk\",\r\n choices: [\r\n {\r\n index: 2,\r\n delta: {\r\n role: \"assistant\",\r\n content: \"\",\r\n },\r\n finish_reason: \"stop\",\r\n },\r\n ],\r\n }) +\r\n \"\\n\\n\"\r\n );\r\n stream.end(\"data: [DONE]\\n\\n\");\r\n })\r\n .catch((err) => {\r\n clearInterval(progressInterval);\r\n clearTimeout(timeoutId);\r\n \r\n logger.error(`视频生成失败: ${err.message}`);\r\n logger.error(`错误详情: ${JSON.stringify(err)}`);\r\n \r\n // 记录详细错误信息\r\n logger.error(`视频生成失败: ${err.message}`);\r\n logger.error(`错误详情: ${JSON.stringify(err)}`);\r\n \r\n // 构建更详细的错误信息\r\n let errorMessage = `⚠️ 视频生成过程中遇到问题: ${err.message}`;\r\n \r\n // 如果是历史记录不存在的错误,提供更具体的建议\r\n if (err.message.includes(\"历史记录不存在\")) {\r\n errorMessage += \"\\n\\n可能原因:\\n1. 视频生成请求已发送,但API无法获取历史记录\\n2. 视频生成服务暂时不可用\\n3. 历史记录ID无效或已过期\\n\\n建议操作:\\n1. 请前往即梦官网查看您的视频是否已生成:https://jimeng.jianying.com/ai-tool/video/generate\\n2. 如果官网已显示视频,但这里无法获取,可能是API连接问题\\n3. 如果官网也没有显示,请稍后再试或重新生成视频\";\r\n } else if (err.message.includes(\"获取视频生成结果超时\")) {\r\n errorMessage += \"\\n\\n视频生成可能仍在进行中,但等待时间已超过系统设定的限制。\\n\\n请前往即梦官网查看您的视频:https://jimeng.jianying.com/ai-tool/video/generate\\n\\n如果您在官网上看到视频已生成,但这里无法显示,可能是因为:\\n1. 获取结果的过程超时\\n2. 网络连接问题\\n3. API访问限制\";\r\n } else {\r\n errorMessage += \"\\n\\n如果您在即梦官网看到已生成的视频,可能是获取结果时出现了问题。\\n\\n请访问即梦官网查看您的创作历史:https://jimeng.jianying.com/ai-tool/video/generate\";\r\n }\r\n \r\n // 添加历史ID信息,方便用户在官网查找\r\n if (err.historyId) {\r\n errorMessage += `\\n\\n历史记录ID: ${err.historyId}(您可以使用此ID在官网搜索您的视频)`;\r\n }\r\n \r\n stream.write(\r\n \"data: \" +\r\n JSON.stringify({\r\n id: util.uuid(),\r\n model: _model,\r\n object: \"chat.completion.chunk\",\r\n choices: [\r\n {\r\n index: 1,\r\n delta: {\r\n role: \"assistant\",\r\n content: `\\n\\n${errorMessage}`,\r\n },\r\n finish_reason: \"stop\",\r\n },\r\n ],\r\n }) +\r\n \"\\n\\n\"\r\n );\r\n stream.end(\"data: [DONE]\\n\\n\");\r\n });\r\n } else {\r\n // 图像生成\r\n stream.write(\r\n \"data: \" +\r\n JSON.stringify({\r\n id: util.uuid(),\r\n model: _model || model,\r\n object: \"chat.completion.chunk\",\r\n choices: [\r\n {\r\n index: 0,\r\n delta: { role: \"assistant\", content: \"🎨 图像生成中,请稍候...\" },\r\n finish_reason: null,\r\n },\r\n ],\r\n }) +\r\n \"\\n\\n\"\r\n );\r\n\r\n generateImages(\r\n model,\r\n messages[messages.length - 1].content,\r\n { width, height },\r\n refreshToken\r\n )\r\n .then((imageUrls) => {\r\n for (let i = 0; i < imageUrls.length; i++) {\r\n const url = imageUrls[i];\r\n stream.write(\r\n \"data: \" +\r\n JSON.stringify({\r\n id: util.uuid(),\r\n model: _model || model,\r\n object: \"chat.completion.chunk\",\r\n choices: [\r\n {\r\n index: i + 1,\r\n delta: {\r\n role: \"assistant\",\r\n content: `\\n`,\r\n },\r\n finish_reason: i < imageUrls.length - 1 ? null : \"stop\",\r\n },\r\n ],\r\n }) +\r\n \"\\n\\n\"\r\n );\r\n }\r\n stream.write(\r\n \"data: \" +\r\n JSON.stringify({\r\n id: util.uuid(),\r\n model: _model || model,\r\n object: \"chat.completion.chunk\",\r\n choices: [\r\n {\r\n index: imageUrls.length + 1,\r\n delta: {\r\n role: \"assistant\",\r\n content: \"图像生成完成!\",\r\n },\r\n finish_reason: \"stop\",\r\n },\r\n ],\r\n }) +\r\n \"\\n\\n\"\r\n );\r\n stream.end(\"data: [DONE]\\n\\n\");\r\n })\r\n .catch((err) => {\r\n stream.write(\r\n \"data: \" +\r\n JSON.stringify({\r\n id: util.uuid(),\r\n model: _model || model,\r\n object: \"chat.completion.chunk\",\r\n choices: [\r\n {\r\n index: 1,\r\n delta: {\r\n role: \"assistant\",\r\n content: `生成图片失败: ${err.message}`,\r\n },\r\n finish_reason: \"stop\",\r\n },\r\n ],\r\n }) +\r\n \"\\n\\n\"\r\n );\r\n stream.end(\"data: [DONE]\\n\\n\");\r\n });\r\n }\r\n return stream;\r\n })().catch((err) => {\r\n if (retryCount < MAX_RETRY_COUNT) {\r\n logger.error(`Response error: ${err.stack}`);\r\n logger.warn(`Try again after ${RETRY_DELAY / 1000}s...`);\r\n return (async () => {\r\n await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY));\r\n return createCompletionStream(\r\n messages,\r\n refreshToken,\r\n _model,\r\n retryCount + 1\r\n );\r\n })();\r\n }\r\n throw err;\r\n });\r\n}\r\n","import _ from \"lodash\";\r\nimport crypto from \"crypto\";\r\nimport fs from \"fs\";\r\n\r\nimport APIException from \"@/lib/exceptions/APIException.ts\";\r\nimport EX from \"@/api/consts/exceptions.ts\";\r\nimport util from \"@/lib/util.ts\";\r\nimport { getCredit, receiveCredit, request, DEFAULT_ASSISTANT_ID as CORE_ASSISTANT_ID, WEB_ID, acquireToken } from \"./core.ts\";\r\nimport logger from \"@/lib/logger.ts\";\r\nimport browserService from \"@/lib/browser-service.ts\";\r\n\r\nconst DEFAULT_ASSISTANT_ID = 513695;\r\nexport const DEFAULT_MODEL = \"jimeng-video-3.0\";\r\nconst DEFAULT_DRAFT_VERSION = \"3.2.8\";\r\n\r\nconst MODEL_DRAFT_VERSIONS: { [key: string]: string } = {\r\n \"jimeng-video-3.5-pro\": \"3.3.4\",\r\n \"jimeng-video-3.0-pro\": \"3.2.8\",\r\n \"jimeng-video-3.0\": \"3.2.8\",\r\n \"jimeng-video-2.0\": \"3.2.8\",\r\n \"jimeng-video-2.0-pro\": \"3.2.8\",\r\n // Seedance 模型(与上游 iptag/jimeng-api 保持一致)\r\n \"jimeng-video-seedance-2.0\": \"3.3.9\",\r\n \"seedance-2.0\": \"3.3.9\",\r\n \"seedance-2.0-pro\": \"3.3.9\",\r\n // Seedance 2.0-fast 模型(v1.9.3 新增)\r\n \"jimeng-video-seedance-2.0-fast\": \"3.3.9\",\r\n \"seedance-2.0-fast\": \"3.3.9\",\r\n};\r\n\r\nconst MODEL_MAP = {\r\n \"jimeng-video-3.5-pro\": \"dreamina_ic_generate_video_model_vgfm_3.5_pro\",\r\n \"jimeng-video-3.0-pro\": \"dreamina_ic_generate_video_model_vgfm_3.0_pro\",\r\n \"jimeng-video-3.0\": \"dreamina_ic_generate_video_model_vgfm_3.0\",\r\n \"jimeng-video-2.0\": \"dreamina_ic_generate_video_model_vgfm_lite\",\r\n \"jimeng-video-2.0-pro\": \"dreamina_ic_generate_video_model_vgfm1.0\",\r\n // Seedance 多图智能视频生成模型(jimeng-video-seedance-2.0 为上游标准名称)\r\n \"jimeng-video-seedance-2.0\": \"dreamina_seedance_40_pro\",\r\n \"seedance-2.0\": \"dreamina_seedance_40_pro\",\r\n \"seedance-2.0-pro\": \"dreamina_seedance_40_pro\",\r\n // Seedance 2.0-fast 快速生成模型(v1.9.3 新增,内部模型为 dreamina_seedance_40)\r\n \"jimeng-video-seedance-2.0-fast\": \"dreamina_seedance_40\",\r\n \"seedance-2.0-fast\": \"dreamina_seedance_40\",\r\n};\r\n\r\n// Seedance 模型的 benefit_type 映射\r\nconst SEEDANCE_BENEFIT_TYPE_MAP: { [key: string]: string } = {\r\n \"jimeng-video-seedance-2.0\": \"dreamina_video_seedance_20_pro\",\r\n \"seedance-2.0\": \"dreamina_video_seedance_20_pro\",\r\n \"seedance-2.0-pro\": \"dreamina_video_seedance_20_pro\",\r\n // Seedance 2.0-fast(v1.9.3 新增,注意:无 \"video_\" 前缀)\r\n \"jimeng-video-seedance-2.0-fast\": \"dreamina_seedance_20_fast\",\r\n \"seedance-2.0-fast\": \"dreamina_seedance_20_fast\",\r\n};\r\n\r\n// 判断是否为 Seedance 模型\r\nexport function isSeedanceModel(model: string): boolean {\r\n return model.startsWith(\"seedance-\") || model.startsWith(\"jimeng-video-seedance-\");\r\n}\r\n\r\n// ========== Seedance 多类型素材支持 ==========\r\n\r\n// 素材类型\r\ntype SeedanceMaterialType = \"image\" | \"video\" | \"audio\";\r\n\r\n// 上传结果统一接口\r\ninterface UploadedMaterial {\r\n type: SeedanceMaterialType;\r\n // 图片\r\n uri?: string;\r\n // 视频/音频(VOD)\r\n vid?: string;\r\n // 通用\r\n width?: number;\r\n height?: number;\r\n duration?: number;\r\n fps?: number;\r\n name?: string;\r\n}\r\n\r\n// MIME 类型 → 素材类型映射\r\nconst MIME_TO_MATERIAL_TYPE: Record<string, SeedanceMaterialType> = {\r\n \"image/jpeg\": \"image\", \"image/png\": \"image\", \"image/webp\": \"image\",\r\n \"image/gif\": \"image\", \"image/bmp\": \"image\",\r\n \"video/mp4\": \"video\", \"video/quicktime\": \"video\", \"video/x-m4v\": \"video\",\r\n \"audio/mpeg\": \"audio\", \"audio/wav\": \"audio\", \"audio/x-wav\": \"audio\",\r\n \"audio/mp3\": \"audio\",\r\n};\r\n\r\n// 扩展名 → 素材类型映射(兜底)\r\nconst EXT_TO_MATERIAL_TYPE: Record<string, SeedanceMaterialType> = {\r\n \".jpg\": \"image\", \".jpeg\": \"image\", \".png\": \"image\", \".webp\": \"image\",\r\n \".gif\": \"image\", \".bmp\": \"image\",\r\n \".mp4\": \"video\", \".mov\": \"video\", \".m4v\": \"video\",\r\n \".mp3\": \"audio\", \".wav\": \"audio\",\r\n};\r\n\r\n// materialTypes 编码映射\r\nconst MATERIAL_TYPE_CODE: Record<SeedanceMaterialType, number> = {\r\n image: 1, video: 2, audio: 3,\r\n};\r\n\r\n/**\r\n * 检测上传文件的素材类型\r\n * 优先通过 MIME 类型判断,兜底通过文件扩展名\r\n */\r\nfunction detectMaterialType(file: any): SeedanceMaterialType {\r\n // 优先通过 MIME 类型判断\r\n const mime = (file.mimetype || file.mimeType || \"\").toLowerCase();\r\n if (mime && MIME_TO_MATERIAL_TYPE[mime]) return MIME_TO_MATERIAL_TYPE[mime];\r\n // 兜底:通过文件扩展名判断\r\n const filename = (file.originalFilename || file.newFilename || \"\").toLowerCase();\r\n const dotIdx = filename.lastIndexOf(\".\");\r\n if (dotIdx >= 0) {\r\n const ext = filename.substring(dotIdx);\r\n if (EXT_TO_MATERIAL_TYPE[ext]) return EXT_TO_MATERIAL_TYPE[ext];\r\n }\r\n // 默认视为图片(向后兼容)\r\n return \"image\";\r\n}\r\n\r\n/**\r\n * 从 URL 检测素材类型\r\n * 通过 URL 路径的扩展名判断\r\n */\r\nfunction detectMaterialTypeFromUrl(url: string): SeedanceMaterialType {\r\n try {\r\n const pathname = new URL(url).pathname.toLowerCase();\r\n const dotIdx = pathname.lastIndexOf(\".\");\r\n if (dotIdx >= 0) {\r\n const ext = pathname.substring(dotIdx);\r\n if (EXT_TO_MATERIAL_TYPE[ext]) return EXT_TO_MATERIAL_TYPE[ext];\r\n }\r\n } catch {}\r\n // 默认视为图片(向后兼容)\r\n return \"image\";\r\n}\r\n\r\n// 视频支持的分辨率和比例配置\r\nconst VIDEO_RESOLUTION_OPTIONS: {\r\n [resolution: string]: {\r\n [ratio: string]: { width: number; height: number };\r\n };\r\n} = {\r\n \"480p\": {\r\n \"1:1\": { width: 480, height: 480 },\r\n \"4:3\": { width: 640, height: 480 },\r\n \"3:4\": { width: 480, height: 640 },\r\n \"16:9\": { width: 854, height: 480 },\r\n \"9:16\": { width: 480, height: 854 },\r\n },\r\n \"720p\": {\r\n \"1:1\": { width: 720, height: 720 },\r\n \"4:3\": { width: 960, height: 720 },\r\n \"3:4\": { width: 720, height: 960 },\r\n \"16:9\": { width: 1280, height: 720 },\r\n \"9:16\": { width: 720, height: 1280 },\r\n },\r\n \"1080p\": {\r\n \"1:1\": { width: 1080, height: 1080 },\r\n \"4:3\": { width: 1440, height: 1080 },\r\n \"3:4\": { width: 1080, height: 1440 },\r\n \"16:9\": { width: 1920, height: 1080 },\r\n \"9:16\": { width: 1080, height: 1920 },\r\n },\r\n};\r\n\r\n// 解析视频分辨率参数\r\nfunction resolveVideoResolution(\r\n resolution: string = \"720p\",\r\n ratio: string = \"1:1\"\r\n): { width: number; height: number } {\r\n const resolutionGroup = VIDEO_RESOLUTION_OPTIONS[resolution];\r\n if (!resolutionGroup) {\r\n const supportedResolutions = Object.keys(VIDEO_RESOLUTION_OPTIONS).join(\", \");\r\n throw new Error(`不支持的视频分辨率 \"${resolution}\"。支持的分辨率: ${supportedResolutions}`);\r\n }\r\n\r\n const ratioConfig = resolutionGroup[ratio];\r\n if (!ratioConfig) {\r\n const supportedRatios = Object.keys(resolutionGroup).join(\", \");\r\n throw new Error(`在 \"${resolution}\" 分辨率下,不支持的比例 \"${ratio}\"。支持的比例: ${supportedRatios}`);\r\n }\r\n\r\n return {\r\n width: ratioConfig.width,\r\n height: ratioConfig.height,\r\n };\r\n}\r\n\r\nexport function getModel(model: string) {\r\n return MODEL_MAP[model] || MODEL_MAP[DEFAULT_MODEL];\r\n}\r\n\r\n// AWS4-HMAC-SHA256 签名生成函数(从 images.ts 复制)\r\nfunction createSignature(\r\n method: string,\r\n url: string,\r\n headers: { [key: string]: string },\r\n accessKeyId: string,\r\n secretAccessKey: string,\r\n sessionToken?: string,\r\n payload: string = '',\r\n awsRegion: string = 'cn-north-1',\r\n serviceName: string = 'imagex'\r\n) {\r\n const urlObj = new URL(url);\r\n const pathname = urlObj.pathname || '/';\r\n const search = urlObj.search;\r\n\r\n // 创建规范请求\r\n const timestamp = headers['x-amz-date'];\r\n const date = timestamp.substr(0, 8);\r\n const region = awsRegion;\r\n const service = serviceName;\r\n \r\n // 规范化查询参数\r\n const queryParams: Array<[string, string]> = [];\r\n const searchParams = new URLSearchParams(search);\r\n searchParams.forEach((value, key) => {\r\n queryParams.push([key, value]);\r\n });\r\n \r\n // 按键名排序\r\n queryParams.sort(([a], [b]) => {\r\n if (a < b) return -1;\r\n if (a > b) return 1;\r\n return 0;\r\n });\r\n \r\n const canonicalQueryString = queryParams\r\n .map(([key, value]) => `${key}=${value}`)\r\n .join('&');\r\n \r\n // 规范化头部\r\n const headersToSign: { [key: string]: string } = {\r\n 'x-amz-date': timestamp\r\n };\r\n \r\n if (sessionToken) {\r\n headersToSign['x-amz-security-token'] = sessionToken;\r\n }\r\n \r\n let payloadHash = crypto.createHash('sha256').update('').digest('hex');\r\n if (method.toUpperCase() === 'POST' && payload) {\r\n payloadHash = crypto.createHash('sha256').update(payload, 'utf8').digest('hex');\r\n headersToSign['x-amz-content-sha256'] = payloadHash;\r\n }\r\n \r\n const signedHeaders = Object.keys(headersToSign)\r\n .map(key => key.toLowerCase())\r\n .sort()\r\n .join(';');\r\n \r\n const canonicalHeaders = Object.keys(headersToSign)\r\n .sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))\r\n .map(key => `${key.toLowerCase()}:${headersToSign[key].trim()}\\n`)\r\n .join('');\r\n \r\n const canonicalRequest = [\r\n method.toUpperCase(),\r\n pathname,\r\n canonicalQueryString,\r\n canonicalHeaders,\r\n signedHeaders,\r\n payloadHash\r\n ].join('\\n');\r\n \r\n // 创建待签名字符串\r\n const credentialScope = `${date}/${region}/${service}/aws4_request`;\r\n const stringToSign = [\r\n 'AWS4-HMAC-SHA256',\r\n timestamp,\r\n credentialScope,\r\n crypto.createHash('sha256').update(canonicalRequest, 'utf8').digest('hex')\r\n ].join('\\n');\r\n \r\n // 生成签名\r\n const kDate = crypto.createHmac('sha256', `AWS4${secretAccessKey}`).update(date).digest();\r\n const kRegion = crypto.createHmac('sha256', kDate).update(region).digest();\r\n const kService = crypto.createHmac('sha256', kRegion).update(service).digest();\r\n const kSigning = crypto.createHmac('sha256', kService).update('aws4_request').digest();\r\n const signature = crypto.createHmac('sha256', kSigning).update(stringToSign, 'utf8').digest('hex');\r\n \r\n return `AWS4-HMAC-SHA256 Credential=${accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;\r\n}\r\n\r\n// 计算文件的CRC32值(从 images.ts 复制)\r\nfunction calculateCRC32(buffer: ArrayBuffer): string {\r\n const crcTable = [];\r\n for (let i = 0; i < 256; i++) {\r\n let crc = i;\r\n for (let j = 0; j < 8; j++) {\r\n crc = (crc & 1) ? (0xEDB88320 ^ (crc >>> 1)) : (crc >>> 1);\r\n }\r\n crcTable[i] = crc;\r\n }\r\n \r\n let crc = 0 ^ (-1);\r\n const bytes = new Uint8Array(buffer);\r\n for (let i = 0; i < bytes.length; i++) {\r\n crc = (crc >>> 8) ^ crcTable[(crc ^ bytes[i]) & 0xFF];\r\n }\r\n return ((crc ^ (-1)) >>> 0).toString(16).padStart(8, '0');\r\n}\r\n\r\n// 视频专用图片上传功能(基于 images.ts 的 uploadImageFromUrl)\r\nasync function uploadImageForVideo(imageUrl: string, refreshToken: string): Promise<string> {\r\n try {\r\n logger.info(`开始上传视频图片: ${imageUrl}`);\r\n \r\n // 第一步:获取上传令牌\r\n const tokenResult = await request(\"post\", \"/mweb/v1/get_upload_token\", refreshToken, {\r\n data: {\r\n scene: 2, // AIGC 图片上传场景\r\n },\r\n });\r\n \r\n const { access_key_id, secret_access_key, session_token, service_id } = tokenResult;\r\n if (!access_key_id || !secret_access_key || !session_token) {\r\n throw new Error(\"获取上传令牌失败\");\r\n }\r\n \r\n const actualServiceId = service_id || \"tb4s082cfz\";\r\n logger.info(`获取上传令牌成功: service_id=${actualServiceId}`);\r\n \r\n // 下载图片数据\r\n const imageResponse = await fetch(imageUrl);\r\n if (!imageResponse.ok) {\r\n throw new Error(`下载图片失败: ${imageResponse.status}`);\r\n }\r\n \r\n const imageBuffer = await imageResponse.arrayBuffer();\r\n const fileSize = imageBuffer.byteLength;\r\n const crc32 = calculateCRC32(imageBuffer);\r\n \r\n logger.info(`图片下载完成: 大小=${fileSize}字节, CRC32=${crc32}`);\r\n \r\n // 第二步:申请图片上传权限\r\n const now = new Date();\r\n const timestamp = now.toISOString().replace(/[:\\-]/g, '').replace(/\\.\\d{3}Z$/, 'Z');\r\n \r\n const randomStr = Math.random().toString(36).substring(2, 12);\r\n const applyUrl = `https://imagex.bytedanceapi.com/?Action=ApplyImageUpload&Version=2018-08-01&ServiceId=${actualServiceId}&FileSize=${fileSize}&s=${randomStr}`;\r\n \r\n const requestHeaders = {\r\n 'x-amz-date': timestamp,\r\n 'x-amz-security-token': session_token\r\n };\r\n \r\n const authorization = createSignature('GET', applyUrl, requestHeaders, access_key_id, secret_access_key, session_token);\r\n \r\n logger.info(`申请上传权限: ${applyUrl}`);\r\n \r\n const applyResponse = await fetch(applyUrl, {\r\n method: 'GET',\r\n headers: {\r\n 'accept': '*/*',\r\n 'accept-language': 'zh-CN,zh;q=0.9',\r\n 'authorization': authorization,\r\n 'origin': 'https://jimeng.jianying.com',\r\n 'referer': 'https://jimeng.jianying.com/ai-tool/video/generate',\r\n 'sec-ch-ua': '\"Not A(Brand\";v=\"8\", \"Chromium\";v=\"132\", \"Google Chrome\";v=\"132\"',\r\n 'sec-ch-ua-mobile': '?0',\r\n 'sec-ch-ua-platform': '\"Windows\"',\r\n 'sec-fetch-dest': 'empty',\r\n 'sec-fetch-mode': 'cors',\r\n 'sec-fetch-site': 'cross-site',\r\n 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',\r\n 'x-amz-date': timestamp,\r\n 'x-amz-security-token': session_token,\r\n },\r\n });\r\n \r\n if (!applyResponse.ok) {\r\n const errorText = await applyResponse.text();\r\n throw new Error(`申请上传权限失败: ${applyResponse.status} - ${errorText}`);\r\n }\r\n \r\n const applyResult = await applyResponse.json();\r\n \r\n if (applyResult?.ResponseMetadata?.Error) {\r\n throw new Error(`申请上传权限失败: ${JSON.stringify(applyResult.ResponseMetadata.Error)}`);\r\n }\r\n \r\n logger.info(`申请上传权限成功`);\r\n \r\n // 解析上传信息\r\n const uploadAddress = applyResult?.Result?.UploadAddress;\r\n if (!uploadAddress || !uploadAddress.StoreInfos || !uploadAddress.UploadHosts) {\r\n throw new Error(`获取上传地址失败: ${JSON.stringify(applyResult)}`);\r\n }\r\n \r\n const storeInfo = uploadAddress.StoreInfos[0];\r\n const uploadHost = uploadAddress.UploadHosts[0];\r\n const auth = storeInfo.Auth;\r\n \r\n const uploadUrl = `https://${uploadHost}/upload/v1/${storeInfo.StoreUri}`;\r\n const imageId = storeInfo.StoreUri.split('/').pop();\r\n \r\n logger.info(`准备上传图片: imageId=${imageId}, uploadUrl=${uploadUrl}`);\r\n \r\n // 第三步:上传图片文件\r\n const uploadResponse = await fetch(uploadUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Accept': '*/*',\r\n 'Accept-Language': 'zh-CN,zh;q=0.9',\r\n 'Authorization': auth,\r\n 'Connection': 'keep-alive',\r\n 'Content-CRC32': crc32,\r\n 'Content-Disposition': 'attachment; filename=\"undefined\"',\r\n 'Content-Type': 'application/octet-stream',\r\n 'Origin': 'https://jimeng.jianying.com',\r\n 'Referer': 'https://jimeng.jianying.com/ai-tool/video/generate',\r\n 'Sec-Fetch-Dest': 'empty',\r\n 'Sec-Fetch-Mode': 'cors',\r\n 'Sec-Fetch-Site': 'cross-site',\r\n 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',\r\n 'X-Storage-U': '704135154117550',\r\n },\r\n body: imageBuffer,\r\n });\r\n \r\n if (!uploadResponse.ok) {\r\n const errorText = await uploadResponse.text();\r\n throw new Error(`图片上传失败: ${uploadResponse.status} - ${errorText}`);\r\n }\r\n \r\n logger.info(`图片文件上传成功`);\r\n \r\n // 第四步:提交上传\r\n const commitUrl = `https://imagex.bytedanceapi.com/?Action=CommitImageUpload&Version=2018-08-01&ServiceId=${actualServiceId}`;\r\n \r\n const commitTimestamp = new Date().toISOString().replace(/[:\\-]/g, '').replace(/\\.\\d{3}Z$/, 'Z');\r\n const commitPayload = JSON.stringify({\r\n SessionKey: uploadAddress.SessionKey,\r\n SuccessActionStatus: \"200\"\r\n });\r\n \r\n const payloadHash = crypto.createHash('sha256').update(commitPayload, 'utf8').digest('hex');\r\n \r\n const commitRequestHeaders = {\r\n 'x-amz-date': commitTimestamp,\r\n 'x-amz-security-token': session_token,\r\n 'x-amz-content-sha256': payloadHash\r\n };\r\n \r\n const commitAuthorization = createSignature('POST', commitUrl, commitRequestHeaders, access_key_id, secret_access_key, session_token, commitPayload);\r\n \r\n const commitResponse = await fetch(commitUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'accept': '*/*',\r\n 'accept-language': 'zh-CN,zh;q=0.9',\r\n 'authorization': commitAuthorization,\r\n 'content-type': 'application/json',\r\n 'origin': 'https://jimeng.jianying.com',\r\n 'referer': 'https://jimeng.jianying.com/ai-tool/video/generate',\r\n 'sec-ch-ua': '\"Not A(Brand\";v=\"8\", \"Chromium\";v=\"132\", \"Google Chrome\";v=\"132\"',\r\n 'sec-ch-ua-mobile': '?0',\r\n 'sec-ch-ua-platform': '\"Windows\"',\r\n 'sec-fetch-dest': 'empty',\r\n 'sec-fetch-mode': 'cors',\r\n 'sec-fetch-site': 'cross-site',\r\n 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',\r\n 'x-amz-date': commitTimestamp,\r\n 'x-amz-security-token': session_token,\r\n 'x-amz-content-sha256': payloadHash,\r\n },\r\n body: commitPayload,\r\n });\r\n \r\n if (!commitResponse.ok) {\r\n const errorText = await commitResponse.text();\r\n throw new Error(`提交上传失败: ${commitResponse.status} - ${errorText}`);\r\n }\r\n \r\n const commitResult = await commitResponse.json();\r\n \r\n if (commitResult?.ResponseMetadata?.Error) {\r\n throw new Error(`提交上传失败: ${JSON.stringify(commitResult.ResponseMetadata.Error)}`);\r\n }\r\n \r\n if (!commitResult?.Result?.Results || commitResult.Result.Results.length === 0) {\r\n throw new Error(`提交上传响应缺少结果: ${JSON.stringify(commitResult)}`);\r\n }\r\n \r\n const uploadResult = commitResult.Result.Results[0];\r\n if (uploadResult.UriStatus !== 2000) {\r\n throw new Error(`图片上传状态异常: UriStatus=${uploadResult.UriStatus}`);\r\n }\r\n \r\n const fullImageUri = uploadResult.Uri;\r\n \r\n // 验证图片信息\r\n const pluginResult = commitResult.Result?.PluginResult?.[0];\r\n if (pluginResult && pluginResult.ImageUri) {\r\n logger.info(`视频图片上传完成: ${pluginResult.ImageUri}`);\r\n return pluginResult.ImageUri;\r\n }\r\n\r\n logger.info(`视频图片上传完成: ${fullImageUri}`);\r\n return fullImageUri;\r\n\r\n } catch (error) {\r\n logger.error(`视频图片上传失败: ${error.message}`);\r\n throw error;\r\n }\r\n}\r\n\r\n// 从Buffer上传视频图片\r\nasync function uploadImageBufferForVideo(buffer: Buffer, refreshToken: string): Promise<string> {\r\n try {\r\n logger.info(`开始从Buffer上传视频图片,大小: ${buffer.length}字节`);\r\n\r\n // 第一步:获取上传令牌\r\n const tokenResult = await request(\"post\", \"/mweb/v1/get_upload_token\", refreshToken, {\r\n data: {\r\n scene: 2,\r\n },\r\n });\r\n\r\n const { access_key_id, secret_access_key, session_token, service_id } = tokenResult;\r\n if (!access_key_id || !secret_access_key || !session_token) {\r\n throw new Error(\"获取上传令牌失败\");\r\n }\r\n\r\n const actualServiceId = service_id || \"tb4s082cfz\";\r\n logger.info(`获取上传令牌成功: service_id=${actualServiceId}`);\r\n\r\n const fileSize = buffer.length;\r\n const crc32 = calculateCRC32(buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength));\r\n\r\n logger.info(`Buffer大小: ${fileSize}字节, CRC32=${crc32}`);\r\n\r\n // 第二步:申请图片上传权限\r\n const now = new Date();\r\n const timestamp = now.toISOString().replace(/[:\\-]/g, '').replace(/\\.\\d{3}Z$/, 'Z');\r\n\r\n const randomStr = Math.random().toString(36).substring(2, 12);\r\n const applyUrl = `https://imagex.bytedanceapi.com/?Action=ApplyImageUpload&Version=2018-08-01&ServiceId=${actualServiceId}&FileSize=${fileSize}&s=${randomStr}`;\r\n\r\n const requestHeaders = {\r\n 'x-amz-date': timestamp,\r\n 'x-amz-security-token': session_token\r\n };\r\n\r\n const authorization = createSignature('GET', applyUrl, requestHeaders, access_key_id, secret_access_key, session_token);\r\n\r\n const applyResponse = await fetch(applyUrl, {\r\n method: 'GET',\r\n headers: {\r\n 'accept': '*/*',\r\n 'accept-language': 'zh-CN,zh;q=0.9',\r\n 'authorization': authorization,\r\n 'origin': 'https://jimeng.jianying.com',\r\n 'referer': 'https://jimeng.jianying.com/ai-tool/video/generate',\r\n 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',\r\n 'x-amz-date': timestamp,\r\n 'x-amz-security-token': session_token,\r\n },\r\n });\r\n\r\n if (!applyResponse.ok) {\r\n const errorText = await applyResponse.text();\r\n throw new Error(`申请上传权限失败: ${applyResponse.status} - ${errorText}`);\r\n }\r\n\r\n const applyResult = await applyResponse.json();\r\n\r\n if (applyResult?.ResponseMetadata?.Error) {\r\n throw new Error(`申请上传权限失败: ${JSON.stringify(applyResult.ResponseMetadata.Error)}`);\r\n }\r\n\r\n const uploadAddress = applyResult?.Result?.UploadAddress;\r\n if (!uploadAddress || !uploadAddress.StoreInfos || !uploadAddress.UploadHosts) {\r\n throw new Error(`获取上传地址失败: ${JSON.stringify(applyResult)}`);\r\n }\r\n\r\n const storeInfo = uploadAddress.StoreInfos[0];\r\n const uploadHost = uploadAddress.UploadHosts[0];\r\n const auth = storeInfo.Auth;\r\n\r\n const uploadUrl = `https://${uploadHost}/upload/v1/${storeInfo.StoreUri}`;\r\n\r\n // 第三步:上传图片文件\r\n const uploadResponse = await fetch(uploadUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Accept': '*/*',\r\n 'Authorization': auth,\r\n 'Content-CRC32': crc32,\r\n 'Content-Disposition': 'attachment; filename=\"undefined\"',\r\n 'Content-Type': 'application/octet-stream',\r\n 'Origin': 'https://jimeng.jianying.com',\r\n 'Referer': 'https://jimeng.jianying.com/ai-tool/video/generate',\r\n 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',\r\n },\r\n body: buffer,\r\n });\r\n\r\n if (!uploadResponse.ok) {\r\n const errorText = await uploadResponse.text();\r\n throw new Error(`图片上传失败: ${uploadResponse.status} - ${errorText}`);\r\n }\r\n\r\n logger.info(`Buffer图片文件上传成功`);\r\n\r\n // 第四步:提交上传\r\n const commitUrl = `https://imagex.bytedanceapi.com/?Action=CommitImageUpload&Version=2018-08-01&ServiceId=${actualServiceId}`;\r\n\r\n const commitTimestamp = new Date().toISOString().replace(/[:\\-]/g, '').replace(/\\.\\d{3}Z$/, 'Z');\r\n const commitPayload = JSON.stringify({\r\n SessionKey: uploadAddress.SessionKey,\r\n SuccessActionStatus: \"200\"\r\n });\r\n\r\n const payloadHash = crypto.createHash('sha256').update(commitPayload, 'utf8').digest('hex');\r\n\r\n const commitRequestHeaders = {\r\n 'x-amz-date': commitTimestamp,\r\n 'x-amz-security-token': session_token,\r\n 'x-amz-content-sha256': payloadHash\r\n };\r\n\r\n const commitAuthorization = createSignature('POST', commitUrl, commitRequestHeaders, access_key_id, secret_access_key, session_token, commitPayload);\r\n\r\n const commitResponse = await fetch(commitUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'accept': '*/*',\r\n 'authorization': commitAuthorization,\r\n 'content-type': 'application/json',\r\n 'origin': 'https://jimeng.jianying.com',\r\n 'referer': 'https://jimeng.jianying.com/ai-tool/video/generate',\r\n 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',\r\n 'x-amz-date': commitTimestamp,\r\n 'x-amz-security-token': session_token,\r\n 'x-amz-content-sha256': payloadHash,\r\n },\r\n body: commitPayload,\r\n });\r\n\r\n if (!commitResponse.ok) {\r\n const errorText = await commitResponse.text();\r\n throw new Error(`提交上传失败: ${commitResponse.status} - ${errorText}`);\r\n }\r\n\r\n const commitResult = await commitResponse.json();\r\n\r\n if (commitResult?.ResponseMetadata?.Error) {\r\n throw new Error(`提交上传失败: ${JSON.stringify(commitResult.ResponseMetadata.Error)}`);\r\n }\r\n\r\n if (!commitResult?.Result?.Results || commitResult.Result.Results.length === 0) {\r\n throw new Error(`提交上传响应缺少结果: ${JSON.stringify(commitResult)}`);\r\n }\r\n\r\n const uploadResult = commitResult.Result.Results[0];\r\n if (uploadResult.UriStatus !== 2000) {\r\n throw new Error(`图片上传状态异常: UriStatus=${uploadResult.UriStatus}`);\r\n }\r\n\r\n const fullImageUri = uploadResult.Uri;\r\n\r\n const pluginResult = commitResult.Result?.PluginResult?.[0];\r\n if (pluginResult && pluginResult.ImageUri) {\r\n logger.info(`Buffer视频图片上传完成: ${pluginResult.ImageUri}`);\r\n return pluginResult.ImageUri;\r\n }\r\n\r\n logger.info(`Buffer视频图片上传完成: ${fullImageUri}`);\r\n return fullImageUri;\r\n\r\n } catch (error) {\r\n logger.error(`Buffer视频图片上传失败: ${error.message}`);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * 解析音频文件时长(毫秒)\r\n * 支持 WAV 格式精确解析,其他格式按 128kbps 估算\r\n */\r\nfunction parseAudioDuration(buffer: Buffer): number {\r\n try {\r\n // WAV: RIFF header check\r\n if (buffer.length >= 44 &&\r\n buffer[0] === 0x52 && buffer[1] === 0x49 && buffer[2] === 0x46 && buffer[3] === 0x46 &&\r\n buffer[8] === 0x57 && buffer[9] === 0x41 && buffer[10] === 0x56 && buffer[11] === 0x45) {\r\n const byteRate = buffer.readUInt32LE(28);\r\n if (byteRate > 0) {\r\n // 查找 data chunk 获取精确大小\r\n let offset = 12;\r\n while (offset < buffer.length - 8) {\r\n const chunkId = buffer.toString('ascii', offset, offset + 4);\r\n const chunkSize = buffer.readUInt32LE(offset + 4);\r\n if (chunkId === 'data') {\r\n return Math.round(chunkSize / byteRate * 1000);\r\n }\r\n offset += 8 + chunkSize;\r\n }\r\n // 兜底:用文件大小估算\r\n return Math.round((buffer.length - 44) / byteRate * 1000);\r\n }\r\n }\r\n // 非 WAV:按 128kbps 估算\r\n return Math.round(buffer.length / (128 * 1000 / 8) * 1000);\r\n } catch {\r\n return 0;\r\n }\r\n}\r\n\r\n/**\r\n * 上传视频/音频文件\r\n * 通过 ByteDance VOD (视频点播) API 上传\r\n * 流程: get_upload_token(scene=1) → ApplyUploadInner → Upload → CommitUploadInner\r\n *\r\n * @param buffer 文件 Buffer\r\n * @param mediaType \"video\" 或 \"audio\"\r\n * @param refreshToken 刷新令牌\r\n * @param filename 原始文件名(可选)\r\n * @returns { vid, width?, height?, duration?, fps? }\r\n */\r\nasync function uploadMediaForVideo(\r\n buffer: Buffer,\r\n mediaType: \"video\" | \"audio\",\r\n refreshToken: string,\r\n filename?: string\r\n): Promise<{ vid: string; width?: number; height?: number; duration?: number; fps?: number }> {\r\n const label = mediaType === \"audio\" ? \"音频\" : \"视频\";\r\n const fileSize = buffer.length;\r\n logger.info(`开始上传${label}文件,大小: ${fileSize} 字节`);\r\n\r\n // 第一步:获取 VOD 上传令牌(scene=1)\r\n const tokenResult = await request(\"post\", \"/mweb/v1/get_upload_token\", refreshToken, {\r\n data: { scene: 1 },\r\n });\r\n\r\n const { access_key_id, secret_access_key, session_token, space_name } = tokenResult;\r\n if (!access_key_id || !secret_access_key || !session_token) {\r\n throw new Error(`获取${label}上传令牌失败`);\r\n }\r\n\r\n const spaceName = space_name || \"dreamina\";\r\n logger.info(`获取${label}上传令牌成功: spaceName=${spaceName}`);\r\n\r\n // 第二步:申请 VOD 上传权限(ApplyUploadInner)\r\n const now = new Date();\r\n const timestamp = now.toISOString().replace(/[:\\-]/g, '').replace(/\\.\\d{3}Z$/, 'Z');\r\n const randomStr = Math.random().toString(36).substring(2, 12);\r\n\r\n const vodHost = \"https://vod.bytedanceapi.com\";\r\n const applyUrl = `${vodHost}/?Action=ApplyUploadInner&Version=2020-11-19&SpaceName=${spaceName}&FileType=video&IsInner=1&FileSize=${fileSize}&s=${randomStr}`;\r\n\r\n const requestHeaders: Record<string, string> = {\r\n 'x-amz-date': timestamp,\r\n 'x-amz-security-token': session_token,\r\n };\r\n\r\n const authorization = createSignature(\r\n 'GET', applyUrl, requestHeaders,\r\n access_key_id, secret_access_key, session_token,\r\n '', 'cn-north-1', 'vod'\r\n );\r\n\r\n logger.info(`申请${label}上传权限: ${applyUrl}`);\r\n\r\n const applyResponse = await fetch(applyUrl, {\r\n method: 'GET',\r\n headers: {\r\n 'accept': '*/*',\r\n 'accept-language': 'zh-CN,zh;q=0.9',\r\n 'authorization': authorization,\r\n 'origin': 'https://jimeng.jianying.com',\r\n 'referer': 'https://jimeng.jianying.com/ai-tool/video/generate',\r\n 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',\r\n 'x-amz-date': timestamp,\r\n 'x-amz-security-token': session_token,\r\n },\r\n });\r\n\r\n if (!applyResponse.ok) {\r\n const errorText = await applyResponse.text();\r\n throw new Error(`申请${label}上传权限失败: ${applyResponse.status} - ${errorText}`);\r\n }\r\n\r\n const applyResult: any = await applyResponse.json();\r\n if (applyResult?.ResponseMetadata?.Error) {\r\n throw new Error(`申请${label}上传权限失败: ${JSON.stringify(applyResult.ResponseMetadata.Error)}`);\r\n }\r\n\r\n const uploadNodes = applyResult?.Result?.InnerUploadAddress?.UploadNodes;\r\n if (!uploadNodes || uploadNodes.length === 0) {\r\n throw new Error(`获取${label}上传节点失败: ${JSON.stringify(applyResult)}`);\r\n }\r\n\r\n const uploadNode = uploadNodes[0];\r\n const storeInfo = uploadNode.StoreInfos?.[0];\r\n if (!storeInfo) {\r\n throw new Error(`获取${label}上传存储信息失败: ${JSON.stringify(uploadNode)}`);\r\n }\r\n\r\n const uploadHost = uploadNode.UploadHost;\r\n const storeUri = storeInfo.StoreUri;\r\n const auth = storeInfo.Auth;\r\n const sessionKey = uploadNode.SessionKey;\r\n const vid = uploadNode.Vid;\r\n\r\n logger.info(`获取${label}上传节点成功: host=${uploadHost}, vid=${vid}`);\r\n\r\n // 第三步:上传文件\r\n const uploadUrl = `https://${uploadHost}/upload/v1/${storeUri}`;\r\n const crc32 = calculateCRC32(buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength));\r\n\r\n logger.info(`开始上传${label}文件: ${uploadUrl}, CRC32=${crc32}`);\r\n\r\n const uploadResponse = await fetch(uploadUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Accept': '*/*',\r\n 'Authorization': auth,\r\n 'Content-CRC32': crc32,\r\n 'Content-Type': 'application/octet-stream',\r\n 'Origin': 'https://jimeng.jianying.com',\r\n 'Referer': 'https://jimeng.jianying.com/ai-tool/video/generate',\r\n 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',\r\n },\r\n body: buffer,\r\n });\r\n\r\n if (!uploadResponse.ok) {\r\n const errorText = await uploadResponse.text();\r\n throw new Error(`${label}文件上传失败: ${uploadResponse.status} - ${errorText}`);\r\n }\r\n\r\n const uploadData: any = await uploadResponse.json();\r\n if (uploadData?.code !== 2000) {\r\n throw new Error(`${label}文件上传失败: code=${uploadData?.code}, message=${uploadData?.message}`);\r\n }\r\n\r\n logger.info(`${label}文件上传成功: crc32=${uploadData.data?.crc32}`);\r\n\r\n // 第四步:确认上传(CommitUploadInner)\r\n const commitUrl = `${vodHost}/?Action=CommitUploadInner&Version=2020-11-19&SpaceName=${spaceName}`;\r\n const commitTimestamp = new Date().toISOString().replace(/[:\\-]/g, '').replace(/\\.\\d{3}Z$/, 'Z');\r\n const commitPayload = JSON.stringify({\r\n SessionKey: sessionKey,\r\n Functions: [],\r\n });\r\n\r\n const payloadHash = crypto.createHash('sha256').update(commitPayload, 'utf8').digest('hex');\r\n\r\n const commitRequestHeaders: Record<string, string> = {\r\n 'x-amz-date': commitTimestamp,\r\n 'x-amz-security-token': session_token,\r\n 'x-amz-content-sha256': payloadHash,\r\n };\r\n\r\n const commitAuthorization = createSignature(\r\n 'POST', commitUrl, commitRequestHeaders,\r\n access_key_id, secret_access_key, session_token,\r\n commitPayload, 'cn-north-1', 'vod'\r\n );\r\n\r\n logger.info(`提交${label}上传确认: ${commitUrl}`);\r\n\r\n const commitResponse = await fetch(commitUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'accept': '*/*',\r\n 'authorization': commitAuthorization,\r\n 'content-type': 'application/json',\r\n 'origin': 'https://jimeng.jianying.com',\r\n 'referer': 'https://jimeng.jianying.com/ai-tool/video/generate',\r\n 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',\r\n 'x-amz-date': commitTimestamp,\r\n 'x-amz-security-token': session_token,\r\n 'x-amz-content-sha256': payloadHash,\r\n },\r\n body: commitPayload,\r\n });\r\n\r\n if (!commitResponse.ok) {\r\n const errorText = await commitResponse.text();\r\n throw new Error(`提交${label}上传失败: ${commitResponse.status} - ${errorText}`);\r\n }\r\n\r\n const commitResult: any = await commitResponse.json();\r\n if (commitResult?.ResponseMetadata?.Error) {\r\n throw new Error(`提交${label}上传失败: ${JSON.stringify(commitResult.ResponseMetadata.Error)}`);\r\n }\r\n\r\n if (!commitResult?.Result?.Results || commitResult.Result.Results.length === 0) {\r\n throw new Error(`提交${label}上传响应缺少结果: ${JSON.stringify(commitResult)}`);\r\n }\r\n\r\n const result = commitResult.Result.Results[0];\r\n if (!result.Vid) {\r\n throw new Error(`提交${label}上传响应缺少 Vid: ${JSON.stringify(result)}`);\r\n }\r\n\r\n // 从 VOD 返回的元数据中获取信息(音频有 Duration)\r\n const videoMeta = result.VideoMeta || {};\r\n let duration = videoMeta.Duration ? Math.round(videoMeta.Duration * 1000) : 0;\r\n\r\n // 如果 VOD 未返回时长,用本地解析兜底\r\n if (duration <= 0 && mediaType === \"audio\") {\r\n duration = parseAudioDuration(buffer);\r\n logger.info(`VOD 未返回${label}时长,本地解析: ${duration}ms`);\r\n }\r\n\r\n logger.info(`${label}上传完成: vid=${result.Vid}, duration=${duration}ms`);\r\n\r\n return {\r\n vid: result.Vid,\r\n width: videoMeta.Width || 0,\r\n height: videoMeta.Height || 0,\r\n duration,\r\n fps: videoMeta.Fps || 0,\r\n };\r\n}\r\n\r\n/**\r\n * 通过 get_local_item_list API 获取高质量视频下载URL\r\n * 浏览器下载视频时使用此API获取高码率版本(~6297 vs 预览版 ~1152)\r\n *\r\n * @param itemId 视频项目ID\r\n * @param refreshToken 刷新令牌\r\n * @returns 高质量视频URL,失败时返回 null\r\n */\r\nasync function fetchHighQualityVideoUrl(itemId: string, refreshToken: string): Promise<string | null> {\r\n try {\r\n logger.info(`尝试获取高质量视频下载URL,item_id: ${itemId}`);\r\n\r\n const result = await request(\"post\", \"/mweb/v1/get_local_item_list\", refreshToken, {\r\n data: {\r\n item_id_list: [itemId],\r\n pack_item_opt: {\r\n scene: 1,\r\n need_data_integrity: true,\r\n },\r\n is_for_video_download: true,\r\n },\r\n });\r\n\r\n const responseStr = JSON.stringify(result);\r\n logger.info(`get_local_item_list 响应大小: ${responseStr.length} 字符`);\r\n\r\n // 策略1: 从结构化字段中提取视频URL\r\n const itemList = result.item_list || result.local_item_list || [];\r\n if (itemList.length > 0) {\r\n const item = itemList[0];\r\n const videoUrl =\r\n item?.video?.transcoded_video?.origin?.video_url ||\r\n item?.video?.download_url ||\r\n item?.video?.play_url ||\r\n item?.video?.url;\r\n\r\n if (videoUrl) {\r\n logger.info(`从get_local_item_list结构化字段获取到高清视频URL: ${videoUrl}`);\r\n return videoUrl;\r\n }\r\n }\r\n\r\n // 策略2: 正则匹配 dreamnia.jimeng.com 高质量URL\r\n const hqUrlMatch = responseStr.match(/https:\\/\\/v[0-9]+-dreamnia\\.jimeng\\.com\\/[^\"\\s\\\\]+/);\r\n if (hqUrlMatch && hqUrlMatch[0]) {\r\n logger.info(`正则提取到高质量视频URL (dreamnia): ${hqUrlMatch[0]}`);\r\n return hqUrlMatch[0];\r\n }\r\n\r\n // 策略3: 匹配任何 jimeng.com 域名的视频URL\r\n const jimengUrlMatch = responseStr.match(/https:\\/\\/v[0-9]+-[^\"\\\\]*\\.jimeng\\.com\\/[^\"\\s\\\\]+/);\r\n if (jimengUrlMatch && jimengUrlMatch[0]) {\r\n logger.info(`正则提取到jimeng视频URL: ${jimengUrlMatch[0]}`);\r\n return jimengUrlMatch[0];\r\n }\r\n\r\n // 策略4: 匹配任何视频URL(兜底)\r\n const anyVideoUrlMatch = responseStr.match(/https:\\/\\/v[0-9]+-[^\"\\\\]*\\.(vlabvod|jimeng)\\.com\\/[^\"\\s\\\\]+/);\r\n if (anyVideoUrlMatch && anyVideoUrlMatch[0]) {\r\n logger.info(`从get_local_item_list提取到视频URL: ${anyVideoUrlMatch[0]}`);\r\n return anyVideoUrlMatch[0];\r\n }\r\n\r\n logger.warn(`未能从get_local_item_list响应中提取到视频URL`);\r\n return null;\r\n } catch (error) {\r\n logger.warn(`获取高质量视频下载URL失败: ${error.message}`);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * 生成视频\r\n *\r\n * @param _model 模型名称\r\n * @param prompt 提示词\r\n * @param options 选项\r\n * @param refreshToken 刷新令牌\r\n * @returns 视频URL\r\n */\r\nexport async function generateVideo(\r\n _model: string,\r\n prompt: string,\r\n {\r\n ratio = \"1:1\",\r\n resolution = \"720p\",\r\n duration = 5,\r\n filePaths = [],\r\n files = [],\r\n }: {\r\n ratio?: string;\r\n resolution?: string;\r\n duration?: number;\r\n filePaths?: string[];\r\n files?: any[];\r\n },\r\n refreshToken: string\r\n) {\r\n const model = getModel(_model);\r\n\r\n // 解析分辨率参数获取实际的宽高\r\n const { width, height } = resolveVideoResolution(resolution, ratio);\r\n\r\n logger.info(`使用模型: ${_model} 映射模型: ${model} ${width}x${height} (${ratio}@${resolution}) 时长: ${duration}秒`);\r\n\r\n // 检查积分\r\n const { totalCredit } = await getCredit(refreshToken);\r\n if (totalCredit <= 0)\r\n await receiveCredit(refreshToken);\r\n\r\n // 处理首帧和尾帧图片\r\n let first_frame_image = undefined;\r\n let end_frame_image = undefined;\r\n\r\n // 处理上传的文件(multipart/form-data)\r\n if (files && files.length > 0) {\r\n let uploadIDs: string[] = [];\r\n logger.info(`开始处理 ${files.length} 个上传文件用于视频生成`);\r\n\r\n for (let i = 0; i < files.length; i++) {\r\n const file = files[i];\r\n if (!file || !file.filepath) {\r\n logger.warn(`第 ${i + 1} 个文件无效,跳过`);\r\n continue;\r\n }\r\n\r\n try {\r\n logger.info(`开始上传第 ${i + 1} 个文件: ${file.originalFilename || file.filepath}`);\r\n\r\n // 读取文件内容并上传\r\n const buffer = fs.readFileSync(file.filepath);\r\n const imageUri = await uploadImageBufferForVideo(buffer, refreshToken);\r\n\r\n if (imageUri) {\r\n uploadIDs.push(imageUri);\r\n logger.info(`第 ${i + 1} 个文件上传成功: ${imageUri}`);\r\n } else {\r\n logger.error(`第 ${i + 1} 个文件上传失败: 未获取到 image_uri`);\r\n }\r\n } catch (error) {\r\n logger.error(`第 ${i + 1} 个文件上传失败: ${error.message}`);\r\n\r\n if (i === 0) {\r\n logger.error(`首帧文件上传失败,停止视频生成以避免浪费积分`);\r\n throw new APIException(EX.API_REQUEST_FAILED, `首帧文件上传失败: ${error.message}`);\r\n } else {\r\n logger.warn(`第 ${i + 1} 个文件上传失败,将跳过此文件继续处理`);\r\n }\r\n }\r\n }\r\n\r\n logger.info(`文件上传完成,成功上传 ${uploadIDs.length} 个文件`);\r\n\r\n if (uploadIDs.length === 0) {\r\n logger.error(`所有文件上传失败,停止视频生成以避免浪费积分`);\r\n throw new APIException(EX.API_REQUEST_FAILED, '所有文件上传失败,请检查文件是否有效');\r\n }\r\n\r\n // 构建首帧图片对象\r\n if (uploadIDs[0]) {\r\n first_frame_image = {\r\n format: \"\",\r\n height: height,\r\n id: util.uuid(),\r\n image_uri: uploadIDs[0],\r\n name: \"\",\r\n platform_type: 1,\r\n source_from: \"upload\",\r\n type: \"image\",\r\n uri: uploadIDs[0],\r\n width: width,\r\n };\r\n logger.info(`设置首帧图片: ${uploadIDs[0]}`);\r\n }\r\n\r\n // 构建尾帧图片对象\r\n if (uploadIDs[1]) {\r\n end_frame_image = {\r\n format: \"\",\r\n height: height,\r\n id: util.uuid(),\r\n image_uri: uploadIDs[1],\r\n name: \"\",\r\n platform_type: 1,\r\n source_from: \"upload\",\r\n type: \"image\",\r\n uri: uploadIDs[1],\r\n width: width,\r\n };\r\n logger.info(`设置尾帧图片: ${uploadIDs[1]}`);\r\n }\r\n } else if (filePaths && filePaths.length > 0) {\r\n let uploadIDs: string[] = [];\r\n logger.info(`开始上传 ${filePaths.length} 张图片用于视频生成`);\r\n \r\n for (let i = 0; i < filePaths.length; i++) {\r\n const filePath = filePaths[i];\r\n if (!filePath) {\r\n logger.warn(`第 ${i + 1} 张图片路径为空,跳过`);\r\n continue;\r\n }\r\n \r\n try {\r\n logger.info(`开始上传第 ${i + 1} 张图片: ${filePath}`);\r\n \r\n // 使用Amazon S3上传方式\r\n const imageUri = await uploadImageForVideo(filePath, refreshToken);\r\n \r\n if (imageUri) {\r\n uploadIDs.push(imageUri);\r\n logger.info(`第 ${i + 1} 张图片上传成功: ${imageUri}`);\r\n } else {\r\n logger.error(`第 ${i + 1} 张图片上传失败: 未获取到 image_uri`);\r\n }\r\n } catch (error) {\r\n logger.error(`第 ${i + 1} 张图片上传失败: ${error.message}`);\r\n \r\n // 图片上传失败时,停止视频生成避免浪费积分\r\n if (i === 0) {\r\n logger.error(`首帧图片上传失败,停止视频生成以避免浪费积分`);\r\n throw new APIException(EX.API_REQUEST_FAILED, `首帧图片上传失败: ${error.message}`);\r\n } else {\r\n logger.warn(`第 ${i + 1} 张图片上传失败,将跳过此图片继续处理`);\r\n }\r\n }\r\n }\r\n \r\n logger.info(`图片上传完成,成功上传 ${uploadIDs.length} 张图片`);\r\n \r\n // 如果没有成功上传任何图片,停止视频生成\r\n if (uploadIDs.length === 0) {\r\n logger.error(`所有图片上传失败,停止视频生成以避免浪费积分`);\r\n throw new APIException(EX.API_REQUEST_FAILED, '所有图片上传失败,请检查图片URL是否有效');\r\n }\r\n \r\n // 构建首帧图片对象\r\n if (uploadIDs[0]) {\r\n first_frame_image = {\r\n format: \"\",\r\n height: height,\r\n id: util.uuid(),\r\n image_uri: uploadIDs[0],\r\n name: \"\",\r\n platform_type: 1,\r\n source_from: \"upload\",\r\n type: \"image\",\r\n uri: uploadIDs[0],\r\n width: width,\r\n };\r\n logger.info(`设置首帧图片: ${uploadIDs[0]}`);\r\n }\r\n \r\n // 构建尾帧图片对象\r\n if (uploadIDs[1]) {\r\n end_frame_image = {\r\n format: \"\",\r\n height: height,\r\n id: util.uuid(),\r\n image_uri: uploadIDs[1],\r\n name: \"\",\r\n platform_type: 1,\r\n source_from: \"upload\",\r\n type: \"image\",\r\n uri: uploadIDs[1],\r\n width: width,\r\n };\r\n logger.info(`设置尾帧图片: ${uploadIDs[1]}`);\r\n } else if (filePaths.length > 1) {\r\n logger.warn(`第二张图片上传失败或未提供,将仅使用首帧图片`);\r\n }\r\n } else {\r\n logger.info(`未提供图片文件,将进行纯文本视频生成`);\r\n }\r\n\r\n const componentId = util.uuid();\r\n const metricsExtra = JSON.stringify({\r\n \"enterFrom\": \"click\",\r\n \"isDefaultSeed\": 1,\r\n \"promptSource\": \"custom\",\r\n \"isRegenerate\": false,\r\n \"originSubmitId\": util.uuid(),\r\n });\r\n \r\n // 获取当前模型的 draft 版本\r\n const draftVersion = MODEL_DRAFT_VERSIONS[_model] || DEFAULT_DRAFT_VERSION;\r\n \r\n // 计算视频宽高比\r\n const gcd = (a: number, b: number): number => b === 0 ? a : gcd(b, a % b);\r\n const divisor = gcd(width, height);\r\n const aspectRatio = `${width / divisor}:${height / divisor}`;\r\n \r\n // 构建请求参数\r\n const { aigc_data } = await request(\r\n \"post\",\r\n \"/mweb/v1/aigc_draft/generate\",\r\n refreshToken,\r\n {\r\n params: {\r\n aigc_features: \"app_lip_sync\",\r\n web_version: \"6.6.0\",\r\n da_version: draftVersion,\r\n },\r\n data: {\r\n \"extend\": {\r\n \"root_model\": end_frame_image ? MODEL_MAP['jimeng-video-3.0'] : model,\r\n \"m_video_commerce_info\": {\r\n benefit_type: \"basic_video_operation_vgfm_v_three\",\r\n resource_id: \"generate_video\",\r\n resource_id_type: \"str\",\r\n resource_sub_type: \"aigc\"\r\n },\r\n \"m_video_commerce_info_list\": [{\r\n benefit_type: \"basic_video_operation_vgfm_v_three\",\r\n resource_id: \"generate_video\",\r\n resource_id_type: \"str\",\r\n resource_sub_type: \"aigc\"\r\n }]\r\n },\r\n \"submit_id\": util.uuid(),\r\n \"metrics_extra\": metricsExtra,\r\n \"draft_content\": JSON.stringify({\r\n \"type\": \"draft\",\r\n \"id\": util.uuid(),\r\n \"min_version\": \"3.0.5\",\r\n \"is_from_tsn\": true,\r\n \"version\": draftVersion,\r\n \"main_component_id\": componentId,\r\n \"component_list\": [{\r\n \"type\": \"video_base_component\",\r\n \"id\": componentId,\r\n \"min_version\": \"1.0.0\",\r\n \"metadata\": {\r\n \"type\": \"\",\r\n \"id\": util.uuid(),\r\n \"created_platform\": 3,\r\n \"created_platform_version\": \"\",\r\n \"created_time_in_ms\": Date.now(),\r\n \"created_did\": \"\"\r\n },\r\n \"generate_type\": \"gen_video\",\r\n \"aigc_mode\": \"workbench\",\r\n \"abilities\": {\r\n \"type\": \"\",\r\n \"id\": util.uuid(),\r\n \"gen_video\": {\r\n \"id\": util.uuid(),\r\n \"type\": \"\",\r\n \"text_to_video_params\": {\r\n \"type\": \"\",\r\n \"id\": util.uuid(),\r\n \"model_req_key\": model,\r\n \"priority\": 0,\r\n \"seed\": Math.floor(Math.random() * 100000000) + 2500000000,\r\n \"video_aspect_ratio\": aspectRatio,\r\n \"video_gen_inputs\": [{\r\n duration_ms: duration * 1000,\r\n first_frame_image: first_frame_image,\r\n end_frame_image: end_frame_image,\r\n fps: 24,\r\n id: util.uuid(),\r\n min_version: \"3.0.5\",\r\n prompt: prompt,\r\n resolution: resolution,\r\n type: \"\",\r\n video_mode: 2\r\n }]\r\n },\r\n \"video_task_extra\": metricsExtra,\r\n }\r\n }\r\n }],\r\n }),\r\n http_common_info: {\r\n aid: DEFAULT_ASSISTANT_ID,\r\n },\r\n },\r\n }\r\n );\r\n\r\n const historyId = aigc_data.history_record_id;\r\n if (!historyId)\r\n throw new APIException(EX.API_IMAGE_GENERATION_FAILED, \"记录ID不存在\");\r\n\r\n // 轮询获取结果\r\n let status = 20, failCode, item_list = [];\r\n let retryCount = 0;\r\n const maxRetries = 60; // 增加重试次数,支持约20分钟的总重试时间\r\n \r\n // 首次查询前等待更长时间,让服务器有时间处理请求\r\n await new Promise((resolve) => setTimeout(resolve, 5000));\r\n \r\n logger.info(`开始轮询视频生成结果,历史ID: ${historyId},最大重试次数: ${maxRetries}`);\r\n logger.info(`即梦官网API地址: https://jimeng.jianying.com/mweb/v1/get_history_by_ids`);\r\n logger.info(`视频生成请求已发送,请同时在即梦官网查看: https://jimeng.jianying.com/ai-tool/video/generate`);\r\n \r\n while (status === 20 && retryCount < maxRetries) {\r\n try {\r\n // 构建请求URL和参数\r\n const requestUrl = \"/mweb/v1/get_history_by_ids\";\r\n const requestData = {\r\n history_ids: [historyId],\r\n };\r\n \r\n // 尝试两种不同的API请求方式\r\n let result;\r\n let useAlternativeApi = retryCount > 10 && retryCount % 2 === 0; // 在重试10次后,每隔一次尝试备用API\r\n \r\n if (useAlternativeApi) {\r\n // 备用API请求方式\r\n logger.info(`尝试备用API请求方式,URL: ${requestUrl}, 历史ID: ${historyId}, 重试次数: ${retryCount + 1}/${maxRetries}`);\r\n const alternativeRequestData = {\r\n history_record_ids: [historyId],\r\n };\r\n result = await request(\"post\", \"/mweb/v1/get_history_records\", refreshToken, {\r\n data: alternativeRequestData,\r\n });\r\n logger.info(`备用API响应摘要: ${JSON.stringify(result).substring(0, 500)}...`);\r\n } else {\r\n // 标准API请求方式\r\n logger.info(`发送请求获取视频生成结果,URL: ${requestUrl}, 历史ID: ${historyId}, 重试次数: ${retryCount + 1}/${maxRetries}`);\r\n result = await request(\"post\", requestUrl, refreshToken, {\r\n data: requestData,\r\n });\r\n const responseStr = JSON.stringify(result);\r\n logger.info(`标准API响应摘要: ${responseStr.substring(0, 300)}...`);\r\n }\r\n \r\n\r\n // 检查结果是否有效\r\n let historyData;\r\n \r\n if (useAlternativeApi && result.history_records && result.history_records.length > 0) {\r\n // 处理备用API返回的数据格式\r\n historyData = result.history_records[0];\r\n logger.info(`从备用API获取到历史记录`);\r\n } else if (result.history_list && result.history_list.length > 0) {\r\n // 处理标准API返回的数据格式\r\n historyData = result.history_list[0];\r\n logger.info(`从标准API获取到历史记录`);\r\n } else if (result[historyId]) {\r\n // get_history_by_ids 返回数据以 historyId 为键(如 result[\"8918159809292\"])\r\n historyData = result[historyId];\r\n logger.info(`从historyId键获取到历史记录`);\r\n } else {\r\n // 所有API都没有返回有效数据\r\n logger.warn(`历史记录不存在,重试中 (${retryCount + 1}/${maxRetries})... 历史ID: ${historyId}`);\r\n logger.info(`请同时在即梦官网检查视频是否已生成: https://jimeng.jianying.com/ai-tool/video/generate`);\r\n\r\n retryCount++;\r\n // 增加重试间隔时间,但设置上限为30秒\r\n const waitTime = Math.min(2000 * (retryCount + 1), 30000);\r\n logger.info(`等待 ${waitTime}ms 后进行第 ${retryCount + 1} 次重试`);\r\n await new Promise((resolve) => setTimeout(resolve, waitTime));\r\n continue;\r\n }\r\n \r\n // 记录获取到的结果详情\r\n logger.info(`获取到历史记录结果: ${JSON.stringify(historyData)}`);\r\n \r\n\r\n // 从历史数据中提取状态和结果\r\n status = historyData.status;\r\n failCode = historyData.fail_code;\r\n item_list = historyData.item_list || [];\r\n \r\n logger.info(`视频生成状态: ${status}, 失败代码: ${failCode || '无'}, 项目列表长度: ${item_list.length}`);\r\n \r\n // 如果有视频URL,提前记录\r\n let tempVideoUrl = item_list?.[0]?.video?.transcoded_video?.origin?.video_url;\r\n if (!tempVideoUrl) {\r\n // 尝试从其他可能的路径获取\r\n tempVideoUrl = item_list?.[0]?.video?.play_url || \r\n item_list?.[0]?.video?.download_url || \r\n item_list?.[0]?.video?.url;\r\n }\r\n \r\n if (tempVideoUrl) {\r\n logger.info(`检测到视频URL: ${tempVideoUrl}`);\r\n }\r\n\r\n if (status === 30) {\r\n const error = failCode === 2038 \r\n ? new APIException(EX.API_CONTENT_FILTERED, \"内容被过滤\")\r\n : new APIException(EX.API_IMAGE_GENERATION_FAILED, `生成失败,错误码: ${failCode}`);\r\n // 添加历史ID到错误对象,以便在chat.ts中显示\r\n error.historyId = historyId;\r\n throw error;\r\n }\r\n \r\n // 如果状态仍在处理中,等待后继续\r\n if (status === 20) {\r\n const waitTime = 2000 * (Math.min(retryCount + 1, 5)); // 随着重试次数增加等待时间,但最多10秒\r\n logger.info(`视频生成中,状态码: ${status},等待 ${waitTime}ms 后继续查询`);\r\n await new Promise((resolve) => setTimeout(resolve, waitTime));\r\n }\r\n } catch (error) {\r\n logger.error(`轮询视频生成结果出错: ${error.message}`);\r\n retryCount++;\r\n await new Promise((resolve) => setTimeout(resolve, 2000 * (retryCount + 1)));\r\n }\r\n }\r\n \r\n // 如果达到最大重试次数仍未成功\r\n if (retryCount >= maxRetries && status === 20) {\r\n logger.error(`视频生成超时,已尝试 ${retryCount} 次,总耗时约 ${Math.floor(retryCount * 2000 / 1000 / 60)} 分钟`);\r\n const error = new APIException(EX.API_IMAGE_GENERATION_FAILED, \"获取视频生成结果超时,请稍后在即梦官网查看您的视频\");\r\n // 添加历史ID到错误对象,以便在chat.ts中显示\r\n error.historyId = historyId;\r\n throw error;\r\n }\r\n\r\n // 尝试通过 get_local_item_list 获取高质量视频下载URL\r\n const itemId = item_list?.[0]?.item_id\r\n || item_list?.[0]?.id\r\n || item_list?.[0]?.local_item_id\r\n || item_list?.[0]?.common_attr?.id;\r\n\r\n if (itemId) {\r\n try {\r\n const hqVideoUrl = await fetchHighQualityVideoUrl(String(itemId), refreshToken);\r\n if (hqVideoUrl) {\r\n logger.info(`视频生成成功(高质量),URL: ${hqVideoUrl}`);\r\n return hqVideoUrl;\r\n }\r\n } catch (error) {\r\n logger.warn(`获取高质量视频URL失败,将使用预览URL作为回退: ${error.message}`);\r\n }\r\n } else {\r\n logger.warn(`未能从item_list中提取item_id,将使用预览URL。item_list[0]键: ${item_list?.[0] ? Object.keys(item_list[0]).join(', ') : '无'}`);\r\n }\r\n\r\n // 回退:提取预览视频URL\r\n let videoUrl = item_list?.[0]?.video?.transcoded_video?.origin?.video_url;\r\n \r\n // 如果通过常规路径无法获取视频URL,尝试其他可能的路径\r\n if (!videoUrl) {\r\n // 尝试从item_list中的其他可能位置获取\r\n if (item_list?.[0]?.video?.play_url) {\r\n videoUrl = item_list[0].video.play_url;\r\n logger.info(`从play_url获取到视频URL: ${videoUrl}`);\r\n } else if (item_list?.[0]?.video?.download_url) {\r\n videoUrl = item_list[0].video.download_url;\r\n logger.info(`从download_url获取到视频URL: ${videoUrl}`);\r\n } else if (item_list?.[0]?.video?.url) {\r\n videoUrl = item_list[0].video.url;\r\n logger.info(`从url获取到视频URL: ${videoUrl}`);\r\n } else {\r\n // 如果仍然找不到,记录错误并抛出异常\r\n logger.error(`未能获取视频URL,item_list: ${JSON.stringify(item_list)}`);\r\n const error = new APIException(EX.API_IMAGE_GENERATION_FAILED, \"未能获取视频URL,请稍后在即梦官网查看\");\r\n // 添加历史ID到错误对象,以便在chat.ts中显示\r\n error.historyId = historyId;\r\n throw error;\r\n }\r\n }\r\n\r\n logger.info(`视频生成成功,URL: ${videoUrl}`);\r\n return videoUrl;\r\n}\r\n\r\n/**\r\n * Seedance 2.0 多图智能视频生成\r\n * 支持多张图片与文本混合生成视频\r\n *\r\n * @param _model 模型名称\r\n * @param prompt 提示词(支持 @1 @2 等引用图片占位符)\r\n * @param options 选项\r\n * @param refreshToken 刷新令牌\r\n * @returns 视频URL\r\n */\r\nexport async function generateSeedanceVideo(\r\n _model: string,\r\n prompt: string,\r\n {\r\n ratio = \"4:3\",\r\n resolution = \"720p\",\r\n duration = 4,\r\n filePaths = [],\r\n files = [],\r\n }: {\r\n ratio?: string;\r\n resolution?: string;\r\n duration?: number;\r\n filePaths?: string[];\r\n files?: any[];\r\n },\r\n refreshToken: string\r\n) {\r\n const model = getModel(_model);\r\n const benefitType = SEEDANCE_BENEFIT_TYPE_MAP[_model] || \"dreamina_video_seedance_20_pro\";\r\n\r\n // Seedance 2.0 默认时长为4秒\r\n const actualDuration = duration || 4;\r\n\r\n // 解析分辨率参数获取实际的宽高\r\n const { width, height } = resolveVideoResolution(resolution, ratio);\r\n\r\n logger.info(`Seedance 2.0 生成: 模型=${_model} 映射=${model} ${width}x${height} (${ratio}@${resolution}) 时长=${actualDuration}秒`);\r\n\r\n // 检查积分\r\n const { totalCredit } = await getCredit(refreshToken);\r\n if (totalCredit <= 0)\r\n await receiveCredit(refreshToken);\r\n\r\n // 上传所有文件(支持图片/视频/音频)\r\n let uploadedMaterials: UploadedMaterial[] = [];\r\n\r\n // 处理上传的文件(multipart/form-data)\r\n if (files && files.length > 0) {\r\n logger.info(`Seedance: 开始处理 ${files.length} 个上传文件`);\r\n\r\n for (let i = 0; i < files.length; i++) {\r\n const file = files[i];\r\n if (!file || !file.filepath) {\r\n logger.warn(`Seedance: 第 ${i + 1} 个文件无效,跳过`);\r\n continue;\r\n }\r\n\r\n const materialType = detectMaterialType(file);\r\n try {\r\n logger.info(`Seedance: 开始上传第 ${i + 1} 个文件 (${materialType}): ${file.originalFilename || file.filepath}`);\r\n const buffer = fs.readFileSync(file.filepath);\r\n\r\n if (materialType === \"image\") {\r\n const imageUri = await uploadImageBufferForVideo(buffer, refreshToken);\r\n if (imageUri) {\r\n uploadedMaterials.push({ type: \"image\", uri: imageUri, width, height });\r\n logger.info(`Seedance: 第 ${i + 1} 个图片上传成功: ${imageUri}`);\r\n }\r\n } else {\r\n // 视频或音频 → VOD 上传\r\n const vodResult = await uploadMediaForVideo(buffer, materialType, refreshToken, file.originalFilename);\r\n uploadedMaterials.push({\r\n type: materialType,\r\n vid: vodResult.vid,\r\n width: vodResult.width,\r\n height: vodResult.height,\r\n duration: vodResult.duration,\r\n fps: vodResult.fps,\r\n name: file.originalFilename || \"\",\r\n });\r\n logger.info(`Seedance: 第 ${i + 1} 个${materialType === \"video\" ? \"视频\" : \"音频\"}上传成功: ${vodResult.vid}`);\r\n }\r\n } catch (error) {\r\n logger.error(`Seedance: 第 ${i + 1} 个文件上传失败: ${error.message}`);\r\n if (i === 0) {\r\n throw new APIException(EX.API_REQUEST_FAILED, `首个文件上传失败: ${error.message}`);\r\n }\r\n }\r\n }\r\n } else if (filePaths && filePaths.length > 0) {\r\n logger.info(`Seedance: 开始上传 ${filePaths.length} 个文件`);\r\n\r\n for (let i = 0; i < filePaths.length; i++) {\r\n const filePath = filePaths[i];\r\n if (!filePath) continue;\r\n\r\n const materialType = detectMaterialTypeFromUrl(filePath);\r\n try {\r\n logger.info(`Seedance: 开始上传第 ${i + 1} 个文件 (${materialType}): ${filePath}`);\r\n\r\n if (materialType === \"image\") {\r\n const imageUri = await uploadImageForVideo(filePath, refreshToken);\r\n if (imageUri) {\r\n uploadedMaterials.push({ type: \"image\", uri: imageUri, width, height });\r\n logger.info(`Seedance: 第 ${i + 1} 个图片上传成功: ${imageUri}`);\r\n }\r\n } else {\r\n // 视频或音频 URL → 下载后 VOD 上传\r\n const response = await fetch(filePath);\r\n if (!response.ok) throw new Error(`下载文件失败: ${response.status}`);\r\n const arrayBuffer = await response.arrayBuffer();\r\n const buffer = Buffer.from(arrayBuffer);\r\n const vodResult = await uploadMediaForVideo(buffer, materialType, refreshToken);\r\n uploadedMaterials.push({\r\n type: materialType,\r\n vid: vodResult.vid,\r\n width: vodResult.width,\r\n height: vodResult.height,\r\n duration: vodResult.duration,\r\n fps: vodResult.fps,\r\n });\r\n logger.info(`Seedance: 第 ${i + 1} 个${materialType === \"video\" ? \"视频\" : \"音频\"}上传成功: ${vodResult.vid}`);\r\n }\r\n } catch (error) {\r\n logger.error(`Seedance: 第 ${i + 1} 个文件上传失败: ${error.message}`);\r\n if (i === 0) {\r\n throw new APIException(EX.API_REQUEST_FAILED, `首个文件上传失败: ${error.message}`);\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (uploadedMaterials.length === 0) {\r\n throw new APIException(EX.API_REQUEST_FAILED, 'Seedance 2.0 需要至少一个文件(图片/视频/音频)');\r\n }\r\n\r\n logger.info(`Seedance: 成功上传 ${uploadedMaterials.length} 个文件`);\r\n\r\n // 动态 benefit_type:包含视频素材时追加 _with_video 后缀\r\n const hasVideoMaterial = uploadedMaterials.some(m => m.type === \"video\");\r\n const finalBenefitType = hasVideoMaterial ? `${benefitType}_with_video` : benefitType;\r\n\r\n // 构建 material_list(支持图片/视频/音频)\r\n const materialList = uploadedMaterials.map((mat) => {\r\n const base = { type: \"\", id: util.uuid() };\r\n if (mat.type === \"image\") {\r\n return {\r\n ...base,\r\n material_type: \"image\",\r\n image_info: {\r\n type: \"image\",\r\n id: util.uuid(),\r\n source_from: \"upload\",\r\n platform_type: 1,\r\n name: \"\",\r\n image_uri: mat.uri,\r\n aigc_image: { type: \"\", id: util.uuid() },\r\n width: mat.width,\r\n height: mat.height,\r\n format: \"\",\r\n uri: mat.uri,\r\n }\r\n };\r\n } else if (mat.type === \"video\") {\r\n return {\r\n ...base,\r\n material_type: \"video\",\r\n video_info: {\r\n type: \"video\",\r\n id: util.uuid(),\r\n source_from: \"upload\",\r\n name: mat.name || \"\",\r\n vid: mat.vid,\r\n fps: mat.fps || 0,\r\n width: mat.width || 0,\r\n height: mat.height || 0,\r\n duration: mat.duration || 0,\r\n }\r\n };\r\n } else {\r\n // audio\r\n return {\r\n ...base,\r\n material_type: \"audio\",\r\n audio_info: {\r\n type: \"audio\",\r\n id: util.uuid(),\r\n source_from: \"upload\",\r\n vid: mat.vid,\r\n duration: mat.duration || 0,\r\n name: mat.name || \"\",\r\n }\r\n };\r\n }\r\n });\r\n\r\n // 解析 prompt 中的素材占位符(@1, @2 等)并构建 meta_list\r\n const metaList = buildMetaListFromPrompt(prompt, uploadedMaterials);\r\n\r\n const componentId = util.uuid();\r\n const submitId = util.uuid();\r\n const draftVersion = MODEL_DRAFT_VERSIONS[_model] || \"3.3.9\";\r\n\r\n // 计算视频宽高比\r\n const gcd = (a: number, b: number): number => b === 0 ? a : gcd(b, a % b);\r\n const divisor = gcd(width, height);\r\n const aspectRatio = `${width / divisor}:${height / divisor}`;\r\n\r\n const metricsExtra = JSON.stringify({\r\n isDefaultSeed: 1,\r\n originSubmitId: submitId,\r\n isRegenerate: false,\r\n enterFrom: \"click\",\r\n position: \"page_bottom_box\",\r\n functionMode: \"omni_reference\",\r\n sceneOptions: JSON.stringify([{\r\n type: \"video\",\r\n scene: \"BasicVideoGenerateButton\",\r\n modelReqKey: model,\r\n videoDuration: actualDuration,\r\n reportParams: {\r\n enterSource: \"generate\",\r\n vipSource: \"generate\",\r\n extraVipFunctionKey: model,\r\n useVipFunctionDetailsReporterHoc: true\r\n },\r\n materialTypes: [...new Set(uploadedMaterials.map(m => MATERIAL_TYPE_CODE[m.type]))]\r\n }])\r\n });\r\n\r\n // 构建 Seedance 2.0 专用请求(通过浏览器代理,绕过 shark a_bogus 检测)\r\n const token = await acquireToken(refreshToken);\r\n const generateQueryParams = new URLSearchParams({\r\n aid: String(CORE_ASSISTANT_ID),\r\n device_platform: \"web\",\r\n region: \"cn\",\r\n webId: String(WEB_ID),\r\n da_version: draftVersion,\r\n web_component_open_flag: \"1\",\r\n web_version: \"7.5.0\",\r\n aigc_features: \"app_lip_sync\",\r\n });\r\n const generateUrl = `https://jimeng.jianying.com/mweb/v1/aigc_draft/generate?${generateQueryParams.toString()}`;\r\n const generateBody = {\r\n extend: {\r\n root_model: model,\r\n m_video_commerce_info: {\r\n benefit_type: finalBenefitType,\r\n resource_id: \"generate_video\",\r\n resource_id_type: \"str\",\r\n resource_sub_type: \"aigc\"\r\n },\r\n m_video_commerce_info_list: [{\r\n benefit_type: finalBenefitType,\r\n resource_id: \"generate_video\",\r\n resource_id_type: \"str\",\r\n resource_sub_type: \"aigc\"\r\n }]\r\n },\r\n submit_id: submitId,\r\n metrics_extra: metricsExtra,\r\n draft_content: JSON.stringify({\r\n type: \"draft\",\r\n id: util.uuid(),\r\n min_version: draftVersion,\r\n min_features: [\"AIGC_Video_UnifiedEdit\"],\r\n is_from_tsn: true,\r\n version: draftVersion,\r\n main_component_id: componentId,\r\n component_list: [{\r\n type: \"video_base_component\",\r\n id: componentId,\r\n min_version: \"1.0.0\",\r\n aigc_mode: \"workbench\",\r\n metadata: {\r\n type: \"\",\r\n id: util.uuid(),\r\n created_platform: 3,\r\n created_platform_version: \"\",\r\n created_time_in_ms: String(Date.now()),\r\n created_did: \"\"\r\n },\r\n generate_type: \"gen_video\",\r\n abilities: {\r\n type: \"\",\r\n id: util.uuid(),\r\n gen_video: {\r\n type: \"\",\r\n id: util.uuid(),\r\n text_to_video_params: {\r\n type: \"\",\r\n id: util.uuid(),\r\n video_gen_inputs: [{\r\n type: \"\",\r\n id: util.uuid(),\r\n min_version: draftVersion,\r\n prompt: \"\", // Seedance 2.0 prompt 在 meta_list 中\r\n video_mode: 2,\r\n fps: 24,\r\n duration_ms: actualDuration * 1000,\r\n idip_meta_list: [],\r\n unified_edit_input: {\r\n type: \"\",\r\n id: util.uuid(),\r\n material_list: materialList,\r\n meta_list: metaList\r\n }\r\n }],\r\n video_aspect_ratio: aspectRatio,\r\n seed: Math.floor(Math.random() * 1000000000),\r\n model_req_key: model,\r\n priority: 0\r\n },\r\n video_task_extra: metricsExtra\r\n }\r\n },\r\n process_type: 1\r\n }]\r\n }),\r\n http_common_info: {\r\n aid: CORE_ASSISTANT_ID,\r\n },\r\n };\r\n\r\n logger.info(`Seedance: 通过浏览器代理发送 generate 请求...`);\r\n const generateResult = await browserService.fetch(\r\n token,\r\n generateUrl,\r\n {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(generateBody),\r\n }\r\n );\r\n\r\n // 检查浏览器代理返回的结果\r\n const { ret, errmsg, data: generateData } = generateResult;\r\n if (ret !== undefined && Number(ret) !== 0) {\r\n if (Number(ret) === 5000) {\r\n throw new APIException(EX.API_IMAGE_GENERATION_INSUFFICIENT_POINTS, `[无法生成视频]: 即梦积分可能不足,${errmsg}`);\r\n }\r\n throw new APIException(EX.API_REQUEST_FAILED, `[请求jimeng失败]: ${errmsg}`);\r\n }\r\n const aigc_data = generateData?.aigc_data || generateResult.aigc_data;\r\n\r\n const historyId = aigc_data.history_record_id;\r\n if (!historyId)\r\n throw new APIException(EX.API_IMAGE_GENERATION_FAILED, \"记录ID不存在\");\r\n\r\n // 轮询获取结果(与普通视频相同的逻辑)\r\n let status = 20, failCode, item_list = [];\r\n let retryCount = 0;\r\n const maxRetries = 60;\r\n\r\n await new Promise((resolve) => setTimeout(resolve, 5000));\r\n\r\n logger.info(`Seedance: 开始轮询视频生成结果,历史ID: ${historyId}`);\r\n\r\n while (status === 20 && retryCount < maxRetries) {\r\n try {\r\n const result = await request(\"post\", \"/mweb/v1/get_history_by_ids\", refreshToken, {\r\n data: { history_ids: [historyId] },\r\n });\r\n\r\n const responseStr = JSON.stringify(result);\r\n logger.info(`Seedance: 轮询响应摘要: ${responseStr.substring(0, 300)}...`);\r\n\r\n // get_history_by_ids 返回的数据可能以 historyId 为键(如 result[\"8918159809292\"]),\r\n // 也可能在 result.history_list 数组中\r\n let historyData = result.history_list?.[0] || result[historyId];\r\n\r\n if (!historyData) {\r\n retryCount++;\r\n const waitTime = Math.min(2000 * (retryCount + 1), 30000);\r\n await new Promise((resolve) => setTimeout(resolve, waitTime));\r\n continue;\r\n }\r\n status = historyData.status;\r\n failCode = historyData.fail_code;\r\n item_list = historyData.item_list || [];\r\n\r\n logger.info(`Seedance: 状态=${status}, 失败码=${failCode || '无'}`);\r\n\r\n if (status === 30) {\r\n const error = failCode === 2038\r\n ? new APIException(EX.API_CONTENT_FILTERED, \"内容被过滤\")\r\n : new APIException(EX.API_IMAGE_GENERATION_FAILED, `生成失败,错误码: ${failCode}`);\r\n error.historyId = historyId;\r\n throw error;\r\n }\r\n\r\n if (status === 20) {\r\n const waitTime = 2000 * Math.min(retryCount + 1, 5);\r\n await new Promise((resolve) => setTimeout(resolve, waitTime));\r\n }\r\n\r\n retryCount++;\r\n } catch (error) {\r\n if (error instanceof APIException) throw error;\r\n logger.error(`Seedance: 轮询出错: ${error.message}`);\r\n retryCount++;\r\n await new Promise((resolve) => setTimeout(resolve, 2000 * (retryCount + 1)));\r\n }\r\n }\r\n\r\n if (retryCount >= maxRetries && status === 20) {\r\n const error = new APIException(EX.API_IMAGE_GENERATION_FAILED, \"视频生成超时\");\r\n error.historyId = historyId;\r\n throw error;\r\n }\r\n\r\n // 尝试通过 get_local_item_list 获取高质量视频下载URL\r\n const seedanceItemId = item_list?.[0]?.item_id\r\n || item_list?.[0]?.id\r\n || item_list?.[0]?.local_item_id\r\n || item_list?.[0]?.common_attr?.id;\r\n\r\n if (seedanceItemId) {\r\n try {\r\n const hqVideoUrl = await fetchHighQualityVideoUrl(String(seedanceItemId), refreshToken);\r\n if (hqVideoUrl) {\r\n logger.info(`Seedance: 视频生成成功(高质量),URL: ${hqVideoUrl}`);\r\n return hqVideoUrl;\r\n }\r\n } catch (error) {\r\n logger.warn(`Seedance: 获取高质量视频URL失败,将使用预览URL作为回退: ${error.message}`);\r\n }\r\n } else {\r\n logger.warn(`Seedance: 未能从item_list中提取item_id,将使用预览URL。item_list[0]键: ${item_list?.[0] ? Object.keys(item_list[0]).join(', ') : '无'}`);\r\n }\r\n\r\n // 回退:提取预览视频URL\r\n let videoUrl = item_list?.[0]?.video?.transcoded_video?.origin?.video_url\r\n || item_list?.[0]?.video?.play_url\r\n || item_list?.[0]?.video?.download_url\r\n || item_list?.[0]?.video?.url;\r\n\r\n if (!videoUrl) {\r\n const error = new APIException(EX.API_IMAGE_GENERATION_FAILED, \"未能获取视频URL\");\r\n error.historyId = historyId;\r\n throw error;\r\n }\r\n\r\n logger.info(`Seedance: 视频生成成功,URL: ${videoUrl}`);\r\n return videoUrl;\r\n}\r\n\r\n/**\r\n * 解析 prompt 中的素材占位符并构建 meta_list\r\n * 支持格式: \"使用 @1 图片,@2 图片做动画\" -> [text, material(0), text, material(1), text]\r\n * meta_type 根据素材实际类型动态匹配(image/video/audio)\r\n */\r\nfunction buildMetaListFromPrompt(prompt: string, materials: Array<{ type: SeedanceMaterialType }>): Array<{meta_type: string, text?: string, material_ref?: {material_idx: number}}> {\r\n const metaList: Array<{meta_type: string, text?: string, material_ref?: {material_idx: number}}> = [];\r\n const materialCount = materials.length;\r\n\r\n // 匹配 @1, @2, @图1, @图2, @image1 等格式\r\n const placeholderRegex = /@(?:图|image)?(\\d+)/gi;\r\n\r\n let lastIndex = 0;\r\n let match;\r\n\r\n while ((match = placeholderRegex.exec(prompt)) !== null) {\r\n // 添加占位符前的文本\r\n if (match.index > lastIndex) {\r\n const textBefore = prompt.substring(lastIndex, match.index);\r\n if (textBefore.trim()) {\r\n metaList.push({ meta_type: \"text\", text: textBefore });\r\n }\r\n }\r\n\r\n // 添加素材引用(使用对应素材的类型作为 meta_type)\r\n const materialIndex = parseInt(match[1]) - 1; // @1 对应 index 0\r\n if (materialIndex >= 0 && materialIndex < materialCount) {\r\n metaList.push({\r\n meta_type: materials[materialIndex].type,\r\n text: \"\",\r\n material_ref: { material_idx: materialIndex }\r\n });\r\n }\r\n\r\n lastIndex = match.index + match[0].length;\r\n }\r\n\r\n // 添加剩余的文本\r\n if (lastIndex < prompt.length) {\r\n const remainingText = prompt.substring(lastIndex);\r\n if (remainingText.trim()) {\r\n metaList.push({ meta_type: \"text\", text: remainingText });\r\n }\r\n }\r\n\r\n // 如果没有找到任何占位符,默认引用所有素材并附加整个prompt作为文本\r\n if (metaList.length === 0) {\r\n // 先添加所有素材引用\r\n for (let i = 0; i < materialCount; i++) {\r\n if (i === 0) {\r\n metaList.push({ meta_type: \"text\", text: \"使用\" });\r\n }\r\n metaList.push({\r\n meta_type: materials[i].type,\r\n text: \"\",\r\n material_ref: { material_idx: i }\r\n });\r\n if (i < materialCount - 1) {\r\n metaList.push({ meta_type: \"text\", text: \"和\" });\r\n }\r\n }\r\n // 添加描述文本\r\n if (prompt && prompt.trim()) {\r\n metaList.push({ meta_type: \"text\", text: `素材,${prompt}` });\r\n } else {\r\n metaList.push({ meta_type: \"text\", text: \"素材生成视频\" });\r\n }\r\n }\r\n\r\n return metaList;\r\n}","export default {\r\n prefix: '/ping',\r\n get: {\r\n '': async () => \"pong\"\r\n }\r\n}","import _ from 'lodash';\r\n\r\nimport Request from '@/lib/request/Request.ts';\r\nimport Response from '@/lib/response/Response.ts';\r\nimport { getTokenLiveStatus, getCredit, tokenSplit } from '@/api/controllers/core.ts';\r\nimport logger from '@/lib/logger.ts';\r\n\r\nexport default {\r\n\r\n prefix: '/token',\r\n\r\n post: {\r\n\r\n '/check': async (request: Request) => {\r\n request\r\n .validate('body.token', _.isString)\r\n const live = await getTokenLiveStatus(request.body.token);\r\n return {\r\n live\r\n }\r\n },\r\n\r\n '/points': async (request: Request) => {\r\n request\r\n .validate('headers.authorization', _.isString)\r\n // refresh_token切分\r\n const tokens = tokenSplit(request.headers.authorization);\r\n const points = await Promise.all(tokens.map(async (token) => {\r\n return {\r\n token,\r\n points: await getCredit(token)\r\n }\r\n }))\r\n return points;\r\n }\r\n\r\n }\r\n\r\n}","import _ from 'lodash';\r\n\r\nexport default {\r\n\r\n prefix: '/v1',\r\n\r\n get: {\r\n '/models': async () => {\r\n return {\r\n \"data\": [\r\n {\r\n \"id\": \"jimeng\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\"\r\n },\r\n {\r\n \"id\": \"jimeng-5.0\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI图像生成模型 5.0 版本(最新)\"\r\n },\r\n {\r\n \"id\": \"jimeng-4.6\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI图像生成模型 4.6 版本(最新)\"\r\n },\r\n {\r\n \"id\": \"jimeng-4.5\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI图像生成模型 4.5 版本\"\r\n },\r\n {\r\n \"id\": \"jimeng-4.1\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI图像生成模型 4.1 版本\"\r\n },\r\n {\r\n \"id\": \"jimeng-4.0\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI图像生成模型 4.0 版本\"\r\n },\r\n {\r\n \"id\": \"jimeng-3.1\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI图像生成模型 3.1 版本\"\r\n },\r\n {\r\n \"id\": \"jimeng-3.0\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI图像生成模型 3.0 版本\"\r\n },\r\n {\r\n \"id\": \"jimeng-2.1\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI图像生成模型 2.1 版本\"\r\n },\r\n {\r\n \"id\": \"jimeng-2.0-pro\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI图像生成模型 2.0 专业版\"\r\n },\r\n {\r\n \"id\": \"jimeng-2.0\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI图像生成模型 2.0 版本\"\r\n },\r\n {\r\n \"id\": \"jimeng-1.4\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI图像生成模型 1.4 版本\"\r\n },\r\n {\r\n \"id\": \"jimeng-xl-pro\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI图像生成模型 XL Pro 版本\"\r\n },\r\n {\r\n \"id\": \"jimeng-video-3.5-pro\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI视频生成模型 3.5 专业版\"\r\n },\r\n {\r\n \"id\": \"jimeng-video-3.0\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI视频生成模型 3.0 版本\"\r\n },\r\n {\r\n \"id\": \"jimeng-video-3.0-pro\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI视频生成模型 3.0 专业版\"\r\n },\r\n {\r\n \"id\": \"jimeng-video-2.0\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI视频生成模型 2.0 版本\"\r\n },\r\n {\r\n \"id\": \"jimeng-video-2.0-pro\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"即梦AI视频生成模型 2.0 专业版\"\r\n },\r\n {\r\n \"id\": \"jimeng-video-seedance-2.0\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"Seedance 2.0 多图智能视频生成模型(上游标准名称,支持4-15秒,多张图片混合生成视频)\"\r\n },\r\n {\r\n \"id\": \"seedance-2.0\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"Seedance 2.0 多图智能视频生成模型(jimeng-video-seedance-2.0 的别名,向后兼容)\"\r\n },\r\n {\r\n \"id\": \"seedance-2.0-pro\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"Seedance 2.0 Pro 多图智能视频生成模型(jimeng-video-seedance-2.0 的别名,向后兼容)\"\r\n },\r\n {\r\n \"id\": \"jimeng-video-seedance-2.0-fast\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"Seedance 2.0-fast 快速多图智能视频生成模型(上游标准名称,支持4-15秒)\"\r\n },\r\n {\r\n \"id\": \"seedance-2.0-fast\",\r\n \"object\": \"model\",\r\n \"owned_by\": \"jimeng-free-api\",\r\n \"description\": \"Seedance 2.0-fast 快速多图智能视频生成模型(jimeng-video-seedance-2.0-fast 的别名,向后兼容)\"\r\n }\r\n ]\r\n };\r\n }\r\n\r\n }\r\n}","import _ from 'lodash';\r\n\r\nimport Request from '@/lib/request/Request.ts';\r\nimport Response from '@/lib/response/Response.ts';\r\nimport { tokenSplit } from '@/api/controllers/core.ts';\r\nimport { generateVideo, generateSeedanceVideo, isSeedanceModel, DEFAULT_MODEL } from '@/api/controllers/videos.ts';\r\nimport util from '@/lib/util.ts';\r\n\r\nexport default {\r\n\r\n prefix: '/v1/videos',\r\n\r\n post: {\r\n\r\n '/generations': async (request: Request) => {\r\n // 检查是否使用了不支持的参数\r\n const unsupportedParams = ['size', 'width', 'height'];\r\n const bodyKeys = Object.keys(request.body);\r\n const foundUnsupported = unsupportedParams.filter(param => bodyKeys.includes(param));\r\n\r\n if (foundUnsupported.length > 0) {\r\n throw new Error(`不支持的参数: ${foundUnsupported.join(', ')}。请使用 ratio 和 resolution 参数控制视频尺寸。`);\r\n }\r\n\r\n const contentType = request.headers['content-type'] || '';\r\n const isMultiPart = contentType.startsWith('multipart/form-data');\r\n\r\n request\r\n .validate('body.model', v => _.isUndefined(v) || _.isString(v))\r\n .validate('body.prompt', v => _.isUndefined(v) || _.isString(v))\r\n .validate('body.ratio', v => _.isUndefined(v) || _.isString(v))\r\n .validate('body.resolution', v => _.isUndefined(v) || _.isString(v))\r\n .validate('body.duration', v => {\r\n if (_.isUndefined(v)) return true;\r\n // 对于 multipart/form-data,允许字符串类型的数字\r\n if (isMultiPart && typeof v === 'string') {\r\n const num = parseInt(v);\r\n // Seedance 支持 4-15 秒连续范围,普通视频支持 5 或 10 秒\r\n return (num >= 4 && num <= 15) || num === 5 || num === 10;\r\n }\r\n // 对于 JSON,要求数字类型\r\n // Seedance 支持 4-15 秒连续范围,普通视频支持 5 或 10 秒\r\n return _.isFinite(v) && ((v >= 4 && v <= 15) || v === 5 || v === 10);\r\n })\r\n .validate('body.file_paths', v => _.isUndefined(v) || _.isArray(v))\r\n .validate('body.filePaths', v => _.isUndefined(v) || _.isArray(v))\r\n .validate('body.response_format', v => _.isUndefined(v) || _.isString(v))\r\n .validate('headers.authorization', _.isString);\r\n\r\n // refresh_token切分\r\n const tokens = tokenSplit(request.headers.authorization);\r\n // 随机挑选一个refresh_token\r\n const token = _.sample(tokens);\r\n\r\n const {\r\n model = DEFAULT_MODEL,\r\n prompt,\r\n ratio = \"1:1\",\r\n resolution = \"720p\",\r\n duration = 5,\r\n file_paths = [],\r\n filePaths = [],\r\n response_format = \"url\"\r\n } = request.body;\r\n\r\n // 如果是 multipart/form-data,需要将字符串转换为数字\r\n const finalDuration = isMultiPart && typeof duration === 'string'\r\n ? parseInt(duration)\r\n : duration;\r\n\r\n // 兼容两种参数名格式:file_paths 和 filePaths\r\n const finalFilePaths = filePaths.length > 0 ? filePaths : file_paths;\r\n\r\n // 根据模型类型选择不同的生成函数\r\n let videoUrl: string;\r\n if (isSeedanceModel(model)) {\r\n // Seedance 2.0 多图智能视频生成\r\n // Seedance 默认时长为 4 秒,默认比例为 4:3\r\n const seedanceDuration = finalDuration === 5 ? 4 : finalDuration; // 如果是默认的5秒,转为4秒\r\n const seedanceRatio = ratio === \"1:1\" ? \"4:3\" : ratio; // 如果是默认的1:1,转为4:3\r\n\r\n videoUrl = await generateSeedanceVideo(\r\n model,\r\n prompt,\r\n {\r\n ratio: seedanceRatio,\r\n resolution,\r\n duration: seedanceDuration,\r\n filePaths: finalFilePaths,\r\n files: request.files,\r\n },\r\n token\r\n );\r\n } else {\r\n // 普通视频生成\r\n videoUrl = await generateVideo(\r\n model,\r\n prompt,\r\n {\r\n ratio,\r\n resolution,\r\n duration: finalDuration,\r\n filePaths: finalFilePaths,\r\n files: request.files,\r\n },\r\n token\r\n );\r\n }\r\n\r\n // 根据response_format返回不同格式的结果\r\n if (response_format === \"b64_json\") {\r\n // 获取视频内容并转换为BASE64\r\n const videoBase64 = await util.fetchFileBASE64(videoUrl);\r\n return {\r\n created: util.unixTimestamp(),\r\n data: [{\r\n b64_json: videoBase64,\r\n revised_prompt: prompt\r\n }]\r\n };\r\n } else {\r\n // 默认返回URL\r\n return {\r\n created: util.unixTimestamp(),\r\n data: [{\r\n url: videoUrl,\r\n revised_prompt: prompt\r\n }]\r\n };\r\n }\r\n }\r\n\r\n }\r\n\r\n}\r\n","import videos from './videos.ts';\r\n\r\nexport default {\r\n ...videos,\r\n prefix: '/v1/video'\r\n};\r\n"],"mappings":"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","names":["cmdArgs","envVars","path","fs","_","path","fs","_","_","path","fs","path","_","fs","path","fs","yaml","_","CONFIG_PATH","path","_","fs","yaml","path","_","fs","dateFormat","fs","path","_","dateFormat","_","mime","axios","_","axios","_","_","request","url","options","_","_","_","_","mime","_","_","_","mime","_","exceptions_default","_","exceptions_default","_","request","response","err","fs","fs","_","crypto","DEFAULT_ASSISTANT_ID","crypto","crc","_","request","_","fs","_","crypto","fs","DEFAULT_ASSISTANT_ID","DEFAULT_MODEL","MODEL_DRAFT_VERSIONS","MODEL_MAP","mime","getModel","createSignature","crypto","calculateCRC32","crc","fs","_","request","_","stream","_","request","_","_","request","_","DEFAULT_MODEL","fs"]}
|