@shun-js/remotion-server 0.6.4 → 0.6.5
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shun-js/remotion-server",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5",
|
|
4
4
|
"description": "remotion.cool server",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "uikoo9 <uikoo9@qq.com>",
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
"@shun-js/shun-config": "^0.3.1",
|
|
24
24
|
"@shun-js/shun-service": "^0.3.1",
|
|
25
25
|
"@supabase/supabase-js": "^2.93.3",
|
|
26
|
-
"qiao-file": "^5.0.6",
|
|
27
26
|
"qiao-log": "^5.1.9",
|
|
28
27
|
"qiao-timer": "^5.8.4",
|
|
29
28
|
"qiao-z": "^5.8.9"
|
|
@@ -32,5 +31,5 @@
|
|
|
32
31
|
"access": "public",
|
|
33
32
|
"registry": "https://registry.npmjs.org/"
|
|
34
33
|
},
|
|
35
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "5e673cd548dc7ab1b20c57750e3f541fe4fa68cc"
|
|
36
35
|
}
|
package/server/util/feishu.js
CHANGED
|
@@ -15,63 +15,11 @@ exports.feishuMsg = (msg) => {
|
|
|
15
15
|
});
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
// is bot
|
|
19
|
-
function isBot(req) {
|
|
20
|
-
const ua = req.useragent;
|
|
21
|
-
const hasOSName = ua && ua.os && ua.os.name;
|
|
22
|
-
const isGoogleBot = ua && ua.browser && ua.browser.name === 'Googlebot';
|
|
23
|
-
const isMetaBot = ua && ua.browser && ua.browser.name === 'meta-externalagent';
|
|
24
|
-
const isSafariBot = ua && ua.engine && ua.engine.name === 'WebKit' && ua.engine.version === '605.1.15';
|
|
25
|
-
return !hasOSName || isGoogleBot || isMetaBot || isSafariBot;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
18
|
/**
|
|
29
19
|
* errorFeishuMsg
|
|
30
|
-
* @param {*} req
|
|
31
20
|
* @param {*} msg
|
|
32
21
|
* @returns
|
|
33
22
|
*/
|
|
34
|
-
exports.errorFeishuMsg = (
|
|
35
|
-
|
|
36
|
-
if (isBot(req)) return;
|
|
37
|
-
|
|
38
|
-
// msg
|
|
39
|
-
const uaJson = JSON.stringify(req.useragent || {});
|
|
40
|
-
exports.feishuMsg(`【通知】服务异常,${msg},请查看日志,ua:${uaJson}`);
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* chatFeishuMsg
|
|
45
|
-
* @param {*} req
|
|
46
|
-
* @returns
|
|
47
|
-
*/
|
|
48
|
-
exports.chatFeishuMsg = (req) => {
|
|
49
|
-
// check
|
|
50
|
-
if (isBot(req)) return;
|
|
51
|
-
|
|
52
|
-
// msg
|
|
53
|
-
const uaJson = JSON.stringify(req.useragent || {});
|
|
54
|
-
const userid = req.headers.userid;
|
|
55
|
-
const prompt = decodeURIComponent(req.body.userPrompt);
|
|
56
|
-
|
|
57
|
-
const msg = `【通知】/chat被访问\nuserid:${userid}\nua:\n${uaJson}\nprompt:\n${prompt}`;
|
|
58
|
-
exports.feishuMsg(msg);
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* chatResFeishuMsg
|
|
63
|
-
* @param {*} req
|
|
64
|
-
* @returns
|
|
65
|
-
*/
|
|
66
|
-
exports.chatResFeishuMsg = (req, chatRes) => {
|
|
67
|
-
// check
|
|
68
|
-
if (isBot(req)) return;
|
|
69
|
-
|
|
70
|
-
// msg
|
|
71
|
-
const uaJson = JSON.stringify(req.useragent || {});
|
|
72
|
-
const userid = req.headers.userid;
|
|
73
|
-
const prompt = decodeURIComponent(req.body.userPrompt);
|
|
74
|
-
|
|
75
|
-
const msg = `【通知】/chat生成成功\nuserid:${userid}\nua:\n${uaJson}\nprompt:\n${prompt}\nres:${chatRes}`;
|
|
76
|
-
exports.feishuMsg(msg);
|
|
23
|
+
exports.errorFeishuMsg = (msg) => {
|
|
24
|
+
exports.feishuMsg(`【通知】服务异常,${msg},请查看日志。`);
|
|
77
25
|
};
|
package/server/util/renderer.js
CHANGED
|
@@ -24,7 +24,7 @@ exports.renderVideo = async ({ sourceCode, outputPath, width, height, fps }) =>
|
|
|
24
24
|
const methodName = 'renderVideo';
|
|
25
25
|
|
|
26
26
|
// const
|
|
27
|
-
const tempDir = path.join(
|
|
27
|
+
const tempDir = path.join('/tmp', 'remotion-render', Date.now().toString());
|
|
28
28
|
const entryPoint = path.join(tempDir, 'src', 'Root.jsx');
|
|
29
29
|
|
|
30
30
|
try {
|
|
@@ -41,19 +41,28 @@ exports.renderVideo = async ({ sourceCode, outputPath, width, height, fps }) =>
|
|
|
41
41
|
version: '1.0.0',
|
|
42
42
|
dependencies: {
|
|
43
43
|
react: '^18.2.0',
|
|
44
|
+
'react-dom': '^18.2.0',
|
|
44
45
|
remotion: '^4.0.0',
|
|
45
46
|
},
|
|
46
47
|
};
|
|
47
48
|
fs.writeFileSync(path.join(tempDir, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
48
49
|
|
|
49
|
-
// 4.
|
|
50
|
+
// 4. 创建 remotion.config.js (可选但推荐)
|
|
51
|
+
const remotionConfig = `
|
|
52
|
+
module.exports = {
|
|
53
|
+
// Remotion 配置
|
|
54
|
+
};
|
|
55
|
+
`;
|
|
56
|
+
fs.writeFileSync(path.join(tempDir, 'remotion.config.js'), remotionConfig);
|
|
57
|
+
|
|
58
|
+
// 5. Bundle 代码
|
|
50
59
|
logger.info(methodName, 'Bundling code...');
|
|
51
60
|
const bundleLocation = await bundle({
|
|
52
61
|
entryPoint,
|
|
53
62
|
webpackOverride: (config) => config,
|
|
54
63
|
});
|
|
55
64
|
|
|
56
|
-
//
|
|
65
|
+
// 6. 获取 composition
|
|
57
66
|
logger.info(methodName, 'Getting composition...');
|
|
58
67
|
const composition = await selectComposition({
|
|
59
68
|
serveUrl: bundleLocation,
|
|
@@ -61,7 +70,7 @@ exports.renderVideo = async ({ sourceCode, outputPath, width, height, fps }) =>
|
|
|
61
70
|
inputProps: {},
|
|
62
71
|
});
|
|
63
72
|
|
|
64
|
-
//
|
|
73
|
+
// 7. 渲染视频
|
|
65
74
|
logger.info(methodName, 'Rendering frames...');
|
|
66
75
|
await renderMedia({
|
|
67
76
|
composition: {
|
|
@@ -98,13 +107,13 @@ exports.renderVideo = async ({ sourceCode, outputPath, width, height, fps }) =>
|
|
|
98
107
|
function wrapUserCode(sourceCode) {
|
|
99
108
|
return `
|
|
100
109
|
import React from 'react';
|
|
101
|
-
import { Composition, AbsoluteFill, useCurrentFrame, interpolate, useVideoConfig } from 'remotion';
|
|
110
|
+
import { Composition, registerRoot, AbsoluteFill, useCurrentFrame, interpolate, useVideoConfig } from 'remotion';
|
|
102
111
|
|
|
103
112
|
// 用户代码
|
|
104
113
|
${sourceCode}
|
|
105
114
|
|
|
106
115
|
// Root 组件 - Remotion 入口
|
|
107
|
-
|
|
116
|
+
const RemotionRoot = () => {
|
|
108
117
|
return (
|
|
109
118
|
<>
|
|
110
119
|
<Composition
|
|
@@ -118,5 +127,8 @@ export const RemotionRoot = () => {
|
|
|
118
127
|
</>
|
|
119
128
|
);
|
|
120
129
|
};
|
|
130
|
+
|
|
131
|
+
// 注册 Root 组件(Remotion 4.x 要求)
|
|
132
|
+
registerRoot(RemotionRoot);
|
|
121
133
|
`;
|
|
122
134
|
}
|
package/server/util/work.js
CHANGED
|
@@ -11,6 +11,9 @@ const { uploadToR2 } = require('./uploader.js');
|
|
|
11
11
|
// model
|
|
12
12
|
const { updateRenderStatus } = require('../model/RemotionModel.js');
|
|
13
13
|
|
|
14
|
+
// feishu
|
|
15
|
+
const { feishuMsg, errorFeishuMsg } = require('../util/feishu.js');
|
|
16
|
+
|
|
14
17
|
// logger
|
|
15
18
|
const Logger = require('qiao-log');
|
|
16
19
|
const logOptions = require('../log-options.js')();
|
|
@@ -26,6 +29,7 @@ exports.processWork = async (work) => {
|
|
|
26
29
|
// const
|
|
27
30
|
const workId = work.id;
|
|
28
31
|
const outputPath = path.join(global.QZ_CONFIG.OUTPUT_DIR, `${workId}.mp4`);
|
|
32
|
+
feishuMsg(`${workId} start`);
|
|
29
33
|
logger.info(methodName, `\n[${new Date().toISOString()}] Processing work: ${workId}`);
|
|
30
34
|
logger.info(methodName, `Title: ${work.title}`);
|
|
31
35
|
logger.info(methodName, `Status: ${work.status}, Render Status: ${work.render_status}`);
|
|
@@ -40,7 +44,7 @@ exports.processWork = async (work) => {
|
|
|
40
44
|
height: work.height || 1080,
|
|
41
45
|
fps: work.fps || 30,
|
|
42
46
|
});
|
|
43
|
-
|
|
47
|
+
feishuMsg(`${workId} render ok`);
|
|
44
48
|
logger.info(methodName, 'Video rendered successfully');
|
|
45
49
|
|
|
46
50
|
// 2. 上传到 R2
|
|
@@ -49,7 +53,7 @@ exports.processWork = async (work) => {
|
|
|
49
53
|
filePath: outputPath,
|
|
50
54
|
workId: workId,
|
|
51
55
|
});
|
|
52
|
-
|
|
56
|
+
feishuMsg(`${workId} upload ok, ${videoUrl}`);
|
|
53
57
|
logger.info(methodName, 'Video uploaded:', videoUrl);
|
|
54
58
|
|
|
55
59
|
// 3. 获取视频信息
|
|
@@ -63,13 +67,15 @@ exports.processWork = async (work) => {
|
|
|
63
67
|
duration_in_frames: durationInFrames,
|
|
64
68
|
duration_seconds: durationInFrames / (work.fps || 30),
|
|
65
69
|
});
|
|
66
|
-
|
|
70
|
+
feishuMsg(`${workId} db ok`);
|
|
67
71
|
logger.info(methodName, `✅ Work ${workId} completed successfully`);
|
|
68
72
|
logger.info(methodName, ` Status: ${work.status}, Render Status: completed`);
|
|
69
73
|
|
|
70
74
|
// 5. 清理本地文件
|
|
71
75
|
fs.unlinkSync(outputPath);
|
|
76
|
+
feishuMsg(`${workId} clear ok`);
|
|
72
77
|
} catch (error) {
|
|
78
|
+
errorFeishuMsg(`${workId} \n ${error}`);
|
|
73
79
|
logger.error(methodName, `❌ Error processing work ${workId}:`, error);
|
|
74
80
|
|
|
75
81
|
// 更新为渲染失败状态
|