| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- /**
- * 云函数:quicklyVideo(一键成片代理)
- * 替代:
- * POST /api/quickly/create → action=create
- * POST /api/quickly/query → action=query
- *
- * 把 server.js 里的签名 + relay 逻辑搬到云函数,
- * 隐藏 APP_KEY / APP_SECRET,前端只需传 videoUrls。
- *
- * ⚠️ 不是参考别项目,是本项目 server.js 1820~1914 行的等价实现。
- */
- const crypto = require('crypto');
- const QUICKLY_APP_KEY = 'ZmNmOGRhNjYzZTAx';
- const QUICKLY_APP_SECRET = 'eaa12154c248cad9159a9d6ea8bedf46';
- const QUICKLY_ACCOUNT_ID = '12859_117409';
- const QUICKLY_CALLBACK_URL = 'https://server.fmode.cn/api/functions/cut/onemerge';
- const QUICKLY_RELAY_URL = 'https://server.fmode.cn/api/functions';
- // 上游筷子代理云函数 ID(fmode 平台已有)
- const UPSTREAM_FN_ID = 'sWvRr8RvPT';
- async function handler(request, response) {
- try {
- const action = pickParam(request, 'action');
- if (action === 'create') {
- const videoUrls = pickParam(request, 'videoUrls');
- const options = pickParam(request, 'options') || {};
- if (!Array.isArray(videoUrls) || videoUrls.length === 0) {
- return response.json({ code: 400, success: false, error: '缺少 videoUrls 参数' });
- }
- const timestamp = Date.now().toString();
- const sign = crypto.createHash('md5').update(timestamp + '#' + QUICKLY_APP_SECRET).digest('hex');
- const apiBody = {
- account_id: QUICKLY_ACCOUNT_ID,
- callback_url: QUICKLY_CALLBACK_URL,
- material_list: videoUrls.map(url => ({ type: 'video', value: url })),
- tags: options.tags || '视频,AI生成',
- proportion: options.proportion || '9:16',
- video_duration: options.videoDuration || { min: 10, max: 30 },
- pre_id: timestamp,
- compose_number: 1,
- ai_voice: options.aiVoice ?? 1,
- ai_bgm: options.aiBgm ?? 1,
- ai_flower: 1,
- ai_subtitle: options.aiSubtitle ?? 0,
- original_voice: 0
- };
- const relayBody = {
- action: 'relay',
- relayData: JSON.stringify({
- apiPath: '/v2/video/vlog/create',
- apiBody,
- appKey: QUICKLY_APP_KEY,
- timestamp,
- sign
- })
- };
- console.log(`📦 quicklyVideo.create timestamp=${timestamp} videos=${videoUrls.length}`);
- const r = await fetch(QUICKLY_RELAY_URL, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(relayBody)
- });
- const result = await r.json();
- response.json({ code: 200, success: true, data: result });
- return;
- }
- if (action === 'query') {
- const taskId = pickParam(request, 'taskId');
- if (!taskId) return response.json({ code: 400, success: false, error: '缺少 taskId' });
- const r = await fetch(QUICKLY_RELAY_URL, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({
- id: UPSTREAM_FN_ID,
- _ApplicationId: 'ncloudmaster',
- action: 'query',
- taskId
- })
- });
- const result = await r.json();
- response.json({ code: 200, success: true, data: result });
- return;
- }
- response.json({ code: 400, success: false, error: `未知 action: ${action}` });
- } catch (error) {
- console.error('❌ quicklyVideo 失败:', error.message);
- response.json({ code: 500, success: false, error: error.message });
- }
- }
- function pickParam(request, ...names) {
- const sources = [request.params, request.body, request];
- for (const src of sources) {
- if (!src || typeof src !== 'object') continue;
- for (const n of names) {
- const v = src[n];
- if (v !== undefined && v !== null && v !== '') return v;
- }
- }
- return null;
- }
|