Explorar el Código

初始提交:完成音频上传和处理功能

黎海 hace 4 meses
commit
6041c9b1c5
Se han modificado 100 ficheros con 120787 adiciones y 0 borrados
  1. 38 0
      .gitignore
  2. 58 0
      README.md
  3. BIN
      assets/icons/jy_draft.jpeg
  4. BIN
      assets/icons/logo.icns
  5. BIN
      assets/icons/logo.ico
  6. BIN
      assets/icons/logo.png
  7. 4 0
      locales/en.json
  8. 1 0
      locales/zh.json
  9. 86 0
      main.js
  10. 14398 0
      package-lock.json
  11. 133 0
      package.json
  12. 56 0
      preload.js
  13. BIN
      public/favicon.ico
  14. 14 0
      public/index.html
  15. BIN
      public/letui.png
  16. BIN
      public/logo.ico
  17. 77 0
      src/App.js
  18. 62 0
      src/api/ApiService.js
  19. 122 0
      src/api/LocalDataService.js
  20. 40 0
      src/api/coze_api.js
  21. 14 0
      src/common/tool.js
  22. 190 0
      src/components/CozeApiSettings.js
  23. 538 0
      src/components/CozeWorkflowDemo.js
  24. 116 0
      src/components/audioPlayer/index.js
  25. 99 0
      src/components/audioPlayer/style.css
  26. 65 0
      src/components/audioUpload/index.js
  27. 27 0
      src/components/audioUpload/style.css
  28. 531 0
      src/components/subtitleUpload/index.js
  29. 50 0
      src/components/subtitleUpload/style.css
  30. 70 0
      src/components/videoDownload/index.css
  31. 107 0
      src/components/videoDownload/index.js
  32. 90 0
      src/css/index.css
  33. 260 0
      src/db/bookInfoService.js
  34. 103 0
      src/db/bookService.js
  35. 145 0
      src/db/config.js
  36. 219 0
      src/db/dbService.js
  37. 2 0
      src/db/index.js
  38. 17 0
      src/db/init.js
  39. BIN
      src/image/close.png
  40. BIN
      src/image/logo.png
  41. 70 0
      src/index.js
  42. 127 0
      src/main/ipcHandlers.js
  43. 367 0
      src/nodeapi/dbHandler.js
  44. 47 0
      src/nodeapi/drafts/add_audio.js
  45. 293 0
      src/nodeapi/drafts/add_keyframes_v2.js
  46. 125 0
      src/nodeapi/drafts/add_text.js
  47. 35 0
      src/nodeapi/drafts/add_text_animations.js
  48. 23 0
      src/nodeapi/drafts/add_tracks.js
  49. 90 0
      src/nodeapi/drafts/add_tracks_segments.js
  50. 93 0
      src/nodeapi/drafts/add_video.js
  51. 36 0
      src/nodeapi/drafts/add_video_animations.js
  52. 11 0
      src/nodeapi/drafts/add_video_effects.js
  53. 2555 0
      src/nodeapi/drafts/data/texiao/aixin.json
  54. 2909 0
      src/nodeapi/drafts/data/texiao/anhei.json
  55. 5906 0
      src/nodeapi/drafts/data/texiao/biankuang.json
  56. 4171 0
      src/nodeapi/drafts/data/texiao/bling.json
  57. 1560 0
      src/nodeapi/drafts/data/texiao/chaoku.json
  58. 522 0
      src/nodeapi/drafts/data/texiao/dianyin.json
  59. 6157 0
      src/nodeapi/drafts/data/texiao/donggan.json
  60. 1796 0
      src/nodeapi/drafts/data/texiao/dv.json
  61. 712 0
      src/nodeapi/drafts/data/texiao/fenpin.json
  62. 4405 0
      src/nodeapi/drafts/data/texiao/fenwei.json
  63. 4472 0
      src/nodeapi/drafts/data/texiao/fugu.json
  64. 2297 0
      src/nodeapi/drafts/data/texiao/guang.json
  65. 4929 0
      src/nodeapi/drafts/data/texiao/jichu.json
  66. 1712 0
      src/nodeapi/drafts/data/texiao/jinfen.json
  67. 1700 0
      src/nodeapi/drafts/data/texiao/manhua.json
  68. 708 0
      src/nodeapi/drafts/data/texiao/niuqu.json
  69. 7147 0
      src/nodeapi/drafts/data/texiao/remen.json
  70. 124 0
      src/nodeapi/drafts/data/texiao/texiao.js
  71. 2354 0
      src/nodeapi/drafts/data/texiao/touyin.json
  72. 2118 0
      src/nodeapi/drafts/data/texiao/wenli.json
  73. 2882 0
      src/nodeapi/drafts/data/texiao/ziran.json
  74. 2287 0
      src/nodeapi/drafts/data/texiao/zongyi.json
  75. 4550 0
      src/nodeapi/drafts/data/text/chuchang.js
  76. 5368 0
      src/nodeapi/drafts/data/text/ruchang.js
  77. 3439 0
      src/nodeapi/drafts/data/text/xunhuan.js
  78. 7499 0
      src/nodeapi/drafts/data/video/group.js
  79. 3050 0
      src/nodeapi/drafts/data/video/ins.js
  80. 1643 0
      src/nodeapi/drafts/data/video/out.js
  81. 1138 0
      src/nodeapi/drafts/data/zhuanchang/diehua123.json
  82. 322 0
      src/nodeapi/drafts/data/zhuanchang/fenge123.json
  83. 618 0
      src/nodeapi/drafts/data/zhuanchang/guangxiao123.json
  84. 692 0
      src/nodeapi/drafts/data/zhuanchang/guzhang123.json
  85. 1795 0
      src/nodeapi/drafts/data/zhuanchang/hot.json
  86. 2331 0
      src/nodeapi/drafts/data/zhuanchang/huandengpian123.json
  87. 248 0
      src/nodeapi/drafts/data/zhuanchang/hudongemoji123.json
  88. 1136 0
      src/nodeapi/drafts/data/zhuanchang/mgdonghua123.json
  89. 628 0
      src/nodeapi/drafts/data/zhuanchang/mohu123.json
  90. 470 0
      src/nodeapi/drafts/data/zhuanchang/niuqu123.json
  91. 396 0
      src/nodeapi/drafts/data/zhuanchang/paishe123.json
  92. 1383 0
      src/nodeapi/drafts/data/zhuanchang/yunjing123.json
  93. 334 0
      src/nodeapi/drafts/data/zhuanchang/ziran123.json
  94. 396 0
      src/nodeapi/drafts/data/zhuanchang/zongyi123.json
  95. 187 0
      src/nodeapi/drafts/drafts_task.js
  96. 13 0
      src/nodeapi/drafts/get_image_info.js
  97. 399 0
      src/nodeapi/ipcHandlers.js
  98. 245 0
      src/nodeapi/plugins/pluginHanlder.js
  99. 35 0
      src/nodeapi/plugins/test_api.js
  100. 0 0
      src/nodeapi/scene/auto_scene.js

+ 38 - 0
.gitignore

@@ -0,0 +1,38 @@
1
+# 依赖
2
+/node_modules
3
+/.pnp
4
+.pnp.js
5
+
6
+# 测试
7
+/coverage
8
+
9
+# 生产构建
10
+/build
11
+/dist
12
+
13
+# 杂项
14
+.DS_Store
15
+.env.local
16
+.env.development.local
17
+.env.test.local
18
+.env.production.local
19
+.env
20
+
21
+# 日志
22
+npm-debug.log*
23
+yarn-debug.log*
24
+yarn-error.log*
25
+
26
+# 编辑器配置
27
+.idea/
28
+.vscode/
29
+*.suo
30
+*.ntvs*
31
+*.njsproj
32
+*.sln
33
+.history/
34
+
35
+# 本地数据库和资源文件
36
+/resources
37
+*.sqlite
38
+*.db

+ 58 - 0
README.md

@@ -0,0 +1,58 @@
1
+# 唇形同步生成器
2
+
3
+一个基于Electron的桌面应用程序,用于生成唇形同步效果。该应用程序允许用户上传字幕和音频文件,然后生成与语音同步的唇形动画。
4
+
5
+## 功能特点
6
+
7
+- 支持SRT和VTT格式的字幕文件
8
+- 支持音频文件上传和处理
9
+- 自动切割音频文件以匹配字幕时间
10
+- 使用AI生成描述词
11
+- 生成唇形同步动画
12
+- 导出和分享功能
13
+
14
+## 开发环境设置
15
+
16
+### 前提条件
17
+
18
+- Node.js (v14.0.0+)
19
+- npm (v6.0.0+)
20
+
21
+### 安装
22
+
23
+1. 克隆仓库
24
+   ```
25
+   git clone http://code.qutaovip.com/lihai/lip_sync.git
26
+   cd lip_sync
27
+   ```
28
+
29
+2. 安装依赖
30
+   ```
31
+   npm install
32
+   ```
33
+
34
+3. 启动开发服务器
35
+   ```
36
+   npm start
37
+   ```
38
+
39
+### 构建应用
40
+
41
+```
42
+npm run build
43
+```
44
+
45
+## 项目结构
46
+
47
+- `/src` - 源代码
48
+  - `/components` - React组件
49
+  - `/pages` - 页面组件
50
+  - `/utils` - 工具函数
51
+  - `/nodeapi` - Node.js API
52
+  - `/db` - 数据库相关代码
53
+
54
+## 许可证
55
+
56
+Copyright (c) 2023
57
+
58
+此项目仅供学习和研究使用。未经许可,禁止商业用途。 

BIN
assets/icons/jy_draft.jpeg


BIN
assets/icons/logo.icns


BIN
assets/icons/logo.ico


BIN
assets/icons/logo.png


+ 4 - 0
locales/en.json

@@ -0,0 +1,4 @@
1
+{
2
+	"Hello": "Hello",
3
+	"login_sms_code_sent_success_toast": "login_sms_code_sent_success_toast"
4
+}

+ 1 - 0
locales/zh.json

@@ -0,0 +1 @@
1
+{}

+ 86 - 0
main.js

@@ -0,0 +1,86 @@
1
+const { app, BrowserWindow } = require('electron');
2
+const path = require('path');
3
+const { setupIpcHandlers } = require('./src/nodeapi/ipcHandlers')
4
+
5
+let mainWindow;
6
+let storedDrafId = null;
7
+
8
+
9
+app.on('open-url', (event, url) => {
10
+  event.preventDefault();
11
+  console.log('open-url event triggered:', url);
12
+  const urlObj = new URL(url);
13
+  const drafId = urlObj.searchParams.get('drafId');
14
+  console.log(drafId, 'drafId');
15
+  if (drafId) {
16
+    storedDrafId = drafId; // 存储 drafId
17
+    console.log('/batchList');
18
+    // 获取所有窗体并发送消息
19
+    const allWindows = BrowserWindow.getAllWindows();
20
+    allWindows.forEach(win => {
21
+      win.webContents.send('navigate-to-batchList', drafId);
22
+    });
23
+  }
24
+});
25
+
26
+app.on('ready', () => {
27
+  console.log('app.on ready');
28
+  createWindow();
29
+
30
+  // 设置默认协议客户端
31
+  if (process.defaultApp) {
32
+    if (process.argv.length >= 2) {
33
+      app.setAsDefaultProtocolClient('jianyingAssistant', process.execPath, [path.resolve(process.argv[1])]);
34
+    }
35
+  } else {
36
+    app.setAsDefaultProtocolClient('jianyingAssistant');
37
+  }
38
+
39
+  // 监听 batchList-ready 信号
40
+  const { ipcMain } = require('electron');
41
+  ipcMain.on('batchList-ready', (event) => {
42
+    if (storedDrafId) {
43
+      event.sender.send('navigate-to-batchList', storedDrafId);
44
+      storedDrafId = null; // 发送后清除存储的 drafId
45
+    }
46
+  });
47
+});
48
+
49
+
50
+function createWindow () {
51
+  mainWindow = new BrowserWindow({
52
+    width: 1366,
53
+    height: 768,
54
+    icon: path.join(__dirname, './assets/icons/logo.ico'),
55
+    webPreferences: {
56
+      preload: path.join(__dirname, 'preload.js'),
57
+      nodeIntegration: false,
58
+      contextIsolation: true,
59
+    }
60
+  });
61
+  if (process.platform==='darwin') {
62
+    app.dock.setIcon(path.join(__dirname, './assets/icons/logo.png'))
63
+  }
64
+
65
+  mainWindow.loadFile(path.join(__dirname, 'dist', 'index.html'));
66
+
67
+  // 设置 IPC 处理程序
68
+  setupIpcHandlers();
69
+
70
+  mainWindow.on('closed', function () {
71
+    mainWindow = null;
72
+  });
73
+}
74
+
75
+
76
+app.on('window-all-closed', function () {
77
+  if (process.platform !== 'darwin') {
78
+    app.quit();
79
+  }
80
+});
81
+
82
+app.on('activate', function () {
83
+  if (mainWindow === null) {
84
+    createWindow();
85
+  }
86
+});

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 14398 - 0
package-lock.json


+ 133 - 0
package.json

@@ -0,0 +1,133 @@
1
+{
2
+  "name": "jianyin_agent",
3
+  "version": "2.4.3",
4
+  "description": "Your project description here",
5
+  "author": "Your Name or Company",
6
+  "main": "main.js",
7
+  "scripts": {
8
+    "start": "electron .",
9
+    "start-web": "webpack serve --open --config webpack.config.js",
10
+    "build": "webpack --config webpack.config.js",
11
+    "mac": "electron-builder --mac",
12
+    "win": "electron-builder --win -w zip -w nsis",
13
+    "watch": "nodemon --watch ./src --exec 'npm run build && electron .'",
14
+    "start-electron": "concurrently \"npm run start-web\" \"wait-on http://localhost:9000 && electron .\"",
15
+    "app": "electron ."
16
+  },
17
+  "devDependencies": {
18
+    "@babel/core": "^7.14.0",
19
+    "@babel/preset-env": "^7.14.1",
20
+    "@babel/preset-react": "^7.13.13",
21
+    "babel-loader": "^8.2.2",
22
+    "concurrently": "^7.3.0",
23
+    "copy-webpack-plugin": "^12.0.2",
24
+    "css-loader": "^5.2.4",
25
+    "electron": "^31.3.1",
26
+    "electron-builder": "^23.0.3",
27
+    "electron-packager": "^17.1.0",
28
+    "electron-reload": "^1.5.0",
29
+    "file-loader": "^6.2.0",
30
+    "html-webpack-plugin": "^5.5.3",
31
+    "process": "^0.11.10",
32
+    "react-bootstrap": "^2.8.0",
33
+    "style-loader": "^2.0.0",
34
+    "wait-on": "^6.0.0",
35
+    "webpack": "^5.37.0",
36
+    "webpack-cli": "^4.7.0",
37
+    "webpack-dev-server": "^4.11.1"
38
+  },
39
+  "dependencies": {
40
+    "@coze/api": "^1.1.0",
41
+    "@fortawesome/fontawesome-svg-core": "^6.5.1",
42
+    "@fortawesome/free-solid-svg-icons": "^6.5.1",
43
+    "@fortawesome/react-fontawesome": "^0.2.0",
44
+    "ali-oss": "^6.18.1",
45
+    "assert": "^2.1.0",
46
+    "axios": "^1.7.2",
47
+    "bootstrap": "^5.3.0",
48
+    "bootstrap-icons": "^1.11.2",
49
+    "buffer": "^6.0.3",
50
+    "fluent-ffmpeg": "^2.1.3",
51
+    "fs-extra": "^11.2.0",
52
+    "image-size": "^1.1.1",
53
+    "jimp": "^0.22.12",
54
+    "knex": "^3.1.0",
55
+    "os-browserify": "^0.3.0",
56
+    "papaparse": "^5.4.1",
57
+    "path-browserify": "^1.0.1",
58
+    "prop-types": "^15.8.1",
59
+    "qrcode": "^1.5.4",
60
+    "react": "^17.0.2",
61
+    "react-bootstrap-icons": "^1.10.3",
62
+    "react-copy-to-clipboard": "^5.1.0",
63
+    "react-dom": "^17.0.2",
64
+    "react-h5-audio-player": "^3.9.0",
65
+    "react-lazy-load-image-component": "^1.6.0",
66
+    "react-router-dom": "^5.3.0",
67
+    "react-select": "^5.8.0",
68
+    "react-swipeable": "^7.0.1",
69
+    "react-toastify": "^9.1.3",
70
+    "sqlite3": "^5.1.7",
71
+    "stream-browserify": "^3.0.0",
72
+    "subtitle": "^4.2.1",
73
+    "tar": "^7.4.3",
74
+    "universalify": "^2.0.1",
75
+    "util": "^0.12.5",
76
+    "uuid": "^9.0.1",
77
+    "xlsx": "^0.18.5"
78
+  },
79
+  "build": {
80
+    "productName": "视频对口型",
81
+    "appId": "com.spring.jianyinAssistant",
82
+    "asarUnpack": [
83
+      "ffmpeg/**/*",
84
+      "jianyin/**/*"
85
+    ],
86
+    "mac": {
87
+      "category": "public.app-category.utilities",
88
+      "icon": "assets/icons/logo.icns",
89
+      "target": [
90
+        "dmg",
91
+        {
92
+          "target": "zip",
93
+          "arch": [
94
+            "x64",
95
+            "arm64"
96
+          ]
97
+        },
98
+        "tar.gz"
99
+      ],
100
+      "protocols": [
101
+        {
102
+          "name": "MyApp Protocol",
103
+          "schemes": [
104
+            "jianyingAssistant"
105
+          ]
106
+        }
107
+      ]
108
+    },
109
+    "win": {
110
+      "target": [
111
+        "nsis",
112
+        "portable"
113
+      ],
114
+      "icon": "assets/icons/logo.ico",
115
+      "publisherName": "Your Company",
116
+      "protocols": [
117
+        {
118
+          "name": "MyApp Protocol",
119
+          "schemes": [
120
+            "jianyingAssistant"
121
+          ]
122
+        }
123
+      ]
124
+    },
125
+    "nsis": {
126
+      "oneClick": false,
127
+      "allowToChangeInstallationDirectory": true
128
+    },
129
+    "directories": {
130
+      "output": "release"
131
+    }
132
+  }
133
+}

+ 56 - 0
preload.js

@@ -0,0 +1,56 @@
1
+// preload.js
2
+const { contextBridge, ipcRenderer } = require('electron');
3
+
4
+// 暴露安全的API给渲染进程
5
+contextBridge.exposeInMainWorld('electron', {
6
+  // IPC通信
7
+  ipcRenderer: {
8
+    // 发送消息到主进程(无返回值)
9
+    send: (channel, ...args) => {
10
+      ipcRenderer.send(channel, ...args);
11
+    },
12
+    // 调用主进程方法并获取返回值(Promise)
13
+    invoke: (channel, ...args) => {
14
+      return ipcRenderer.invoke(channel, ...args);
15
+    },
16
+    // 监听来自主进程的消息
17
+    on: (channel, func) => {
18
+      const subscription = (event, ...args) => func(...args);
19
+      ipcRenderer.on(channel, subscription);
20
+      return () => {
21
+        ipcRenderer.removeListener(channel, subscription);
22
+      };
23
+    },
24
+    // 一次性监听来自主进程的消息
25
+    once: (channel, func) => {
26
+      ipcRenderer.once(channel, (event, ...args) => func(...args));
27
+    }
28
+  },
29
+  
30
+  // 操作系统与应用相关信息
31
+  system: {
32
+    // 获取应用版本
33
+    getAppVersion: () => ipcRenderer.invoke('get-app-version')
34
+  },
35
+  
36
+  // 文件操作
37
+  files: {
38
+    // 打开文件选择对话框
39
+    openDirectoryDialog: () => ipcRenderer.invoke('open-directory-dialog'),
40
+    // 在文件管理器中显示文件
41
+    showItemInFolder: (path) => ipcRenderer.invoke('open-file-path', path),
42
+    // 获取文件状态信息
43
+    getFileStats: (path) => ipcRenderer.invoke('get-file-stats', path)
44
+  },
45
+  
46
+  // 外部链接
47
+  shell: {
48
+    // 在默认浏览器中打开URL
49
+    openExternal: (url) => ipcRenderer.invoke('open-url', url)
50
+  }
51
+});
52
+
53
+window.addEventListener('DOMContentLoaded', () => {
54
+  console.log('Preload script loaded');
55
+});
56
+  

BIN
public/favicon.ico


+ 14 - 0
public/index.html

@@ -0,0 +1,14 @@
1
+<!DOCTYPE html>
2
+<html>
3
+  <head>
4
+    <meta charset="UTF-8">
5
+    <meta name="viewport" content="width=device-width, initial-scale=1">
6
+    <link rel="shortcut icon" href="https://ts.fyshark.com/logo.ico" />
7
+
8
+    <title>视频对口型</title>
9
+  </head>
10
+  <body>
11
+    <div id="root"></div>
12
+    <script src="../src/index.js"></script>
13
+  </body>
14
+</html>

BIN
public/letui.png


BIN
public/logo.ico


+ 77 - 0
src/App.js

@@ -0,0 +1,77 @@
1
+import React, { useRef, useState, useEffect } from 'react';
2
+import { HashRouter as Router, Link, NavLink, useHistory } from 'react-router-dom';
3
+import { Navbar, Nav } from 'react-bootstrap';
4
+import Routes from './router/index'; // 引入Routes组件
5
+import 'bootstrap/dist/css/bootstrap.min.css';
6
+import 'bootstrap-icons/font/bootstrap-icons.css'; // Import Bootstrap Icons
7
+import 'react-toastify/dist/ReactToastify.css';
8
+import LocalDataService from './api/LocalDataService';
9
+import './css/index.css'
10
+import { ToastContainer } from 'react-toastify';
11
+import ApiService from './api/ApiService';
12
+import { initDb } from './db';
13
+import { toast } from 'react-toastify';
14
+
15
+let ipcRenderer;
16
+if (typeof window !== 'undefined' && window.require) {
17
+  ipcRenderer = window.require('electron').ipcRenderer;
18
+}
19
+
20
+function App () {
21
+  const userProfileRef = useRef(null);
22
+  const apiService = new ApiService();
23
+  const [dbInitialized, setDbInitialized] = useState(false);
24
+
25
+  useEffect(() => {
26
+    // 初始化数据库
27
+    const initDatabase = async () => {
28
+      try {
29
+        const result = await initDb();
30
+        setDbInitialized(result);
31
+        if (result) {
32
+          console.log('数据库初始化成功');
33
+        } else {
34
+          console.error('数据库初始化失败');
35
+          toast.error('数据库初始化失败,部分功能可能无法正常使用');
36
+        }
37
+      } catch (error) {
38
+        console.error('数据库初始化失败:', error);
39
+        toast.error(`数据库初始化失败: ${error.message},部分功能可能无法正常使用`);
40
+        setDbInitialized(false);
41
+      }
42
+    };
43
+    
44
+    initDatabase();
45
+    
46
+    let user_info = LocalDataService.load_user_data();
47
+    if (!user_info) {
48
+      userProfileRef.current.showLoginModal();
49
+    }
50
+    apiService.setUserProfileRef(userProfileRef);
51
+  }, []);
52
+
53
+
54
+  return (
55
+    <div className='app'>
56
+      <Router>
57
+        <Navbar expand="lg" className='navigation'>
58
+          <Navbar.Brand as={Link} to="/" style={{ color: 'white', marginLeft: '12px', display: 'flex', alignItems: 'center' }}>
59
+          视频对口型
60
+          </Navbar.Brand>
61
+          <Navbar.Toggle aria-controls="basic-navbar-nav" className="custom-toggler" />
62
+          <Navbar.Collapse id="basic-navbar-nav" >
63
+            <Nav className="navigation-tab" >
64
+              <NavLink className='tab-info' to='/histList' activeClassName="active-link">历史记录</NavLink>
65
+            </Nav>
66
+          </Navbar.Collapse>
67
+        </Navbar>
68
+        <div className='content'>
69
+          <Routes userProfileRef={userProfileRef} /> {/* 使用Routes组件 */}
70
+        </div>
71
+        <ToastContainer style={{ top: '55px' }} />
72
+      </Router>
73
+    </div>
74
+  );
75
+}
76
+
77
+export default App;

+ 62 - 0
src/api/ApiService.js

@@ -0,0 +1,62 @@
1
+import { toast } from 'react-toastify';
2
+import LocalDataService from './LocalDataService';
3
+class ApiService {
4
+  constructor() {
5
+    this.apiBase = 'https://ts-api.fyshark.com/api'; // 服务器地址
6
+    // 全局引用,用于存储userProfileRef
7
+    this.userProfileRef = null;
8
+  }
9
+
10
+  // 设置userProfileRef的方法
11
+  setUserProfileRef(ref) {
12
+    this.userProfileRef = ref;
13
+  }
14
+
15
+  // 通用的请求方法
16
+  async request (url, method, data) {
17
+    const requestOptions = {
18
+      method: method,
19
+      headers: {
20
+        'Content-Type': 'application/json',
21
+        'accept': 'application/json'
22
+      },
23
+      body: JSON.stringify(data)
24
+    };
25
+
26
+    try {
27
+      const response = await fetch(url, requestOptions);
28
+      const responseData = await response.json();
29
+      if (!response.ok) {
30
+        throw { status: response.status, data: JSON.stringify(responseData) };
31
+      }
32
+      return responseData; // 返回解析后的JSON对象
33
+    } catch (error) {
34
+      // 检查是否是500错误(登录态失效)
35
+      if (error && error.status === 500 && error.data.indexOf('token') != -1) {
36
+        // 清除本地登录信息
37
+        LocalDataService.set_user_data(null);
38
+         
39
+        
40
+        // 显示错误提示
41
+        toast.error('登录已过期,请重新登录');
42
+      } else {
43
+        // 其他错误,如果不是获取命令列表的请求,则显示错误提示
44
+        
45
+        toast.error(`请求错误:${error.data || JSON.stringify(error)}`);
46
+        
47
+      }
48
+      
49
+      throw error; // 将错误抛出,使得调用者能够处理它
50
+    }
51
+  }
52
+
53
+  // 视频下载
54
+  down_load_video (token, url) {
55
+    return this.request(`${this.apiBase}/down_load_video`, 'POST', { token, url });
56
+  }
57
+
58
+
59
+
60
+}
61
+
62
+export default ApiService;

+ 122 - 0
src/api/LocalDataService.js

@@ -0,0 +1,122 @@
1
+class LocalDataService {
2
+  
3
+  static load_user_data(){
4
+    let user =  this.loadData('user_info');
5
+    
6
+    if(user){
7
+      return user;
8
+    }else{
9
+      return null;
10
+    }
11
+  }
12
+
13
+
14
+  static set_user_data(user_info){
15
+    this.storeData('user_info', user_info);
16
+  }
17
+  
18
+  // 获取剪映草稿路径
19
+  static getDraftPath() {
20
+    return this.loadData('draft_path');
21
+  }
22
+
23
+  // 写入剪映草稿路径
24
+  static setDraftPath(path) {
25
+    this.storeData('draft_path', path);
26
+  }
27
+
28
+  // 存储数据
29
+  static storeData(key, data) {
30
+    try {
31
+      const serializedData = JSON.stringify(data);
32
+      localStorage.setItem(key, serializedData);
33
+    } catch (error) {
34
+      console.error("Error saving data to localStorage", error);
35
+    }
36
+  }
37
+
38
+  // 读取数据
39
+  static loadData(key) {
40
+    try {
41
+      const serializedData = localStorage.getItem(key);
42
+      if (serializedData === null) {
43
+        return undefined;
44
+      }
45
+      return JSON.parse(serializedData);
46
+    } catch (error) {
47
+      console.error("Error loading data from localStorage", error);
48
+      return undefined;
49
+    }
50
+  }
51
+
52
+  // 删除数据
53
+  static removeData(key) {
54
+    try {
55
+      localStorage.removeItem(key);
56
+    } catch (error) {
57
+      console.error("Error removing data from localStorage", error);
58
+    }
59
+  }
60
+
61
+    // 记录空间列表
62
+    static setSpaceList(spaces) {
63
+      this.storeData('space_list', spaces);
64
+    }
65
+  
66
+    // 获取空间列表
67
+    static getSpaceList() {
68
+      return this.loadData('space_list') || [];
69
+    }
70
+  
71
+    // 增加空间
72
+    static addSpace(title, hash,url) {
73
+      const spaces = this.getSpaceList();
74
+      spaces.push({ title, hash ,url});
75
+      this.setSpaceList(spaces);
76
+    }
77
+  
78
+    // 删除空间
79
+    static removeSpace(hash) {
80
+      let spaces = this.getSpaceList();
81
+      spaces = spaces.filter(space => space.hash !== hash);
82
+      this.setSpaceList(spaces);
83
+    }
84
+
85
+    // Save cookies associated with a specific space
86
+  static saveCookies(hash, cookies) {
87
+    try {
88
+      const key = `cookie_data_${hash}`; // Unique key for each space's cookies
89
+      this.storeData(key, cookies);
90
+    } catch (error) {
91
+      console.error("Error saving cookies to localStorage", error);
92
+    }
93
+  }
94
+
95
+  // Get cookies associated with a specific space
96
+  static getCookies(hash) {
97
+    try {
98
+      const key = `cookie_data_${hash}`; // Unique key for each space's cookies
99
+      return this.loadData(key);
100
+    } catch (error) {
101
+      console.error("Error loading cookies from localStorage", error);
102
+      return null;
103
+    }
104
+  }
105
+
106
+  // 保存是否自动打开草稿路径的设置
107
+  static setAutoOpenDraft(isOpen) {
108
+    this.storeData('auto_open_draft', isOpen);
109
+  }
110
+
111
+  // 获取是否自动打开草稿路径的设置
112
+  static getAutoOpenDraft() {
113
+    const value = this.loadData('auto_open_draft');
114
+    // 如果没有设置过,默认返回 true
115
+    return value === undefined ? true : value;
116
+  }
117
+
118
+  
119
+
120
+}
121
+
122
+module.exports = LocalDataService;

+ 40 - 0
src/api/coze_api.js

@@ -0,0 +1,40 @@
1
+import { Args } from '@/runtime';
2
+import { Input, Output } from "@/typings/create_task_list/create_task_list";
3
+import axios from 'axios';
4
+
5
+/**
6
+  * Each file needs to export a function named `handler`. This function is the entrance to the Tool.
7
+  * @param {Object} args.input - input parameters, you can get test input value by input.xxx.
8
+  * @param {Object} args.logger - logger instance used to print logs, injected by runtime
9
+  * @returns {*} The return data of the function, which should match the declared output parameters.
10
+  * 
11
+  * Remember to fill in input/output in Metadata, it helps LLM to recognize and use tool.
12
+  */
13
+export async function handler({ input, logger }: Args<Input>): Promise<Output> {
14
+  try {
15
+    const response = await axios.post('http://hailuo.st-ai.top/video_tasks_create', {
16
+      prompt: input.prompt,
17
+      image_url: input.image_url
18
+    }, {
19
+      headers: {
20
+        'accept': 'application/json',
21
+        'Content-Type': 'application/json',
22
+        'Authorization': `Bearer ${input.token}` // 使用 token 作为 Bearer token
23
+      }
24
+    });
25
+
26
+    // 处理响应数据
27
+    const data = response.data;
28
+    logger.info('API response:', data);
29
+
30
+    return {
31
+      message: "API call successful",
32
+      // 你可以根据需要返回更多数据
33
+    };
34
+  } catch (error) {
35
+    logger.error('API call failed:', error);
36
+    return {
37
+      message: "API call failed",
38
+    };
39
+  }
40
+};

+ 14 - 0
src/common/tool.js

@@ -0,0 +1,14 @@
1
+const tool={
2
+  /**
3
+   * 
4
+   * @param {内容} str 
5
+   * @param {长度} maxLength 
6
+   */
7
+  truncateString: function (str, maxLength) {
8
+    if (str.length <= maxLength) {
9
+      return str;
10
+    }
11
+    return str.slice(0, maxLength) + '...';
12
+  }
13
+}
14
+export default tool;

+ 190 - 0
src/components/CozeApiSettings.js

@@ -0,0 +1,190 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Button, Card, Container, Row, Col, Alert, Tab, Tabs, InputGroup } from 'react-bootstrap';
3
+import { saveCozeApiToken, getCozeApiToken, saveWorkflowIds, getWorkflowIds } from '../utils/storageUtils';
4
+import { WORKFLOW_DISPLAY_NAMES, hasValidToken } from '../utils/cozeConfig';
5
+import { toast } from 'react-toastify';
6
+
7
+/**
8
+ * Coze API设置组件
9
+ * 允许用户配置Coze API Token和工作流ID
10
+ */
11
+const CozeApiSettings = ({ onSave, isInModal = true }) => {
12
+  const [apiToken, setApiToken] = useState('');
13
+  const [showToken, setShowToken] = useState(false);
14
+  const [workflowIds, setWorkflowIds] = useState({});
15
+  const [activeTab, setActiveTab] = useState('token');
16
+  const [hasChanges, setHasChanges] = useState(false);
17
+  const [errorMessage, setErrorMessage] = useState('');
18
+
19
+  // 加载已存储的设置
20
+  useEffect(() => {
21
+    const storedToken = getCozeApiToken();
22
+    if (storedToken) {
23
+      setApiToken(storedToken);
24
+    }
25
+
26
+    const storedWorkflowIds = getWorkflowIds();
27
+    if (storedWorkflowIds) {
28
+      setWorkflowIds(storedWorkflowIds);
29
+    }
30
+    
31
+    setHasChanges(false);
32
+  }, []);
33
+
34
+  // 处理API Token变更
35
+  const handleTokenChange = (e) => {
36
+    setApiToken(e.target.value);
37
+    setHasChanges(true);
38
+  };
39
+
40
+  // 处理工作流ID变更
41
+  const handleWorkflowIdChange = (key, value) => {
42
+    setWorkflowIds(prev => ({
43
+      ...prev,
44
+      [key]: value
45
+    }));
46
+    setHasChanges(true);
47
+  };
48
+
49
+  // 保存设置
50
+  const handleSave = () => {
51
+    setErrorMessage('');
52
+    
53
+    try {
54
+      // 保存API Token
55
+      if (apiToken) {
56
+        saveCozeApiToken(apiToken);
57
+      }
58
+      
59
+      // 保存工作流ID
60
+      saveWorkflowIds(workflowIds);
61
+      
62
+      setHasChanges(false);
63
+      toast.success('设置已保存');
64
+      
65
+      // 如果提供了回调函数,则调用它
66
+      if (onSave && typeof onSave === 'function') {
67
+        onSave();
68
+      }
69
+      
70
+      // 需要刷新页面以应用新设置
71
+      // 询问用户是否刷新
72
+      if (window.confirm('设置已保存。需要刷新页面以应用新设置,是否立即刷新?')) {
73
+        window.location.reload();
74
+      }
75
+    } catch (error) {
76
+      console.error('保存设置失败:', error);
77
+      setErrorMessage(`保存设置失败: ${error.message}`);
78
+      toast.error(`保存设置失败: ${error.message}`);
79
+    }
80
+  };
81
+
82
+  // 显示或隐藏Token
83
+  const toggleShowToken = () => {
84
+    setShowToken(!showToken);
85
+  };
86
+
87
+  // 生成工作流ID配置表单
88
+  const renderWorkflowIdInputs = () => {
89
+    // 添加所有工作流
90
+    const mainWorkflows = ['textToDescription', 'getStyleList', 'generateImage'];
91
+    
92
+    return mainWorkflows.map((key) => (
93
+      <Form.Group className="mb-3" key={key}>
94
+        <Form.Label>{WORKFLOW_DISPLAY_NAMES[key]}</Form.Label>
95
+        <Form.Control
96
+          type="text"
97
+          placeholder={`请输入${WORKFLOW_DISPLAY_NAMES[key]}工作流ID`}
98
+          value={workflowIds[key] || ''}
99
+          onChange={(e) => handleWorkflowIdChange(key, e.target.value)}
100
+        />
101
+        <Form.Text className="text-muted">
102
+          {`${WORKFLOW_DISPLAY_NAMES[key]}工作流的唯一标识符。在Coze平台工作流设置中获取。`}
103
+        </Form.Text>
104
+      </Form.Group>
105
+    ));
106
+  };
107
+
108
+  const content = (
109
+    <>
110
+      {errorMessage && (
111
+        <Alert variant="danger" onClose={() => setErrorMessage('')} dismissible>
112
+          {errorMessage}
113
+        </Alert>
114
+      )}
115
+      
116
+      <Tabs
117
+        activeKey={activeTab}
118
+        onSelect={(k) => setActiveTab(k)}
119
+        className="mb-3"
120
+      >
121
+        <Tab eventKey="token" title="API Token">
122
+          <Form.Group className="mb-3">
123
+            <Form.Label>Coze API Token</Form.Label>
124
+            <InputGroup>
125
+              <Form.Control
126
+                type={showToken ? "text" : "password"}
127
+                placeholder="请输入您的Coze API Token"
128
+                value={apiToken}
129
+                onChange={handleTokenChange}
130
+              />
131
+              <Button 
132
+                variant="outline-secondary"
133
+                onClick={toggleShowToken}
134
+              >
135
+                {showToken ? '隐藏' : '显示'}
136
+              </Button>
137
+            </InputGroup>
138
+            {/* <Form.Text className="text-muted">
139
+              您的Coze API Token。访问 <a href="https://www.coze.cn" target="_blank" rel="noopener noreferrer">Coze平台</a> 获取。
140
+            </Form.Text> */}
141
+          </Form.Group>
142
+          
143
+          <Alert variant={hasValidToken() ? "success" : "warning"}>
144
+            {hasValidToken() 
145
+              ? "API Token已配置" 
146
+              : "请配置有效的API Token,否则相关功能将无法使用"}
147
+          </Alert>
148
+        </Tab>
149
+        
150
+        <Tab eventKey="workflows" title="工作流ID">
151
+          <p className="text-muted mb-3">
152
+            配置各功能对应的工作流ID。如果您没有特定的工作流,可以留空使用默认值。
153
+          </p>
154
+          {renderWorkflowIdInputs()}
155
+        </Tab>
156
+      </Tabs>
157
+      
158
+      <div className="text-center mt-4">
159
+        <Button
160
+          variant="primary"
161
+          onClick={handleSave}
162
+          disabled={!hasChanges}
163
+        >
164
+          保存设置
165
+        </Button>
166
+      </div>
167
+    </>
168
+  );
169
+
170
+  // 如果是在对话框中,不需要卡片包装
171
+  if (isInModal) {
172
+    return content;
173
+  }
174
+
175
+  // 如果是独立页面,使用卡片包装
176
+  return (
177
+    <Container className="my-4">
178
+      <Card>
179
+        <Card.Header>
180
+          <h4 className="mb-0">Coze API设置</h4>
181
+        </Card.Header>
182
+        <Card.Body>
183
+          {content}
184
+        </Card.Body>
185
+      </Card>
186
+    </Container>
187
+  );
188
+};
189
+
190
+export default CozeApiSettings; 

+ 538 - 0
src/components/CozeWorkflowDemo.js

@@ -0,0 +1,538 @@
1
+import React, { useState, useEffect, useRef } from 'react';
2
+import { Button, Form, Spinner, Card, Container, Row, Col, Alert } from 'react-bootstrap';
3
+import { toast } from 'react-toastify';
4
+import {
5
+  textToSpeech,
6
+  speechToText,
7
+  translateText,
8
+  summarizeText,
9
+  cozeService
10
+} from '../utils/cozeExample';
11
+
12
+/**
13
+ * Coze工作流演示组件
14
+ */
15
+const CozeWorkflowDemo = () => {
16
+  // 状态管理
17
+  const [loading, setLoading] = useState(false);
18
+  const [audioUrl, setAudioUrl] = useState(null);
19
+  const [inputText, setInputText] = useState('');
20
+  const [outputText, setOutputText] = useState('');
21
+  const [targetLanguage, setTargetLanguage] = useState('en');
22
+  const [audioFile, setAudioFile] = useState(null);
23
+  const [errorMessage, setErrorMessage] = useState('');
24
+  const [workflowId, setWorkflowId] = useState('');
25
+  const [activeTab, setActiveTab] = useState('tts'); // tts, stt, translate, summarize
26
+  
27
+  const audioRef = useRef(null);
28
+  
29
+  useEffect(() => {
30
+    // 在组件卸载时清理音频URL
31
+    return () => {
32
+      if (audioUrl) {
33
+        URL.revokeObjectURL(audioUrl);
34
+      }
35
+    };
36
+  }, [audioUrl]);
37
+  
38
+  // 处理文本转语音
39
+  const handleTextToSpeech = async () => {
40
+    if (!inputText.trim()) {
41
+      setErrorMessage('请输入要转换的文本');
42
+      return;
43
+    }
44
+    
45
+    setLoading(true);
46
+    setErrorMessage('');
47
+    
48
+    try {
49
+      if (audioUrl) {
50
+        URL.revokeObjectURL(audioUrl);
51
+        setAudioUrl(null);
52
+      }
53
+      
54
+      const response = await textToSpeech(inputText, {
55
+        voice: 'female', // 可以是不同的声音选项
56
+        speed: 1.0      // 语速
57
+      });
58
+      
59
+      // 处理流式响应
60
+      if (response && response.audio) {
61
+        // 假设返回的是Base64格式的音频数据
62
+        const blob = base64ToBlob(response.audio, 'audio/mp3');
63
+        const url = URL.createObjectURL(blob);
64
+        setAudioUrl(url);
65
+        
66
+        // 设置输出文本为成功消息
67
+        setOutputText('语音合成成功,可点击播放按钮收听');
68
+      } else {
69
+        throw new Error('未接收到有效的音频数据');
70
+      }
71
+    } catch (error) {
72
+      console.error('文本转语音失败:', error);
73
+      setErrorMessage(`文本转语音失败: ${error.message}`);
74
+      toast.error(`文本转语音失败: ${error.message}`);
75
+    } finally {
76
+      setLoading(false);
77
+    }
78
+  };
79
+  
80
+  // 处理语音转文本
81
+  const handleSpeechToText = async () => {
82
+    if (!audioFile) {
83
+      setErrorMessage('请先选择音频文件');
84
+      return;
85
+    }
86
+    
87
+    setLoading(true);
88
+    setErrorMessage('');
89
+    
90
+    try {
91
+      const response = await speechToText(audioFile);
92
+      
93
+      if (response && response.text) {
94
+        setOutputText(response.text);
95
+      } else {
96
+        throw new Error('未接收到有效的识别结果');
97
+      }
98
+    } catch (error) {
99
+      console.error('语音识别失败:', error);
100
+      setErrorMessage(`语音识别失败: ${error.message}`);
101
+      toast.error(`语音识别失败: ${error.message}`);
102
+    } finally {
103
+      setLoading(false);
104
+    }
105
+  };
106
+  
107
+  // 处理文本翻译
108
+  const handleTextTranslation = async () => {
109
+    if (!inputText.trim()) {
110
+      setErrorMessage('请输入要翻译的文本');
111
+      return;
112
+    }
113
+    
114
+    setLoading(true);
115
+    setErrorMessage('');
116
+    
117
+    try {
118
+      const response = await translateText(inputText, targetLanguage);
119
+      
120
+      if (response && response.translated_text) {
121
+        setOutputText(response.translated_text);
122
+      } else {
123
+        throw new Error('未接收到有效的翻译结果');
124
+      }
125
+    } catch (error) {
126
+      console.error('文本翻译失败:', error);
127
+      setErrorMessage(`文本翻译失败: ${error.message}`);
128
+      toast.error(`文本翻译失败: ${error.message}`);
129
+    } finally {
130
+      setLoading(false);
131
+    }
132
+  };
133
+  
134
+  // 处理文本摘要
135
+  const handleTextSummarization = async () => {
136
+    if (!inputText.trim()) {
137
+      setErrorMessage('请输入要摘要的文本');
138
+      return;
139
+    }
140
+    
141
+    setLoading(true);
142
+    setErrorMessage('');
143
+    
144
+    try {
145
+      const response = await summarizeText(inputText);
146
+      
147
+      if (response && response.summary) {
148
+        setOutputText(response.summary);
149
+      } else {
150
+        throw new Error('未接收到有效的摘要结果');
151
+      }
152
+    } catch (error) {
153
+      console.error('文本摘要失败:', error);
154
+      setErrorMessage(`文本摘要失败: ${error.message}`);
155
+      toast.error(`文本摘要失败: ${error.message}`);
156
+    } finally {
157
+      setLoading(false);
158
+    }
159
+  };
160
+  
161
+  // 直接调用工作流
162
+  const handleRunWorkflow = async () => {
163
+    if (!workflowId.trim()) {
164
+      setErrorMessage('请输入工作流ID');
165
+      return;
166
+    }
167
+    
168
+    if (!inputText.trim()) {
169
+      setErrorMessage('请输入参数');
170
+      return;
171
+    }
172
+    
173
+    setLoading(true);
174
+    setErrorMessage('');
175
+    
176
+    try {
177
+      // 解析JSON参数
178
+      let parameters = {};
179
+      try {
180
+        parameters = JSON.parse(inputText);
181
+      } catch (e) {
182
+        // 如果不是有效的JSON,则作为text参数传递
183
+        parameters = { text: inputText };
184
+      }
185
+      
186
+      const response = await cozeService.runWorkflow(workflowId, parameters);
187
+      
188
+      // 在实际应用中,您可能需要根据工作流的不同输出格式进行不同的处理
189
+      setOutputText(JSON.stringify(response, null, 2));
190
+    } catch (error) {
191
+      console.error('运行工作流失败:', error);
192
+      setErrorMessage(`运行工作流失败: ${error.message}`);
193
+      toast.error(`运行工作流失败: ${error.message}`);
194
+    } finally {
195
+      setLoading(false);
196
+    }
197
+  };
198
+  
199
+  // 处理音频文件选择
200
+  const handleFileChange = (e) => {
201
+    const file = e.target.files[0];
202
+    if (file) {
203
+      setAudioFile(file);
204
+      // 创建本地URL以便预览
205
+      if (audioUrl) {
206
+        URL.revokeObjectURL(audioUrl);
207
+      }
208
+      const url = URL.createObjectURL(file);
209
+      setAudioUrl(url);
210
+    }
211
+  };
212
+  
213
+  // 辅助函数:将Base64字符串转换为Blob对象
214
+  const base64ToBlob = (base64, mimeType) => {
215
+    const byteString = atob(base64);
216
+    const ab = new ArrayBuffer(byteString.length);
217
+    const ia = new Uint8Array(ab);
218
+    
219
+    for (let i = 0; i < byteString.length; i++) {
220
+      ia[i] = byteString.charCodeAt(i);
221
+    }
222
+    
223
+    return new Blob([ab], { type: mimeType });
224
+  };
225
+  
226
+  // 渲染不同的功能面板
227
+  const renderPanel = () => {
228
+    switch (activeTab) {
229
+      case 'tts':
230
+        return (
231
+          <>
232
+            <Form.Group className="mb-3">
233
+              <Form.Label>输入文本</Form.Label>
234
+              <Form.Control
235
+                as="textarea"
236
+                rows={5}
237
+                value={inputText}
238
+                onChange={(e) => setInputText(e.target.value)}
239
+                placeholder="请输入要转换为语音的文本..."
240
+              />
241
+            </Form.Group>
242
+            
243
+            <Button 
244
+              variant="primary" 
245
+              onClick={handleTextToSpeech}
246
+              disabled={loading || !inputText.trim()}
247
+            >
248
+              {loading ? (
249
+                <>
250
+                  <Spinner size="sm" animation="border" className="me-2" />
251
+                  处理中...
252
+                </>
253
+              ) : '转换为语音'}
254
+            </Button>
255
+            
256
+            {audioUrl && (
257
+              <div className="mt-3">
258
+                <audio ref={audioRef} src={audioUrl} controls className="w-100" />
259
+              </div>
260
+            )}
261
+          </>
262
+        );
263
+        
264
+      case 'stt':
265
+        return (
266
+          <>
267
+            <Form.Group className="mb-3">
268
+              <Form.Label>选择音频文件</Form.Label>
269
+              <Form.Control
270
+                type="file"
271
+                accept="audio/*"
272
+                onChange={handleFileChange}
273
+              />
274
+              <Form.Text className="text-muted">
275
+                支持常见的音频格式,如MP3、WAV等
276
+              </Form.Text>
277
+            </Form.Group>
278
+            
279
+            {audioUrl && (
280
+              <div className="mb-3">
281
+                <audio src={audioUrl} controls className="w-100" />
282
+              </div>
283
+            )}
284
+            
285
+            <Button 
286
+              variant="primary" 
287
+              onClick={handleSpeechToText}
288
+              disabled={loading || !audioFile}
289
+            >
290
+              {loading ? (
291
+                <>
292
+                  <Spinner size="sm" animation="border" className="me-2" />
293
+                  识别中...
294
+                </>
295
+              ) : '识别语音'}
296
+            </Button>
297
+            
298
+            {outputText && (
299
+              <div className="mt-3">
300
+                <Form.Group>
301
+                  <Form.Label>识别结果</Form.Label>
302
+                  <Form.Control
303
+                    as="textarea"
304
+                    rows={5}
305
+                    value={outputText}
306
+                    readOnly
307
+                  />
308
+                </Form.Group>
309
+              </div>
310
+            )}
311
+          </>
312
+        );
313
+        
314
+      case 'translate':
315
+        return (
316
+          <>
317
+            <Form.Group className="mb-3">
318
+              <Form.Label>输入文本</Form.Label>
319
+              <Form.Control
320
+                as="textarea"
321
+                rows={5}
322
+                value={inputText}
323
+                onChange={(e) => setInputText(e.target.value)}
324
+                placeholder="请输入要翻译的文本..."
325
+              />
326
+            </Form.Group>
327
+            
328
+            <Form.Group className="mb-3">
329
+              <Form.Label>目标语言</Form.Label>
330
+              <Form.Select
331
+                value={targetLanguage}
332
+                onChange={(e) => setTargetLanguage(e.target.value)}
333
+              >
334
+                <option value="en">英语</option>
335
+                <option value="zh">中文</option>
336
+                <option value="ja">日语</option>
337
+                <option value="ko">韩语</option>
338
+                <option value="fr">法语</option>
339
+                <option value="de">德语</option>
340
+                <option value="es">西班牙语</option>
341
+                <option value="ru">俄语</option>
342
+              </Form.Select>
343
+            </Form.Group>
344
+            
345
+            <Button 
346
+              variant="primary" 
347
+              onClick={handleTextTranslation}
348
+              disabled={loading || !inputText.trim()}
349
+            >
350
+              {loading ? (
351
+                <>
352
+                  <Spinner size="sm" animation="border" className="me-2" />
353
+                  翻译中...
354
+                </>
355
+              ) : '翻译文本'}
356
+            </Button>
357
+            
358
+            {outputText && (
359
+              <div className="mt-3">
360
+                <Form.Group>
361
+                  <Form.Label>翻译结果</Form.Label>
362
+                  <Form.Control
363
+                    as="textarea"
364
+                    rows={5}
365
+                    value={outputText}
366
+                    readOnly
367
+                  />
368
+                </Form.Group>
369
+              </div>
370
+            )}
371
+          </>
372
+        );
373
+        
374
+      case 'summarize':
375
+        return (
376
+          <>
377
+            <Form.Group className="mb-3">
378
+              <Form.Label>输入文本</Form.Label>
379
+              <Form.Control
380
+                as="textarea"
381
+                rows={5}
382
+                value={inputText}
383
+                onChange={(e) => setInputText(e.target.value)}
384
+                placeholder="请输入要摘要的文本..."
385
+              />
386
+            </Form.Group>
387
+            
388
+            <Button 
389
+              variant="primary" 
390
+              onClick={handleTextSummarization}
391
+              disabled={loading || !inputText.trim()}
392
+            >
393
+              {loading ? (
394
+                <>
395
+                  <Spinner size="sm" animation="border" className="me-2" />
396
+                  摘要中...
397
+                </>
398
+              ) : '生成摘要'}
399
+            </Button>
400
+            
401
+            {outputText && (
402
+              <div className="mt-3">
403
+                <Form.Group>
404
+                  <Form.Label>摘要结果</Form.Label>
405
+                  <Form.Control
406
+                    as="textarea"
407
+                    rows={5}
408
+                    value={outputText}
409
+                    readOnly
410
+                  />
411
+                </Form.Group>
412
+              </div>
413
+            )}
414
+          </>
415
+        );
416
+        
417
+      case 'custom':
418
+        return (
419
+          <>
420
+            <Form.Group className="mb-3">
421
+              <Form.Label>工作流ID</Form.Label>
422
+              <Form.Control
423
+                type="text"
424
+                value={workflowId}
425
+                onChange={(e) => setWorkflowId(e.target.value)}
426
+                placeholder="请输入Coze工作流ID..."
427
+              />
428
+            </Form.Group>
429
+            
430
+            <Form.Group className="mb-3">
431
+              <Form.Label>参数 (JSON格式或文本)</Form.Label>
432
+              <Form.Control
433
+                as="textarea"
434
+                rows={5}
435
+                value={inputText}
436
+                onChange={(e) => setInputText(e.target.value)}
437
+                placeholder='{"key": "value"} 或直接输入文本'
438
+              />
439
+            </Form.Group>
440
+            
441
+            <Button 
442
+              variant="primary" 
443
+              onClick={handleRunWorkflow}
444
+              disabled={loading || !workflowId.trim() || !inputText.trim()}
445
+            >
446
+              {loading ? (
447
+                <>
448
+                  <Spinner size="sm" animation="border" className="me-2" />
449
+                  处理中...
450
+                </>
451
+              ) : '运行工作流'}
452
+            </Button>
453
+            
454
+            {outputText && (
455
+              <div className="mt-3">
456
+                <Form.Group>
457
+                  <Form.Label>输出结果</Form.Label>
458
+                  <Form.Control
459
+                    as="textarea"
460
+                    rows={5}
461
+                    value={outputText}
462
+                    readOnly
463
+                  />
464
+                </Form.Group>
465
+              </div>
466
+            )}
467
+          </>
468
+        );
469
+        
470
+      default:
471
+        return null;
472
+    }
473
+  };
474
+  
475
+  return (
476
+    <Container className="my-4">
477
+      <h2 className="mb-4 text-center">Coze工作流演示</h2>
478
+      
479
+      {errorMessage && (
480
+        <Alert variant="danger" className="mb-3" onClose={() => setErrorMessage('')} dismissible>
481
+          {errorMessage}
482
+        </Alert>
483
+      )}
484
+      
485
+      <Card>
486
+        <Card.Header>
487
+          <Nav variant="tabs" className="flex-row">
488
+            <Nav.Item>
489
+              <Nav.Link 
490
+                active={activeTab === 'tts'} 
491
+                onClick={() => setActiveTab('tts')}
492
+              >
493
+                文本转语音
494
+              </Nav.Link>
495
+            </Nav.Item>
496
+            <Nav.Item>
497
+              <Nav.Link 
498
+                active={activeTab === 'stt'} 
499
+                onClick={() => setActiveTab('stt')}
500
+              >
501
+                语音识别
502
+              </Nav.Link>
503
+            </Nav.Item>
504
+            <Nav.Item>
505
+              <Nav.Link 
506
+                active={activeTab === 'translate'} 
507
+                onClick={() => setActiveTab('translate')}
508
+              >
509
+                文本翻译
510
+              </Nav.Link>
511
+            </Nav.Item>
512
+            <Nav.Item>
513
+              <Nav.Link 
514
+                active={activeTab === 'summarize'} 
515
+                onClick={() => setActiveTab('summarize')}
516
+              >
517
+                文本摘要
518
+              </Nav.Link>
519
+            </Nav.Item>
520
+            <Nav.Item>
521
+              <Nav.Link 
522
+                active={activeTab === 'custom'} 
523
+                onClick={() => setActiveTab('custom')}
524
+              >
525
+                自定义工作流
526
+              </Nav.Link>
527
+            </Nav.Item>
528
+          </Nav>
529
+        </Card.Header>
530
+        <Card.Body>
531
+          {renderPanel()}
532
+        </Card.Body>
533
+      </Card>
534
+    </Container>
535
+  );
536
+};
537
+
538
+export default CozeWorkflowDemo; 

+ 116 - 0
src/components/audioPlayer/index.js

@@ -0,0 +1,116 @@
1
+import React, { useState, useEffect } from 'react';
2
+import PropTypes from 'prop-types';
3
+import AudioPlayer from 'react-h5-audio-player';
4
+import 'react-h5-audio-player/lib/styles.css';
5
+import { path } from 'path-browserify';
6
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
7
+import { faMusic, faFileAudio } from '@fortawesome/free-solid-svg-icons';
8
+import './style.css';
9
+
10
+/**
11
+ * 音频播放器组件
12
+ * @param {Object} props 组件属性
13
+ * @param {string} props.audioPath 音频文件路径
14
+ * @param {string} props.label 显示的标签
15
+ * @param {function} props.onPlay 播放事件回调
16
+ * @param {function} props.onPause 暂停事件回调
17
+ */
18
+const AudioPlayerComponent = ({ audioPath, label, onPlay, onPause }) => {
19
+  const [audioFile, setAudioFile] = useState(null);
20
+  const [audioInfo, setAudioInfo] = useState({
21
+    fileName: '',
22
+    fileSize: ''
23
+  });
24
+  
25
+  useEffect(() => {
26
+    if (audioPath) {
27
+      // 设置文件路径
28
+      setAudioFile(audioPath);
29
+      
30
+      // 提取文件名
31
+      const fileName = path.basename(audioPath);
32
+      
33
+      // 获取文件大小信息
34
+      try {
35
+        // 通过Electron的fs模块获取文件信息
36
+        window.electron.ipcRenderer.invoke('get-file-stats', audioPath)
37
+          .then(stats => {
38
+            if (stats) {
39
+              setAudioInfo({
40
+                fileName,
41
+                fileSize: formatFileSize(stats.size)
42
+              });
43
+            }
44
+          })
45
+          .catch(err => {
46
+            console.error('获取音频文件信息时出错:', err);
47
+          });
48
+      } catch (error) {
49
+        console.error('处理音频文件路径时出错:', error);
50
+      }
51
+    }
52
+  }, [audioPath]);
53
+  
54
+  /**
55
+   * 格式化文件大小
56
+   * @param {number} bytes 文件大小(字节)
57
+   * @returns {string} 格式化后的文件大小
58
+   */
59
+  const formatFileSize = (bytes) => {
60
+    if (bytes === 0) return '0 字节';
61
+    
62
+    const sizes = ['字节', 'KB', 'MB', 'GB', 'TB'];
63
+    const i = Math.floor(Math.log(bytes) / Math.log(1024));
64
+    return parseFloat((bytes / Math.pow(1024, i)).toFixed(2)) + ' ' + sizes[i];
65
+  };
66
+  
67
+  if (!audioFile) {
68
+    return (
69
+      <div className="audio-player-placeholder">
70
+        <FontAwesomeIcon icon={faMusic} size="lg" />
71
+        <span>未找到音频文件</span>
72
+      </div>
73
+    );
74
+  }
75
+  
76
+  return (
77
+    <div className="audio-player-container">
78
+      <div className="audio-info">
79
+        <FontAwesomeIcon icon={faFileAudio} size="lg" />
80
+        <div className="audio-details">
81
+          {label && <div className="audio-label">{label}</div>}
82
+          <div className="audio-filename">{audioInfo.fileName}</div>
83
+          <div className="audio-filesize">{audioInfo.fileSize}</div>
84
+        </div>
85
+      </div>
86
+      
87
+      <div className="audio-player-wrapper">
88
+        <AudioPlayer
89
+          src={`file://${audioFile}`}
90
+          showJumpControls={true}
91
+          showSkipControls={false}
92
+          layout="horizontal"
93
+          customAdditionalControls={[]}
94
+          onPlay={onPlay}
95
+          onPause={onPause}
96
+          autoPlayAfterSrcChange={false}
97
+        />
98
+      </div>
99
+    </div>
100
+  );
101
+};
102
+
103
+AudioPlayerComponent.propTypes = {
104
+  audioPath: PropTypes.string,
105
+  label: PropTypes.string,
106
+  onPlay: PropTypes.func,
107
+  onPause: PropTypes.func
108
+};
109
+
110
+AudioPlayerComponent.defaultProps = {
111
+  label: '项目音频',
112
+  onPlay: () => {},
113
+  onPause: () => {}
114
+};
115
+
116
+export default AudioPlayerComponent; 

+ 99 - 0
src/components/audioPlayer/style.css

@@ -0,0 +1,99 @@
1
+.audio-player-container {
2
+  background-color: #f8f9fa;
3
+  border-radius: 8px;
4
+  padding: 12px;
5
+  margin-bottom: 16px;
6
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
7
+}
8
+
9
+.audio-info {
10
+  display: flex;
11
+  align-items: center;
12
+  margin-bottom: 10px;
13
+}
14
+
15
+.audio-info svg {
16
+  color: #0d6efd;
17
+  margin-right: 10px;
18
+  font-size: 24px;
19
+}
20
+
21
+.audio-details {
22
+  flex: 1;
23
+}
24
+
25
+.audio-label {
26
+  font-weight: bold;
27
+  color: #212529;
28
+  margin-bottom: 2px;
29
+}
30
+
31
+.audio-filename {
32
+  font-size: 0.9rem;
33
+  color: #6c757d;
34
+  margin-bottom: 2px;
35
+  white-space: nowrap;
36
+  overflow: hidden;
37
+  text-overflow: ellipsis;
38
+  max-width: 300px;
39
+}
40
+
41
+.audio-filesize {
42
+  font-size: 0.8rem;
43
+  color: #6c757d;
44
+}
45
+
46
+.audio-player-wrapper {
47
+  margin-top: 8px;
48
+}
49
+
50
+/* 自定义播放器样式 */
51
+.audio-player-wrapper .rhap_container {
52
+  background-color: #ffffff;
53
+  box-shadow: none;
54
+  padding: 8px;
55
+  border-radius: 4px;
56
+}
57
+
58
+.audio-player-wrapper .rhap_main-controls-button {
59
+  color: #0d6efd;
60
+}
61
+
62
+.audio-player-wrapper .rhap_progress-indicator {
63
+  background-color: #0d6efd;
64
+}
65
+
66
+.audio-player-wrapper .rhap_progress-filled {
67
+  background-color: #0d6efd;
68
+}
69
+
70
+.audio-player-wrapper .rhap_download-progress {
71
+  background-color: #e9ecef;
72
+}
73
+
74
+.audio-player-placeholder {
75
+  display: flex;
76
+  flex-direction: column;
77
+  align-items: center;
78
+  justify-content: center;
79
+  background-color: #f8f9fa;
80
+  border-radius: 8px;
81
+  padding: 20px;
82
+  color: #6c757d;
83
+}
84
+
85
+.audio-player-placeholder svg {
86
+  margin-bottom: 8px;
87
+  color: #adb5bd;
88
+}
89
+
90
+/* 响应式调整 */
91
+@media (max-width: 576px) {
92
+  .audio-player-container {
93
+    padding: 8px;
94
+  }
95
+  
96
+  .audio-filename {
97
+    max-width: 200px;
98
+  }
99
+} 

+ 65 - 0
src/components/audioUpload/index.js

@@ -0,0 +1,65 @@
1
+import React, { useState } from 'react';
2
+import { Button, Form, Spinner, Card } from 'react-bootstrap';
3
+import { toast } from 'react-toastify';
4
+import './style.css';
5
+
6
+const AudioUpload = ({ onAudioSelected }) => {
7
+  const [audioFile, setAudioFile] = useState(null);
8
+  const [loading, setLoading] = useState(false);
9
+  const [audioFileName, setAudioFileName] = useState('');
10
+
11
+  // 处理音频文件选择
12
+  const handleAudioFileChange = (e) => {
13
+    const selectedFile = e.target.files[0];
14
+    if (selectedFile) {
15
+      setAudioFile(selectedFile);
16
+      setAudioFileName(selectedFile.name);
17
+      
18
+      // 调用回调函数将音频文件传递给父组件
19
+      if (typeof onAudioSelected === 'function') {
20
+        onAudioSelected(selectedFile);
21
+      }
22
+    }
23
+  };
24
+
25
+  return (
26
+    <div className="audio-upload-container">
27
+      <Card>
28
+        <Card.Header as="h5">上传音频(必选)</Card.Header>
29
+        <Card.Body>
30
+          <Form>
31
+            <Form.Group controlId="audioFile" className="mb-3">
32
+              <Form.Label>选择音频文件</Form.Label>
33
+              <div className="custom-file-upload">
34
+                <input
35
+                  type="file"
36
+                  accept="audio/*"
37
+                  onChange={handleAudioFileChange}
38
+                  id="audio-file-input"
39
+                  className="d-none"
40
+                  required
41
+                />
42
+                <div className="file-upload-box">
43
+                  <Button 
44
+                    variant="outline-primary" 
45
+                    onClick={() => document.getElementById('audio-file-input').click()}
46
+                  >
47
+                    选择音频
48
+                  </Button>
49
+                  <span className="ml-2">{audioFileName || '未选择音频文件'}</span>
50
+                </div>
51
+              </div>
52
+              {!audioFile && (
53
+                <Form.Text className="text-danger">
54
+                  请上传音频文件,这是必选项
55
+                </Form.Text>
56
+              )}
57
+            </Form.Group>
58
+          </Form>
59
+        </Card.Body>
60
+      </Card>
61
+    </div>
62
+  );
63
+};
64
+
65
+export default AudioUpload; 

+ 27 - 0
src/components/audioUpload/style.css

@@ -0,0 +1,27 @@
1
+.audio-upload-container {
2
+  margin-bottom: 20px;
3
+}
4
+
5
+.custom-file-upload {
6
+  display: flex;
7
+  align-items: center;
8
+  margin-bottom: 10px;
9
+}
10
+
11
+.file-upload-box {
12
+  display: flex;
13
+  align-items: center;
14
+  width: 100%;
15
+}
16
+
17
+.file-upload-box span {
18
+  margin-left: 10px;
19
+  overflow: hidden;
20
+  text-overflow: ellipsis;
21
+  white-space: nowrap;
22
+}
23
+
24
+.audio-player {
25
+  width: 100%;
26
+  margin-top: 10px;
27
+} 

+ 531 - 0
src/components/subtitleUpload/index.js

@@ -0,0 +1,531 @@
1
+import React, { useState } from 'react';
2
+import { Button, Form, Spinner, Card, ListGroup, Modal, InputGroup, Alert } from 'react-bootstrap';
3
+import { toast } from 'react-toastify';
4
+import './style.css';
5
+import { bookService, bookInfoService } from '../../db';
6
+import { processProjectAudio } from '../../utils/audioProcessor'; // 导入音频处理工具
7
+// 替换Node.js模块为浏览器兼容版本
8
+// const fs = require('fs');
9
+// const path = require('path');
10
+// const os = require('os');
11
+import path from 'path-browserify';
12
+import os from 'os-browserify/browser';
13
+// fs模块在浏览器中不可用,需要通过IPC调用主进程
14
+
15
+const SubtitleUpload = ({ onProjectCreated, projectAudioFile }) => {
16
+  const [file, setFile] = useState(null);
17
+  const [isLoading, setIsLoading] = useState(false);
18
+  const [subtitles, setSubtitles] = useState([]);
19
+  const [fileName, setFileName] = useState('');
20
+  const [showCreateModal, setShowCreateModal] = useState(false);
21
+  const [projectTitle, setProjectTitle] = useState('');
22
+  const [isCreating, setIsCreating] = useState(false);
23
+  const [processingAudio, setProcessingAudio] = useState(false);
24
+  const [audioProgress, setAudioProgress] = useState(0);
25
+
26
+  // 处理文件选择
27
+  const handleFileChange = (e) => {
28
+    const selectedFile = e.target.files[0];
29
+    if (selectedFile) {
30
+      setFile(selectedFile);
31
+      setFileName(selectedFile.name);
32
+    }
33
+  };
34
+
35
+  // 解析SRT格式字幕
36
+  const parseSRT = (content) => {
37
+    const srtRegex = /(\d+)\r?\n(\d{2}:\d{2}:\d{2},\d{3}) --> (\d{2}:\d{2}:\d{2},\d{3})\r?\n([\s\S]*?)(?=\r?\n\r?\n\d+|$)/g;
38
+    const subtitles = [];
39
+    let match;
40
+
41
+    while ((match = srtRegex.exec(content)) !== null) {
42
+      subtitles.push({
43
+        id: parseInt(match[1]),
44
+        startTime: match[2],
45
+        endTime: match[3],
46
+        text: match[4].trim()
47
+      });
48
+    }
49
+
50
+    return subtitles;
51
+  };
52
+
53
+  // 解析VTT格式字幕
54
+  const parseVTT = (content) => {
55
+    // 移除WEBVTT头部
56
+    const lines = content.replace(/^WEBVTT\r?\n/, '').split(/\r?\n\r?\n/);
57
+    const subtitles = [];
58
+    
59
+    lines.forEach((block, index) => {
60
+      const lines = block.split(/\r?\n/);
61
+      if (lines.length >= 2) {
62
+        // 检查时间戳行
63
+        const timeLine = lines.find(line => line.includes(' --> '));
64
+        if (timeLine) {
65
+          const [startTime, endTime] = timeLine.split(' --> ');
66
+          const textLines = lines.filter(line => line !== timeLine && !line.match(/^\d+$/));
67
+          
68
+          subtitles.push({
69
+            id: index + 1,
70
+            startTime: startTime,
71
+            endTime: endTime,
72
+            text: textLines.join(' ').trim()
73
+          });
74
+        }
75
+      }
76
+    });
77
+
78
+    return subtitles;
79
+  };
80
+
81
+  // 上传并解析字幕
82
+  const handleUpload = () => {
83
+    if (!file) {
84
+      toast.error('请先选择字幕文件');
85
+      return;
86
+    }
87
+
88
+    setIsLoading(true);
89
+    const reader = new FileReader();
90
+    
91
+    reader.onload = (e) => {
92
+      try {
93
+        const content = e.target.result;
94
+        let parsedSubtitles = [];
95
+        
96
+        if (file.name.endsWith('.srt')) {
97
+          parsedSubtitles = parseSRT(content);
98
+        } else if (file.name.endsWith('.vtt')) {
99
+          parsedSubtitles = parseVTT(content);
100
+        } else {
101
+          throw new Error('不支持的字幕格式,请上传.srt或.vtt格式的字幕文件');
102
+        }
103
+        
104
+        if (parsedSubtitles.length > 0) {
105
+          setSubtitles(parsedSubtitles);
106
+          toast.success(`成功解析 ${parsedSubtitles.length} 条字幕`);
107
+        } else {
108
+          toast.warning('未能解析出任何字幕内容,请检查文件格式');
109
+        }
110
+      } catch (error) {
111
+        toast.error(`解析字幕失败: ${error.message}`);
112
+      } finally {
113
+        setIsLoading(false);
114
+      }
115
+    };
116
+    
117
+    reader.onerror = () => {
118
+      toast.error('读取文件失败');
119
+      setIsLoading(false);
120
+    };
121
+    
122
+    reader.readAsText(file);
123
+  };
124
+
125
+  // 打开创建项目模态框
126
+  const openCreateProjectModal = () => {
127
+    if (subtitles.length === 0) {
128
+      toast.error('请先上传并解析字幕文件');
129
+      return;
130
+    }
131
+    
132
+    if (!projectAudioFile) {
133
+      toast.error('请先上传音频文件(必选)');
134
+      return;
135
+    }
136
+    
137
+    setShowCreateModal(true);
138
+  };
139
+
140
+  // 获取应用数据路径
141
+  const getAppDataPath = async () => {
142
+    try {
143
+      // 首先通过IPC获取数据库路径
144
+      const dbPath = await window.electron.ipcRenderer.invoke('db:getPath');
145
+      
146
+      // 数据库路径示例: /Users/username/Library/Application Support/lip_sync/database.sqlite
147
+      // 提取基础目录
148
+      let basePath = '';
149
+      if (dbPath) {
150
+        const lastSlashIndex = Math.max(dbPath.lastIndexOf('/'), dbPath.lastIndexOf('\\'));
151
+        if (lastSlashIndex !== -1) {
152
+          basePath = dbPath.substring(0, lastSlashIndex);
153
+        }
154
+      } else {
155
+        // 备用方案:使用基于平台的默认路径
156
+        const platform = process?.platform || 'unknown';
157
+        
158
+        if (platform === 'win32') {
159
+          // Windows
160
+          basePath = path.join(process.env.APPDATA || '', 'lip_sync');
161
+        } else if (platform === 'darwin') {
162
+          // macOS
163
+          basePath = path.join(os.homedir(), 'Library/Application Support/lip_sync');
164
+        } else {
165
+          // Linux或其他
166
+          basePath = path.join(os.homedir(), '.local/share/lip_sync');
167
+        }
168
+      }
169
+      
170
+      // 添加资源子目录
171
+      const resourcePath = path.join(basePath, 'resources');
172
+      const audioPath = path.join(resourcePath, 'audio');
173
+      
174
+      console.log('音频文件路径:', audioPath);
175
+      return audioPath;
176
+    } catch (error) {
177
+      console.error('获取应用数据路径失败:', error);
178
+      return null;
179
+    }
180
+  };
181
+
182
+  // 保存音频文件到本地
183
+  const saveAudioFile = async (audioFile, projectId) => {
184
+    try {
185
+      const audioDir = await getAppDataPath();
186
+      if (!audioDir) {
187
+        throw new Error('无法获取音频存储路径');
188
+      }
189
+      
190
+      const fileName = `project_${projectId}_full.mp3`;
191
+      
192
+      // 读取文件内容
193
+      const buffer = await audioFile.arrayBuffer();
194
+      
195
+      // 检查electron对象是否存在
196
+      if (typeof window.electron !== 'undefined' && window.electron.ipcRenderer) {
197
+        // 通过IPC调用保存文件
198
+        const result = await window.electron.ipcRenderer.invoke('save-audio-file', {
199
+          buffer: Array.from(new Uint8Array(buffer)),
200
+          fileName: fileName,
201
+          directory: audioDir,
202
+          projectId: projectId
203
+        });
204
+        
205
+        if (result.success) {
206
+          return {
207
+            success: true,
208
+            path: result.filePath,
209
+            relativePath: path.join('audio', fileName)
210
+          };
211
+        } else {
212
+          throw new Error(result.error);
213
+        }
214
+      } else {
215
+        // 处理非Electron环境(例如开发环境中的Web浏览器)
216
+        console.warn('Electron IPC不可用,无法保存文件到本地');
217
+        
218
+        // 模拟成功返回,用于开发环境测试
219
+        return {
220
+          success: true,
221
+          path: path.join(audioDir, fileName),
222
+          relativePath: path.join('audio', fileName)
223
+        };
224
+      }
225
+    } catch (error) {
226
+      console.error('保存音频文件失败:', error);
227
+      return {
228
+        success: false,
229
+        error: error.message
230
+      };
231
+    }
232
+  };
233
+
234
+  // 创建项目
235
+  const handleCreateProject = async () => {
236
+    if (!projectTitle.trim()) {
237
+      toast.error('请输入项目标题');
238
+      return;
239
+    }
240
+
241
+    if (!projectAudioFile) {
242
+      toast.error('请上传音频文件(必选)');
243
+      return;
244
+    }
245
+
246
+    setIsCreating(true);
247
+    try {
248
+      // 创建项目记录
249
+      const bookId = await bookService.createBook({
250
+        title: projectTitle,
251
+        subtitle_path: file ? file.name : null,
252
+        audio_path: projectAudioFile ? projectAudioFile.name : null,
253
+        created_at: new Date().toISOString()
254
+      });
255
+
256
+      // 为每个字幕段计算持续时间
257
+      const processedSubtitles = subtitles.map(sub => {
258
+        // 解析开始和结束时间
259
+        const startParts = sub.startTime.replace(',', '.').split(':').map(Number);
260
+        const endParts = sub.endTime.replace(',', '.').split(':').map(Number);
261
+        
262
+        // 计算开始和结束时间(秒)
263
+        const startSeconds = startParts[0] * 3600 + startParts[1] * 60 + parseFloat(startParts[2]);
264
+        const endSeconds = endParts[0] * 3600 + endParts[1] * 60 + parseFloat(endParts[2]);
265
+        
266
+        // 计算持续时间
267
+        const durationSeconds = endSeconds - startSeconds;
268
+        
269
+        return {
270
+          ...sub,
271
+          duration: durationSeconds.toFixed(3)
272
+        };
273
+      });
274
+
275
+      // 创建项目详细信息(先不包含音频路径)
276
+      const bookInfoPromises = processedSubtitles.map(sub => {
277
+        return bookInfoService.createBookInfo({
278
+          book_id: bookId,
279
+          segment_id: sub.id,
280
+          start_time: sub.startTime,
281
+          end_time: sub.endTime,
282
+          duration: sub.duration,
283
+          text: sub.text
284
+        });
285
+      });
286
+
287
+      const createdSegments = await Promise.all(bookInfoPromises);
288
+      
289
+      // 处理音频文件
290
+      setProcessingAudio(true);
291
+      toast.info('正在处理音频文件,请稍候...');
292
+      
293
+      // 保存完整音频文件
294
+      const savedAudio = await saveAudioFile(projectAudioFile, bookId);
295
+      
296
+      if (savedAudio.success) {
297
+        // 更新项目记录中的音频路径为相对路径
298
+        await bookService.updateBook(bookId, {
299
+          audio_path: savedAudio.relativePath
300
+        });
301
+        
302
+        // 获取所有已创建的分镜信息
303
+        const segments = await bookInfoService.getBookInfoByBookId(bookId);
304
+        
305
+        // 切割音频
306
+        const audioProcessResult = await processProjectAudio(
307
+          bookId,
308
+          savedAudio.path,
309
+          segments,
310
+          getAppDataPath()
311
+        );
312
+        
313
+        if (audioProcessResult.success) {
314
+          // 更新每个分镜的音频路径
315
+          const updatePromises = audioProcessResult.segments.map(segment => {
316
+            return bookInfoService.updateBookInfo(segment.segmentId, {
317
+              audio_path: segment.relativePath
318
+            });
319
+          });
320
+          
321
+          await Promise.all(updatePromises);
322
+          
323
+          toast.success(`音频处理完成,已为 ${audioProcessResult.processedSegments}/${audioProcessResult.totalSegments} 个分镜生成独立音频`);
324
+        } else {
325
+          toast.warning(`音频切割过程中出现一些问题: ${audioProcessResult.error}`);
326
+        }
327
+      } else {
328
+        toast.warning(`保存音频文件失败: ${savedAudio.error}`);
329
+      }
330
+
331
+      toast.success('项目创建成功!');
332
+      setShowCreateModal(false);
333
+      
334
+      // 重置表单
335
+      setProjectTitle('');
336
+      setFile(null);
337
+      setFileName('');
338
+      setSubtitles([]);
339
+      setProcessingAudio(false);
340
+      
341
+      // 调用回调函数
342
+      if (typeof onProjectCreated === 'function') {
343
+        onProjectCreated();
344
+      }
345
+    } catch (error) {
346
+      console.error('创建项目失败:', error);
347
+      toast.error(`创建项目失败: ${error.message}`);
348
+    } finally {
349
+      setIsCreating(false);
350
+      setProcessingAudio(false);
351
+    }
352
+  };
353
+
354
+  return (
355
+    <div className="subtitle-upload-container">
356
+      <Card>
357
+        <Card.Header as="h5">上传字幕</Card.Header>
358
+        <Card.Body>
359
+          <Form>
360
+            <Form.Group controlId="subtitleFile" className="mb-3">
361
+              <Form.Label>选择字幕文件 (.srt 或 .vtt 格式)</Form.Label>
362
+              <div className="custom-file-upload">
363
+                <input
364
+                  type="file"
365
+                  accept=".srt,.vtt"
366
+                  onChange={handleFileChange}
367
+                  id="subtitle-file-input"
368
+                  className="d-none"
369
+                />
370
+                <div className="file-upload-box">
371
+                  <Button 
372
+                    variant="outline-primary" 
373
+                    onClick={() => document.getElementById('subtitle-file-input').click()}
374
+                  >
375
+                    选择文件
376
+                  </Button>
377
+                  <span className="ml-2">{fileName || '未选择文件'}</span>
378
+                </div>
379
+              </div>
380
+            </Form.Group>
381
+            
382
+            <Button 
383
+              variant="primary" 
384
+              onClick={handleUpload}
385
+              disabled={isLoading || !file}
386
+              className="w-100"
387
+            >
388
+              {isLoading ? (
389
+                <>
390
+                  <Spinner
391
+                    as="span"
392
+                    animation="border"
393
+                    size="sm"
394
+                    role="status"
395
+                    aria-hidden="true"
396
+                  />
397
+                  <span className="ml-2">处理中...</span>
398
+                </>
399
+              ) : (
400
+                '上传并解析字幕'
401
+              )}
402
+            </Button>
403
+          </Form>
404
+          
405
+          {subtitles.length > 0 && (
406
+            <>
407
+              <div className="mt-4">
408
+                <h5>解析结果 ({subtitles.length} 条字幕)</h5>
409
+                <div className="subtitle-list">
410
+                  <ListGroup>
411
+                    {subtitles.map((subtitle) => (
412
+                      <ListGroup.Item key={subtitle.id}>
413
+                        <div className="subtitle-item">
414
+                          <div className="subtitle-time">
415
+                            {subtitle.startTime} → {subtitle.endTime}
416
+                          </div>
417
+                          <div className="subtitle-text">{subtitle.text}</div>
418
+                        </div>
419
+                      </ListGroup.Item>
420
+                    ))}
421
+                  </ListGroup>
422
+                </div>
423
+              </div>
424
+              
425
+              <div className="mt-4 text-center">
426
+                <Button 
427
+                  variant="success" 
428
+                  size="lg" 
429
+                  onClick={openCreateProjectModal}
430
+                  disabled={!projectAudioFile}
431
+                >
432
+                  创建项目
433
+                </Button>
434
+                {!projectAudioFile && (
435
+                  <div className="text-danger mt-2">
436
+                    请先上传音频文件(必选)
437
+                  </div>
438
+                )}
439
+              </div>
440
+            </>
441
+          )}
442
+        </Card.Body>
443
+      </Card>
444
+
445
+      {/* 创建项目模态框 */}
446
+      <Modal show={showCreateModal} onHide={() => !isCreating && !processingAudio && setShowCreateModal(false)}>
447
+        <Modal.Header closeButton={!isCreating && !processingAudio}>
448
+          <Modal.Title>创建新项目</Modal.Title>
449
+        </Modal.Header>
450
+        <Modal.Body>
451
+          <Form>
452
+            <Form.Group controlId="projectTitle">
453
+              <Form.Label>项目标题</Form.Label>
454
+              <Form.Control
455
+                type="text"
456
+                placeholder="请输入项目标题"
457
+                value={projectTitle}
458
+                onChange={(e) => setProjectTitle(e.target.value)}
459
+                disabled={isCreating || processingAudio}
460
+              />
461
+            </Form.Group>
462
+            <Form.Group className="mt-3">
463
+              <Form.Label>字幕文件</Form.Label>
464
+              <InputGroup>
465
+                <Form.Control
466
+                  readOnly
467
+                  value={fileName}
468
+                />
469
+              </InputGroup>
470
+            </Form.Group>
471
+            <Form.Group className="mt-3">
472
+              <Form.Label>音频文件</Form.Label>
473
+              <InputGroup>
474
+                <Form.Control
475
+                  readOnly
476
+                  value={projectAudioFile ? projectAudioFile.name : '未选择音频文件'}
477
+                />
478
+              </InputGroup>
479
+            </Form.Group>
480
+            <Form.Group className="mt-3">
481
+              <Form.Label>字幕条数</Form.Label>
482
+              <Form.Control
483
+                readOnly
484
+                value={`${subtitles.length} 条`}
485
+              />
486
+            </Form.Group>
487
+            
488
+            {processingAudio && (
489
+              <div className="mt-3">
490
+                <Alert variant="info">
491
+                  正在处理音频文件,请稍候...这可能需要一些时间。
492
+                </Alert>
493
+              </div>
494
+            )}
495
+          </Form>
496
+        </Modal.Body>
497
+        <Modal.Footer>
498
+          <Button 
499
+            variant="secondary" 
500
+            onClick={() => setShowCreateModal(false)}
501
+            disabled={isCreating || processingAudio}
502
+          >
503
+            取消
504
+          </Button>
505
+          <Button 
506
+            variant="primary" 
507
+            onClick={handleCreateProject}
508
+            disabled={isCreating || processingAudio}
509
+          >
510
+            {isCreating || processingAudio ? (
511
+              <>
512
+                <Spinner
513
+                  as="span"
514
+                  animation="border"
515
+                  size="sm"
516
+                  role="status"
517
+                  aria-hidden="true"
518
+                />
519
+                <span className="ml-2">{processingAudio ? '处理音频中...' : '创建中...'}</span>
520
+              </>
521
+            ) : (
522
+              '确认创建'
523
+            )}
524
+          </Button>
525
+        </Modal.Footer>
526
+      </Modal>
527
+    </div>
528
+  );
529
+};
530
+
531
+export default SubtitleUpload; 

+ 50 - 0
src/components/subtitleUpload/style.css

@@ -0,0 +1,50 @@
1
+.subtitle-upload-container {
2
+  margin-top: 20px;
3
+  margin-bottom: 20px;
4
+}
5
+
6
+.custom-file-upload {
7
+  margin-bottom: 15px;
8
+}
9
+
10
+.file-upload-box {
11
+  display: flex;
12
+  align-items: center;
13
+  gap: 10px;
14
+}
15
+
16
+.subtitle-list {
17
+  max-height: 300px;
18
+  overflow-y: auto;
19
+  margin-top: 10px;
20
+  border: 1px solid #dee2e6;
21
+  border-radius: 4px;
22
+}
23
+
24
+.subtitle-item {
25
+  display: flex;
26
+  flex-direction: column;
27
+}
28
+
29
+.subtitle-time {
30
+  font-size: 0.85rem;
31
+  color: #6c757d;
32
+  margin-bottom: 5px;
33
+}
34
+
35
+.subtitle-text {
36
+  font-size: 1rem;
37
+}
38
+
39
+/* 响应式调整 */
40
+@media (max-width: 768px) {
41
+  .file-upload-box {
42
+    flex-direction: column;
43
+    align-items: flex-start;
44
+  }
45
+  
46
+  .file-upload-box span {
47
+    margin-top: 5px;
48
+    word-break: break-all;
49
+  }
50
+} 

+ 70 - 0
src/components/videoDownload/index.css

@@ -0,0 +1,70 @@
1
+.video-down {}
2
+
3
+.updata-title {}
4
+
5
+.close-video {
6
+  margin-top: 10px;
7
+  width: 100%;
8
+  display: flex;
9
+}
10
+
11
+.close-video-type {
12
+  border-radius: 5px;
13
+  display: flex;
14
+  font-size: 14px;
15
+  border: 1px solid #b8beba;
16
+}
17
+
18
+.close-video-type-left {
19
+  padding: 8px 10px;
20
+}
21
+
22
+.close-video-type-right {
23
+  padding: 8px 10px;
24
+}
25
+
26
+.close-video-content {
27
+  margin-top: 20px;
28
+  border-radius: 10px;
29
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
30
+  padding: 10px;
31
+}
32
+
33
+.video-content-all {
34
+  margin-top: 10px !important;
35
+  display: flex;
36
+  align-items: center;
37
+  flex-wrap: wrap;
38
+}
39
+
40
+.video-content-url {
41
+  position: relative;
42
+  width: 33%;
43
+  margin-right: 1%;
44
+}
45
+
46
+.content-url-video {
47
+  width: 100%;
48
+  border-radius: 5px;
49
+}
50
+
51
+.close-img {
52
+  position: absolute;
53
+  top: 5px;
54
+  left: 5px;
55
+  width: 50px;
56
+  height: 50px;
57
+}
58
+
59
+.close-img-con {
60
+  width: 100%;
61
+  height: 100%;
62
+}
63
+
64
+@media screen and (max-width: 600px) {
65
+  .video-content-url {
66
+    position: relative;
67
+    width: 100%;
68
+    margin-right: 0;
69
+  }
70
+}

+ 107 - 0
src/components/videoDownload/index.js

@@ -0,0 +1,107 @@
1
+import React, { useState, forwardRef } from 'react';
2
+import { ButtonGroup, Button, Row, Col, Spinner, Form } from 'react-bootstrap';
3
+import ApiService from '../../api/ApiService';
4
+import LocalDataService from '../../api/LocalDataService';
5
+import { toast } from 'react-toastify';
6
+
7
+const VideoDown = forwardRef((props, ref) => {
8
+  const [searchVideoUrl, setSearchVideoUrl] = useState('');
9
+  const [videoUrlList, setVideoUrlList] = useState([]);
10
+  const [isLoading, setIsLoading] = useState(false);
11
+
12
+  const searchVideo = async () => {
13
+    setIsLoading(true);
14
+    const text = searchVideoUrl;
15
+    const regex = /(https?:\/\/[^\s]+)/;
16
+    const match = text.match(regex);
17
+    const firstLink = match ? match[0] : "";
18
+    let user = LocalDataService.load_user_data();
19
+    const api = new ApiService();
20
+    let json = await api.down_load_video(user.token, firstLink);
21
+    setIsLoading(false);
22
+    if (json.status) {
23
+      toast.error('搜索失败,链接错误,请重新输入');
24
+    } else {
25
+      let videoUrlList = json.medias.filter(item => item.type === 'video' || item.extension === 'mp4' || item.extension === 'mp3');
26
+      setVideoUrlList(videoUrlList);
27
+    }
28
+  }
29
+
30
+  const getBtnTitle = (quality) => {
31
+    const titles = {
32
+      'hd_no_watermark': '高清无水印',
33
+      'no_watermark': '无水印',
34
+      'watermark': '水印',
35
+      'audio': '音频'
36
+    };
37
+    return titles[quality] || quality;
38
+  }
39
+
40
+  return (
41
+    <div >
42
+      <div >
43
+        <div className='mt-3'>
44
+          
45
+            <Form>
46
+              <Form.Group controlId="searchVideoUrl">
47
+                <Form.Control
48
+                  as="textarea"
49
+                  rows={5}
50
+                  placeholder="请输入抖音分享链接,可以无水印下载"
51
+                  value={searchVideoUrl}
52
+                  onChange={(e) => setSearchVideoUrl(e.target.value)}
53
+                />
54
+              </Form.Group>
55
+              
56
+                <Button 
57
+                className='mt-3'
58
+                  variant="primary" 
59
+                  style={{width:'100%'}}
60
+                  disabled={isLoading} 
61
+                  onClick={searchVideo}
62
+                >
63
+                  {isLoading ? (
64
+                    <>
65
+                      <Spinner
66
+                        as="span"
67
+                        animation="border"
68
+                        size="sm"
69
+                        role="status"
70
+                        aria-hidden="true"
71
+                      />
72
+                      <span className="sr-only">Loading...</span>
73
+                    </>
74
+                  ) : (
75
+                    '点击搜索视频'
76
+                  )}
77
+                </Button>
78
+              
79
+            </Form>
80
+          
81
+        </div>
82
+        {videoUrlList.length > 0 &&
83
+          <div className="list-group-item" >
84
+            <Col>请选择视频:</Col>
85
+            <Col>
86
+              <div className="d-flex flex-wrap">
87
+                {videoUrlList.map((item, index) => (
88
+                  <a 
89
+                    href={item.url} 
90
+                    target="_blank" 
91
+                    rel="noopener noreferrer" 
92
+                    key={index}
93
+                    className="m-2"
94
+                  >
95
+                    <Button variant="info">下载{getBtnTitle(item.quality)}</Button>
96
+                  </a>
97
+                ))}
98
+              </div>
99
+            </Col>
100
+          </div>
101
+        }
102
+      </div>
103
+    </div>
104
+  );
105
+});
106
+
107
+export default VideoDown;

+ 90 - 0
src/css/index.css

@@ -0,0 +1,90 @@
1
+.app {
2
+  min-height: 100vh;
3
+  
4
+  display: flex;
5
+  flex-direction: column;
6
+}
7
+
8
+
9
+.navigation-tab {
10
+  flex: 1;
11
+  justify-content: end;
12
+  
13
+  margin-right: 30px;
14
+}
15
+.content{
16
+  margin-top: 55px;
17
+  flex-grow: 1;
18
+ 
19
+  /* height: calc(100vh - 55px);  */
20
+  background: #f8f8f8;
21
+  /* background-color: white; */
22
+  display: flex;
23
+  flex-direction: column;
24
+}
25
+.content-notflow{
26
+  overflow-y: hidden;
27
+}
28
+.active-link {
29
+  /* text-decoration: underline; */
30
+  color: #fff !important;
31
+  position: relative;
32
+}
33
+.tab-info{
34
+  padding: 5px 10px;
35
+  color: rgba(255,255,255,.5);
36
+  text-decoration: none; /* 去掉下划线 */
37
+}
38
+.navigation{
39
+  position: fixed;
40
+  z-index: 11;
41
+  width: 100%;
42
+  padding-right: 10px;
43
+  background-color: #343a40!important;
44
+}
45
+.navbar-toggler:focus{
46
+  box-shadow:none !important;
47
+}
48
+.custom-toggler{
49
+  border-color: rgba(255, 255, 255, 0.5);
50
+}
51
+.custom-toggler .navbar-toggler-icon {
52
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E");
53
+}
54
+
55
+/* 添加到您的 CSS 文件中 */
56
+.mobile-navigation-tab {
57
+  display: flex;                  /* 水平布局 */
58
+  justify-content: space-around;  /* 每个元素之间的间隔均匀分布 */
59
+  align-items: center;            /* 垂直居中 */
60
+  position: fixed;                /* 固定位置 */
61
+  bottom: 0;                      /* 底部对齐 */
62
+  width: 100%;                    /* 充满整个屏幕宽度 */
63
+  background-color: #ffffff;         /* 背景色 */
64
+  box-shadow: 0 -2px 10px rgba(0,0,0,0.1); /* 阴影效果 */
65
+  z-index: 999;
66
+}
67
+
68
+.mobile-tab-info {
69
+  display: flex;                  /* 水平布局 */
70
+  flex-direction: column;         /* 垂直堆叠 */
71
+  align-items: center;            /* 居中对齐 */
72
+  text-decoration: none;          /* 去掉下划线 */
73
+  color: inherit;                 /* 继承颜色 */
74
+  padding: 10px;                  /* 内边距 */
75
+  color: #333; 
76
+}
77
+
78
+.mobile-tab-info span {
79
+  margin-top: 4px;                /* 图标和文字之间的间隔 */
80
+}
81
+
82
+.mobile-active-link {
83
+  color: #007bff; /* 选中状态下的颜色,这里使用的是亮蓝色 */
84
+}
85
+
86
+.mobile-content{
87
+  
88
+  background: #f8f8f8;
89
+  margin-bottom: 60px;
90
+}

+ 260 - 0
src/db/bookInfoService.js

@@ -0,0 +1,260 @@
1
+const { db } = require('./config');
2
+
3
+class BookInfoService {
4
+  /**
5
+   * 创建项目详细信息
6
+   * @param {Object} bookInfoData - 项目详细信息数据
7
+   * @returns {Promise<number>} - 返回新创建的详细信息ID
8
+   */
9
+  async createBookInfo(bookInfoData) {
10
+    try {
11
+      const now = new Date().toISOString();
12
+      
13
+      // 如果subtitle_segments是对象,转换为JSON字符串
14
+      let subtitleSegments = bookInfoData.subtitle_segments;
15
+      if (subtitleSegments && typeof subtitleSegments === 'object') {
16
+        subtitleSegments = JSON.stringify(subtitleSegments);
17
+      }
18
+      
19
+      // 如果merged_from是数组,转换为JSON字符串
20
+      let mergedFrom = bookInfoData.merged_from;
21
+      if (mergedFrom && Array.isArray(mergedFrom)) {
22
+        mergedFrom = JSON.stringify(mergedFrom);
23
+      }
24
+      
25
+      const bookInfo = {
26
+        book_id: bookInfoData.book_id,
27
+        subtitle_content: bookInfoData.subtitle_content || null,
28
+        subtitle_segments: subtitleSegments || null,
29
+        audio_path: bookInfoData.audio_path || null,
30
+        image_path: bookInfoData.image_path || null,
31
+        description: bookInfoData.description || null,
32
+        video_path: bookInfoData.video_path || null,
33
+        is_merged: bookInfoData.is_merged || false,
34
+        merged_from: mergedFrom || null,
35
+        created_at: now,
36
+        updated_at: now
37
+      };
38
+      
39
+      // 插入数据并返回ID
40
+      const [id] = await db('book_info').insert(bookInfo);
41
+      return id;
42
+    } catch (error) {
43
+      console.error('创建项目详细信息失败:', error);
44
+      throw error;
45
+    }
46
+  }
47
+
48
+  /**
49
+   * 根据项目ID获取详细信息
50
+   * @param {number} bookId - 项目ID
51
+   * @returns {Promise<Object>} - 返回项目详细信息
52
+   */
53
+  async getBookInfoByBookId(bookId) {
54
+    try {
55
+      const segments = await db('book_info').where({ book_id: bookId }).orderBy('id', 'asc');
56
+      
57
+      // 处理每个分镜的数据
58
+      return segments.map(segment => {
59
+        // 如果subtitle_segments是JSON字符串,解析为对象
60
+        if (segment.subtitle_segments && typeof segment.subtitle_segments === 'string') {
61
+          try {
62
+            segment.subtitle_segments = JSON.parse(segment.subtitle_segments);
63
+          } catch (e) {
64
+            console.error('解析subtitle_segments失败:', e);
65
+          }
66
+        }
67
+        
68
+        // 如果merged_from是JSON字符串,解析为数组
69
+        if (segment.merged_from && typeof segment.merged_from === 'string') {
70
+          try {
71
+            segment.merged_from = JSON.parse(segment.merged_from);
72
+          } catch (e) {
73
+            console.error('解析merged_from失败:', e);
74
+          }
75
+        }
76
+        
77
+        return segment;
78
+      });
79
+    } catch (error) {
80
+      console.error(`获取项目详细信息(BookID: ${bookId})失败:`, error);
81
+      throw error;
82
+    }
83
+  }
84
+
85
+  /**
86
+   * 更新项目详细信息
87
+   * @param {number} id - 分镜ID
88
+   * @param {Object} bookInfoData - 更新的项目详细信息数据
89
+   * @returns {Promise<boolean>} - 返回是否更新成功
90
+   */
91
+  async updateBookInfo(id, bookInfoData) {
92
+    try {
93
+      console.log(`更新分镜信息: id=${id}, data=`, bookInfoData);
94
+      
95
+      // 如果subtitle_segments是对象,转换为JSON字符串
96
+      let updateData = { ...bookInfoData };
97
+      
98
+      // 确保包含id字段
99
+      updateData.id = id;
100
+      
101
+      if (updateData.subtitle_segments && typeof updateData.subtitle_segments === 'object') {
102
+        updateData.subtitle_segments = JSON.stringify(updateData.subtitle_segments);
103
+      }
104
+      
105
+      // 如果merged_from是数组,转换为JSON字符串
106
+      if (updateData.merged_from && Array.isArray(updateData.merged_from)) {
107
+        updateData.merged_from = JSON.stringify(updateData.merged_from);
108
+      }
109
+      
110
+      updateData.updated_at = new Date().toISOString();
111
+      
112
+      await db('book_info').where({ id }).update(updateData);
113
+      console.log(`分镜更新成功: id=${id}`);
114
+      return true;
115
+    } catch (error) {
116
+      console.error(`更新项目详细信息(ID: ${id})失败:`, error);
117
+      throw error;
118
+    }
119
+  }
120
+
121
+  /**
122
+   * 删除项目详细信息
123
+   * @param {number} id - 分镜ID
124
+   * @returns {Promise<boolean>} - 返回是否删除成功
125
+   */
126
+  async deleteBookInfo(id) {
127
+    try {
128
+      await db('book_info').where({ id }).delete();
129
+      return true;
130
+    } catch (error) {
131
+      console.error(`删除项目详细信息(ID: ${id})失败:`, error);
132
+      throw error;
133
+    }
134
+  }
135
+  
136
+  /**
137
+   * 合并分镜
138
+   * @param {number} bookId - 项目ID
139
+   * @param {number[]} segmentIds - 要合并的分镜ID数组
140
+   * @returns {Promise<number>} - 返回新创建的合并分镜ID
141
+   */
142
+  async mergeSegments(bookId, segmentIds) {
143
+    try {
144
+      // 查询要合并的分镜
145
+      const segments = await db('book_info')
146
+        .whereIn('id', segmentIds)
147
+        .where('book_id', bookId)
148
+        .orderBy('id', 'asc');
149
+      
150
+      if (segments.length < 2) {
151
+        throw new Error('至少需要两个分镜才能合并');
152
+      }
153
+      
154
+      // 提取分镜的文本内容和时间信息
155
+      const firstSegment = segments[0];
156
+      const lastSegment = segments[segments.length - 1];
157
+      
158
+      // 合并文本内容
159
+      const mergedText = segments.map(segment => {
160
+        // 尝试解析subtitle_segments
161
+        let subtitleData = segment.subtitle_segments;
162
+        if (typeof subtitleData === 'string') {
163
+          try {
164
+            subtitleData = JSON.parse(subtitleData);
165
+          } catch (e) {
166
+            console.error('解析subtitle_segments失败:', e);
167
+            subtitleData = null;
168
+          }
169
+        }
170
+        
171
+        return segment.text || (subtitleData && subtitleData.text ? subtitleData.text : '');
172
+      }).join('\n\n');
173
+      
174
+      // 创建合并后的分镜
175
+      const mergedSegment = {
176
+        book_id: bookId,
177
+        text: mergedText,
178
+        start_time: firstSegment.start_time,
179
+        end_time: lastSegment.end_time,
180
+        duration: this._calculateDuration(firstSegment.start_time, lastSegment.end_time),
181
+        is_merged: true,
182
+        merged_from: JSON.stringify(segmentIds),
183
+        created_at: new Date().toISOString(),
184
+        updated_at: new Date().toISOString()
185
+      };
186
+      
187
+      // 插入合并后的分镜
188
+      const [id] = await db('book_info').insert(mergedSegment);
189
+      
190
+      return id;
191
+    } catch (error) {
192
+      console.error(`合并分镜失败:`, error);
193
+      throw error;
194
+    }
195
+  }
196
+  
197
+  /**
198
+   * 拆分分镜
199
+   * @param {number} segmentId - 要拆分的分镜ID
200
+   * @param {Object[]} newSegments - 新分镜数据数组
201
+   * @returns {Promise<number[]>} - 返回新创建的分镜ID数组
202
+   */
203
+  async splitSegment(segmentId, newSegments) {
204
+    try {
205
+      // 查询要拆分的分镜
206
+      const segment = await db('book_info').where({ id: segmentId }).first();
207
+      
208
+      if (!segment) {
209
+        throw new Error(`分镜(ID: ${segmentId})不存在`);
210
+      }
211
+      
212
+      // 创建新分镜
213
+      const newSegmentIds = [];
214
+      for (const newSegment of newSegments) {
215
+        const segmentData = {
216
+          book_id: segment.book_id,
217
+          text: newSegment.text,
218
+          start_time: newSegment.start_time,
219
+          end_time: newSegment.end_time,
220
+          duration: this._calculateDuration(newSegment.start_time, newSegment.end_time),
221
+          created_at: new Date().toISOString(),
222
+          updated_at: new Date().toISOString()
223
+        };
224
+        
225
+        const [id] = await db('book_info').insert(segmentData);
226
+        newSegmentIds.push(id);
227
+      }
228
+      
229
+      // 删除原分镜
230
+      await this.deleteBookInfo(segmentId);
231
+      
232
+      return newSegmentIds;
233
+    } catch (error) {
234
+      console.error(`拆分分镜失败:`, error);
235
+      throw error;
236
+    }
237
+  }
238
+  
239
+  /**
240
+   * 计算两个时间点之间的持续时间(秒)
241
+   * @param {string} startTime - 开始时间 (HH:MM:SS,mmm)
242
+   * @param {string} endTime - 结束时间 (HH:MM:SS,mmm)
243
+   * @returns {number} - 持续时间(秒)
244
+   * @private
245
+   */
246
+  _calculateDuration(startTime, endTime) {
247
+    const parseTime = (time) => {
248
+      if (!time) return 0;
249
+      const [hours, minutes, seconds] = time.replace(',', '.').split(':').map(parseFloat);
250
+      return hours * 3600 + minutes * 60 + seconds;
251
+    };
252
+    
253
+    const startSeconds = parseTime(startTime);
254
+    const endSeconds = parseTime(endTime);
255
+    
256
+    return (endSeconds - startSeconds).toFixed(2);
257
+  }
258
+}
259
+
260
+module.exports = new BookInfoService(); 

+ 103 - 0
src/db/bookService.js

@@ -0,0 +1,103 @@
1
+const { db } = require('./config');
2
+
3
+class BookService {
4
+  /**
5
+   * 创建新项目
6
+   * @param {Object} bookData - 项目数据
7
+   * @returns {Promise<number>} - 返回新创建的项目ID
8
+   */
9
+  async createBook(bookData) {
10
+    try {
11
+      const now = new Date().toISOString();
12
+      const book = {
13
+        title: bookData.title,
14
+        video_path: bookData.video_path || null,
15
+        subtitle_path: bookData.subtitle_path || null,
16
+        audio_path: bookData.audio_path || null,
17
+        created_at: now,
18
+        updated_at: now
19
+      };
20
+      
21
+      // 插入数据并返回ID
22
+      const [id] = await db('book').insert(book);
23
+      return id;
24
+    } catch (error) {
25
+      console.error('创建项目失败:', error);
26
+      throw error;
27
+    }
28
+  }
29
+
30
+  /**
31
+   * 获取所有项目
32
+   * @returns {Promise<Array>} - 返回项目列表
33
+   */
34
+  async getAllBooks() {
35
+    try {
36
+      // 按创建时间降序排列
37
+      const books = await db('book').orderBy('created_at', 'desc');
38
+      return books;
39
+    } catch (error) {
40
+      console.error('获取项目列表失败:', error);
41
+      throw error;
42
+    }
43
+  }
44
+
45
+  /**
46
+   * 根据ID获取项目
47
+   * @param {number} id - 项目ID
48
+   * @returns {Promise<Object>} - 返回项目信息
49
+   */
50
+  async getBookById(id) {
51
+    try {
52
+      const book = await db('book').where({ id }).first();
53
+      return book;
54
+    } catch (error) {
55
+      console.error(`获取项目(ID: ${id})失败:`, error);
56
+      throw error;
57
+    }
58
+  }
59
+
60
+  /**
61
+   * 更新项目信息
62
+   * @param {number} id - 项目ID
63
+   * @param {Object} bookData - 更新的项目数据
64
+   * @returns {Promise<boolean>} - 返回是否更新成功
65
+   */
66
+  async updateBook(id, bookData) {
67
+    try {
68
+      const book = await this.getBookById(id);
69
+      if (!book) {
70
+        throw new Error(`项目(ID: ${id})不存在`);
71
+      }
72
+      
73
+      const updatedBook = {
74
+        ...bookData,
75
+        updated_at: new Date().toISOString()
76
+      };
77
+      
78
+      await db('book').where({ id }).update(updatedBook);
79
+      return true;
80
+    } catch (error) {
81
+      console.error(`更新项目(ID: ${id})失败:`, error);
82
+      throw error;
83
+    }
84
+  }
85
+
86
+  /**
87
+   * 删除项目
88
+   * @param {number} id - 项目ID
89
+   * @returns {Promise<boolean>} - 返回是否删除成功
90
+   */
91
+  async deleteBook(id) {
92
+    try {
93
+      // 由于外键约束,删除book会自动删除关联的book_info
94
+      await db('book').where({ id }).delete();
95
+      return true;
96
+    } catch (error) {
97
+      console.error(`删除项目(ID: ${id})失败:`, error);
98
+      throw error;
99
+    }
100
+  }
101
+}
102
+
103
+module.exports = new BookService();

+ 145 - 0
src/db/config.js

@@ -0,0 +1,145 @@
1
+const path = require('path');
2
+const os = require('os');
3
+const fs = require('fs');
4
+const knex = require('knex');
5
+
6
+// 获取数据库文件路径
7
+const getDbPath = () => {
8
+  let basePath;
9
+  if (process.platform === 'darwin') {
10
+    // macOS
11
+    basePath = path.join(os.homedir(), 'Library/Application Support/lip_sync');
12
+  } else if (process.platform === 'win32') {
13
+    // Windows
14
+    basePath = path.join(os.homedir(), 'AppData/Roaming/lip_sync');
15
+  } else {
16
+    // Linux
17
+    basePath = path.join(os.homedir(), '.local/share/lip_sync');
18
+  }
19
+  
20
+  // 确保目录存在
21
+  if (!fs.existsSync(basePath)) {
22
+    fs.mkdirSync(basePath, { recursive: true });
23
+  }
24
+  
25
+  return path.join(basePath, 'lip_sync.db');
26
+};
27
+
28
+// 创建Knex实例
29
+const db = knex({
30
+  client: 'sqlite3',
31
+  connection: {
32
+    filename: getDbPath(),
33
+  },
34
+  useNullAsDefault: true, // SQLite需要此选项
35
+  pool: {
36
+    afterCreate: (conn, cb) => {
37
+      // 启用外键约束
38
+      conn.run('PRAGMA foreign_keys = ON', cb);
39
+    }
40
+  }
41
+});
42
+
43
+// 初始化数据库
44
+const initDB = async () => {
45
+  // 创建book表
46
+  const hasBookTable = await db.schema.hasTable('book');
47
+  if (!hasBookTable) {
48
+    await db.schema.createTable('book', (table) => {
49
+      table.increments('id').primary();
50
+      table.string('title').notNullable();
51
+      table.string('video_path').nullable();
52
+      table.string('subtitle_path').nullable();
53
+      table.string('audio_path').nullable(); // 添加音频文件路径字段
54
+      table.timestamp('created_at').defaultTo(db.fn.now());
55
+      table.timestamp('updated_at').defaultTo(db.fn.now());
56
+    });
57
+    console.log('创建book表成功');
58
+  } else {
59
+    // 检查表是否需要更新字段
60
+    const columns = await db.table('book').columnInfo();
61
+    
62
+    // 添加新字段(如果不存在)
63
+    if (!columns.audio_path) {
64
+      await db.schema.table('book', table => {
65
+        table.string('audio_path').nullable();
66
+      });
67
+      console.log('更新book表结构:添加audio_path字段');
68
+    }
69
+  }
70
+  
71
+  // 创建book_info表
72
+  const hasBookInfoTable = await db.schema.hasTable('book_info');
73
+  if (!hasBookInfoTable) {
74
+    await db.schema.createTable('book_info', (table) => {
75
+      table.increments('id').primary();
76
+      table.integer('book_id').unsigned().notNullable();
77
+      table.text('subtitle_content').nullable();
78
+      table.text('subtitle_segments').nullable();
79
+      table.string('audio_path').nullable(); // 音频文件路径
80
+      table.string('image_path').nullable(); // 图片文件路径
81
+      table.text('description').nullable(); // 描述词
82
+      table.string('video_path').nullable(); // 口播视频路径
83
+      table.boolean('is_merged').defaultTo(false); // 是否已合并
84
+      table.integer('merged_from').nullable(); // 从哪些分镜合并而来,存储分镜ID数组的JSON字符串
85
+      table.timestamp('created_at').defaultTo(db.fn.now());
86
+      table.timestamp('updated_at').defaultTo(db.fn.now());
87
+      
88
+      // 外键约束,删除book时级联删除book_info
89
+      table.foreign('book_id').references('id').inTable('book').onDelete('CASCADE');
90
+      
91
+      // 索引
92
+      table.unique(['book_id']);
93
+    });
94
+    console.log('创建book_info表成功');
95
+  } else {
96
+    // 检查表是否需要更新字段
97
+    const columns = await db.table('book_info').columnInfo();
98
+    
99
+    // 添加新字段(如果不存在)
100
+    const updates = [];
101
+    if (!columns.audio_path) {
102
+      updates.push(db.schema.table('book_info', table => {
103
+        table.string('audio_path').nullable();
104
+      }));
105
+    }
106
+    if (!columns.image_path) {
107
+      updates.push(db.schema.table('book_info', table => {
108
+        table.string('image_path').nullable();
109
+      }));
110
+    }
111
+    if (!columns.description) {
112
+      updates.push(db.schema.table('book_info', table => {
113
+        table.text('description').nullable();
114
+      }));
115
+    }
116
+    if (!columns.video_path) {
117
+      updates.push(db.schema.table('book_info', table => {
118
+        table.string('video_path').nullable();
119
+      }));
120
+    }
121
+    if (!columns.is_merged) {
122
+      updates.push(db.schema.table('book_info', table => {
123
+        table.boolean('is_merged').defaultTo(false);
124
+      }));
125
+    }
126
+    if (!columns.merged_from) {
127
+      updates.push(db.schema.table('book_info', table => {
128
+        table.integer('merged_from').nullable();
129
+      }));
130
+    }
131
+    
132
+    if (updates.length > 0) {
133
+      await Promise.all(updates);
134
+      console.log('更新book_info表成功');
135
+    }
136
+  }
137
+  
138
+  return db;
139
+};
140
+
141
+module.exports = {
142
+  db,
143
+  initDB,
144
+  getDbPath
145
+}; 

+ 219 - 0
src/db/dbService.js

@@ -0,0 +1,219 @@
1
+/**
2
+ * 数据库服务 - 渲染进程
3
+ * 使用ipcRenderer与主进程通信,处理数据库操作
4
+ */
5
+
6
+// 获取ipcRenderer
7
+const getIpcRenderer = () => {
8
+  // 使用preload.js暴露的window.electron对象
9
+  if (window.electron && window.electron.ipcRenderer) {
10
+    return window.electron.ipcRenderer;
11
+  }
12
+  
13
+  // 降级到旧方法(仅用于向后兼容)
14
+  if (window.require) {
15
+    try {
16
+      return window.require('electron').ipcRenderer;
17
+    } catch (error) {
18
+      console.error('无法通过require获取ipcRenderer:', error);
19
+    }
20
+  }
21
+  
22
+  console.error('无法获取ipcRenderer,electron API不可用');
23
+  return null;
24
+};
25
+
26
+// 初始化数据库
27
+const initDatabase = async (forceUpdate = false) => {
28
+  console.log(`尝试初始化数据库,forceUpdate=${forceUpdate}`);
29
+  const ipcRenderer = getIpcRenderer();
30
+  if (!ipcRenderer) {
31
+    console.error('ipcRenderer不可用,无法初始化数据库');
32
+    return false;
33
+  }
34
+
35
+  try {
36
+    console.log('调用ipcRenderer.invoke("db:init")...');
37
+    const result = await ipcRenderer.invoke('db:init', forceUpdate);
38
+    console.log('db:init返回结果:', result);
39
+    // 确保返回布尔值,无论result的数据结构如何
40
+    return result && result.success === true;
41
+  } catch (error) {
42
+    console.error('初始化数据库失败:', error);
43
+    return false;
44
+  }
45
+};
46
+
47
+// 获取数据库路径
48
+const getDbPath = async () => {
49
+  const ipcRenderer = getIpcRenderer();
50
+  if (!ipcRenderer) {
51
+    console.error('ipcRenderer不可用,无法获取数据库路径');
52
+    return null;
53
+  }
54
+
55
+  try {
56
+    return await ipcRenderer.invoke('db:getPath');
57
+  } catch (error) {
58
+    console.error('获取数据库路径失败:', error);
59
+    return null;
60
+  }
61
+};
62
+
63
+// Book服务
64
+const bookService = {
65
+  // 创建新项目
66
+  async createBook(bookData) {
67
+    const ipcRenderer = getIpcRenderer();
68
+    if (!ipcRenderer) {
69
+      console.error('ipcRenderer不可用,无法创建项目');
70
+      throw new Error('ipcRenderer不可用');
71
+    }
72
+
73
+    const result = await ipcRenderer.invoke('book:create', bookData);
74
+    if (!result.success) {
75
+      throw new Error(result.error || '创建项目失败');
76
+    }
77
+    return result.id;
78
+  },
79
+
80
+  // 获取所有项目
81
+  async getAllBooks() {
82
+    const ipcRenderer = getIpcRenderer();
83
+    if (!ipcRenderer) {
84
+      console.error('ipcRenderer不可用,无法获取项目列表');
85
+      throw new Error('ipcRenderer不可用');
86
+    }
87
+
88
+    const result = await ipcRenderer.invoke('book:getAll');
89
+    if (!result.success) {
90
+      throw new Error(result.error || '获取项目列表失败');
91
+    }
92
+    return result.books;
93
+  },
94
+
95
+  // 根据ID获取项目
96
+  async getBookById(id) {
97
+    const ipcRenderer = getIpcRenderer();
98
+    if (!ipcRenderer) {
99
+      console.error('ipcRenderer不可用,无法获取项目');
100
+      throw new Error('ipcRenderer不可用');
101
+    }
102
+
103
+    const result = await ipcRenderer.invoke('book:getById', id);
104
+    if (!result.success) {
105
+      throw new Error(result.error || `获取项目(ID: ${id})失败`);
106
+    }
107
+    return result.book;
108
+  },
109
+
110
+  // 更新项目信息
111
+  async updateBook(id, bookData) {
112
+    const ipcRenderer = getIpcRenderer();
113
+    if (!ipcRenderer) {
114
+      console.error('ipcRenderer不可用,无法更新项目');
115
+      throw new Error('ipcRenderer不可用');
116
+    }
117
+
118
+    const result = await ipcRenderer.invoke('book:update', { id, bookData });
119
+    if (!result.success) {
120
+      throw new Error(result.error || `更新项目(ID: ${id})失败`);
121
+    }
122
+    return true;
123
+  },
124
+
125
+  // 删除项目
126
+  async deleteBook(id) {
127
+    const ipcRenderer = getIpcRenderer();
128
+    if (!ipcRenderer) {
129
+      console.error('ipcRenderer不可用,无法删除项目');
130
+      throw new Error('ipcRenderer不可用');
131
+    }
132
+
133
+    const result = await ipcRenderer.invoke('book:delete', id);
134
+    if (!result.success) {
135
+      throw new Error(result.error || `删除项目(ID: ${id})失败`);
136
+    }
137
+    return true;
138
+  }
139
+};
140
+
141
+// BookInfo服务
142
+const bookInfoService = {
143
+  // 创建项目详细信息
144
+  async createBookInfo(bookInfoData) {
145
+    const ipcRenderer = getIpcRenderer();
146
+    if (!ipcRenderer) {
147
+      console.error('ipcRenderer不可用,无法创建项目详细信息');
148
+      throw new Error('ipcRenderer不可用');
149
+    }
150
+
151
+    const result = await ipcRenderer.invoke('bookInfo:create', bookInfoData);
152
+    if (!result.success) {
153
+      throw new Error(result.error || '创建项目详细信息失败');
154
+    }
155
+    return result.id;
156
+  },
157
+
158
+  // 根据项目ID获取详细信息
159
+  async getBookInfoByBookId(bookId) {
160
+    const ipcRenderer = getIpcRenderer();
161
+    if (!ipcRenderer) {
162
+      console.error('ipcRenderer不可用,无法获取项目详细信息');
163
+      throw new Error('ipcRenderer不可用');
164
+    }
165
+
166
+    const result = await ipcRenderer.invoke('bookInfo:getByBookId', bookId);
167
+    if (!result.success) {
168
+      throw new Error(result.error || `获取项目详细信息(BookID: ${bookId})失败`);
169
+    }
170
+    return result.bookInfo || []; // 返回字幕段落数组,如果为空则返回空数组
171
+  },
172
+
173
+  // 更新项目详细信息
174
+  async updateBookInfo(segmentId, bookInfoData) {
175
+    const ipcRenderer = getIpcRenderer();
176
+    if (!ipcRenderer) {
177
+      console.error('ipcRenderer不可用,无法更新项目详细信息');
178
+      throw new Error('ipcRenderer不可用');
179
+    }
180
+
181
+    // 添加ID到bookInfoData对象
182
+    const dataWithId = { 
183
+      ...bookInfoData,
184
+      id: segmentId 
185
+    };
186
+
187
+    const result = await ipcRenderer.invoke('bookInfo:update', { 
188
+      bookId: segmentId, // 保持向后兼容
189
+      bookInfoData: dataWithId 
190
+    });
191
+    
192
+    if (!result.success) {
193
+      throw new Error(result.error || `更新项目详细信息(segmentId: ${segmentId})失败`);
194
+    }
195
+    return true;
196
+  },
197
+
198
+  // 删除项目详细信息
199
+  async deleteBookInfo(bookId) {
200
+    const ipcRenderer = getIpcRenderer();
201
+    if (!ipcRenderer) {
202
+      console.error('ipcRenderer不可用,无法删除项目详细信息');
203
+      throw new Error('ipcRenderer不可用');
204
+    }
205
+
206
+    const result = await ipcRenderer.invoke('bookInfo:delete', bookId);
207
+    if (!result.success) {
208
+      throw new Error(result.error || `删除项目详细信息(BookID: ${bookId})失败`);
209
+    }
210
+    return true;
211
+  }
212
+};
213
+
214
+module.exports = {
215
+  initDb: initDatabase,
216
+  getDbPath,
217
+  bookService,
218
+  bookInfoService
219
+}; 

+ 2 - 0
src/db/index.js

@@ -0,0 +1,2 @@
1
+// 导出数据库服务
2
+module.exports = require('./dbService'); 

+ 17 - 0
src/db/init.js

@@ -0,0 +1,17 @@
1
+const { initDB } = require('./config');
2
+
3
+// 初始化数据库
4
+const initDatabase = async () => {
5
+  try {
6
+    await initDB();
7
+    console.log('数据库初始化成功');
8
+    return true;
9
+  } catch (error) {
10
+    console.error('初始化数据库失败:', error);
11
+    return false;
12
+  }
13
+};
14
+
15
+module.exports = {
16
+  initDatabase
17
+}; 

BIN
src/image/close.png


BIN
src/image/logo.png


+ 70 - 0
src/index.js

@@ -0,0 +1,70 @@
1
+import React from 'react';
2
+import ReactDOM from 'react-dom';
3
+import Routes from './router/index';
4
+import App from './App';
5
+
6
+// 添加electron全局对象检查和降级方案
7
+if (typeof window !== 'undefined' && !window.electron) {
8
+  console.warn('Electron API 不可用,使用模拟实现');
9
+  // 在浏览器环境中提供一个模拟的electron对象
10
+  window.electron = {
11
+    // IPC通信
12
+    ipcRenderer: {
13
+      send: (channel, ...args) => {
14
+        console.warn(`[Electron模拟] 发送消息到通道 ${channel}`, args);
15
+      },
16
+      invoke: (channel, ...args) => {
17
+        console.warn(`[Electron模拟] 调用 ${channel}`, args);
18
+        // 返回不同API的模拟数据
19
+        if (channel === 'save-audio-file') {
20
+          return Promise.resolve({
21
+            success: true,
22
+            filePath: '/模拟路径/audio.mp3'
23
+          });
24
+        } else if (channel === 'process-project-audio') {
25
+          return Promise.resolve({
26
+            success: true,
27
+            totalSegments: args[0]?.segments?.length || 0,
28
+            processedSegments: 0,
29
+            segments: []
30
+          });
31
+        } else if (channel === 'get-audio-duration') {
32
+          return Promise.resolve({
33
+            success: true,
34
+            duration: 60 // 默认返回60秒
35
+          });
36
+        } else if (channel === 'get-app-version') {
37
+          return Promise.resolve('1.0.0');
38
+        } else if (channel === 'open-directory-dialog') {
39
+          return Promise.resolve({ canceled: false, filePaths: ['/模拟目录路径'] });
40
+        } else if (channel === 'open-file-path' || channel === 'open-url' || channel === 'get-file-stats') {
41
+          return Promise.resolve(null);
42
+        }
43
+        return Promise.resolve(null);
44
+      },
45
+      on: (channel, func) => {
46
+        console.warn(`[Electron模拟] 监听通道 ${channel}`);
47
+        return () => {}; // 返回清理函数
48
+      },
49
+      once: (channel, func) => {
50
+        console.warn(`[Electron模拟] 一次性监听通道 ${channel}`);
51
+      }
52
+    },
53
+    // 模拟系统相关API
54
+    system: {
55
+      getAppVersion: () => Promise.resolve('1.0.0')
56
+    },
57
+    // 模拟文件操作API
58
+    files: {
59
+      openDirectoryDialog: () => Promise.resolve({ canceled: false, filePaths: ['/模拟目录路径'] }),
60
+      showItemInFolder: () => Promise.resolve(),
61
+      getFileStats: () => Promise.resolve(null)
62
+    },
63
+    // 模拟外部链接API
64
+    shell: {
65
+      openExternal: () => Promise.resolve()
66
+    }
67
+  };
68
+}
69
+
70
+ReactDOM.render(<App />, document.getElementById('root'));

+ 127 - 0
src/main/ipcHandlers.js

@@ -0,0 +1,127 @@
1
+const path = require('path');
2
+const fs = require('fs');
3
+const { dbService } = require('./database/dbService');
4
+const bookInfoService = require('./database/bookInfoService');
5
+const uuid = require('uuid');
6
+const ffmpeg = require('fluent-ffmpeg');
7
+
8
+// 添加音频处理相关的IPC处理程序
9
+const setupAudioProcessingHandlers = (ipcMain) => {
10
+  // 获取音频时长
11
+  ipcMain.handle('get-audio-duration', async (event, { audioPath }) => {
12
+    try {
13
+      const duration = await getAudioDuration(audioPath);
14
+      return { success: true, duration };
15
+    } catch (error) {
16
+      console.error('获取音频时长失败:', error);
17
+      return { success: false, error: error.message };
18
+    }
19
+  });
20
+
21
+  // 处理项目音频
22
+  ipcMain.handle('process-project-audio', async (event, { projectId, audioPath, segments, outputDir }) => {
23
+    try {
24
+      // 确保输出目录存在
25
+      const projectDir = path.join(outputDir, `project_${projectId}`);
26
+      ensureDirectoryExists(projectDir);
27
+      
28
+      // 获取音频总时长
29
+      const audioDuration = await getAudioDuration(audioPath);
30
+      console.log(`音频总时长: ${audioDuration}秒`);
31
+      
32
+      // 按照字幕时间切割音频
33
+      const results = [];
34
+      
35
+      for (const segment of segments) {
36
+        // 解析开始和结束时间
37
+        const startSeconds = timeToSeconds(segment.start_time);
38
+        const endSeconds = timeToSeconds(segment.end_time);
39
+        const segmentDuration = endSeconds - startSeconds;
40
+        
41
+        // 输出文件路径
42
+        const outputFileName = `segment_${segment.id}_${segment.segment_id}.mp3`;
43
+        const outputFilePath = path.join(projectDir, outputFileName);
44
+        
45
+        console.log(`处理片段 ${segment.id}: ${startSeconds}s - ${endSeconds}s (${segmentDuration}s)`);
46
+        
47
+        try {
48
+          // 切割音频
49
+          await cutAudioSegment(audioPath, outputFilePath, startSeconds, segmentDuration);
50
+          
51
+          // 添加到结果
52
+          results.push({
53
+            segmentId: segment.id,
54
+            originalStartTime: segment.start_time,
55
+            originalEndTime: segment.end_time,
56
+            outputPath: outputFilePath,
57
+            relativePath: path.join(`project_${projectId}`, outputFileName)
58
+          });
59
+          
60
+        } catch (error) {
61
+          console.error(`切割片段 ${segment.id} 失败:`, error);
62
+        }
63
+      }
64
+      
65
+      return {
66
+        success: true,
67
+        totalSegments: segments.length,
68
+        processedSegments: results.length,
69
+        segments: results
70
+      };
71
+    } catch (error) {
72
+      console.error('处理项目音频失败:', error);
73
+      return { success: false, error: error.message };
74
+    }
75
+  });
76
+};
77
+
78
+// 确保目录存在
79
+const ensureDirectoryExists = (directory) => {
80
+  if (!fs.existsSync(directory)) {
81
+    fs.mkdirSync(directory, { recursive: true });
82
+    console.log(`创建目录: ${directory}`);
83
+  }
84
+};
85
+
86
+// 获取音频时长(秒)
87
+const getAudioDuration = (audioPath) => {
88
+  return new Promise((resolve, reject) => {
89
+    ffmpeg.ffprobe(audioPath, (err, metadata) => {
90
+      if (err) {
91
+        return reject(err);
92
+      }
93
+      resolve(metadata.format.duration);
94
+    });
95
+  });
96
+};
97
+
98
+// 转换时间格式为秒
99
+const timeToSeconds = (timeString) => {
100
+  // 处理SRT格式: 00:00:12,345
101
+  const normalizedTime = timeString.replace(',', '.');
102
+  const [hours, minutes, seconds] = normalizedTime.split(':').map(parseFloat);
103
+  return hours * 3600 + minutes * 60 + seconds;
104
+};
105
+
106
+// 切割音频片段
107
+const cutAudioSegment = (inputFile, outputFile, startTime, duration) => {
108
+  return new Promise((resolve, reject) => {
109
+    ffmpeg(inputFile)
110
+      .setStartTime(startTime)
111
+      .setDuration(duration)
112
+      .output(outputFile)
113
+      .on('end', () => {
114
+        console.log(`音频片段已保存: ${outputFile}`);
115
+        resolve();
116
+      })
117
+      .on('error', (err) => {
118
+        console.error('音频处理错误:', err);
119
+        reject(err);
120
+      })
121
+      .run();
122
+  });
123
+};
124
+
125
+module.exports = {
126
+  setupAudioProcessingHandlers,
127
+}; 

+ 367 - 0
src/nodeapi/dbHandler.js

@@ -0,0 +1,367 @@
1
+const path = require('path');
2
+const os = require('os');
3
+const fs = require('fs');
4
+const knex = require('knex');
5
+
6
+// 获取数据库文件路径
7
+const getDbPath = () => {
8
+  let basePath;
9
+  if (process.platform === 'darwin') {
10
+    // macOS
11
+    basePath = path.join(os.homedir(), 'Library/Application Support/lip_sync');
12
+  } else if (process.platform === 'win32') {
13
+    // Windows
14
+    basePath = path.join(os.homedir(), 'AppData/Roaming/lip_sync');
15
+  } else {
16
+    // Linux
17
+    basePath = path.join(os.homedir(), '.local/share/lip_sync');
18
+  }
19
+  
20
+  // 确保目录存在
21
+  if (!fs.existsSync(basePath)) {
22
+    fs.mkdirSync(basePath, { recursive: true });
23
+  }
24
+  
25
+  return path.join(basePath, 'lip_sync.db');
26
+};
27
+
28
+// 创建Knex实例
29
+const db = knex({
30
+  client: 'sqlite3',
31
+  connection: {
32
+    filename: getDbPath(),
33
+  },
34
+  useNullAsDefault: true, // SQLite需要此选项
35
+  pool: {
36
+    afterCreate: (conn, cb) => {
37
+      // 启用外键约束
38
+      conn.run('PRAGMA foreign_keys = ON', cb);
39
+    }
40
+  }
41
+});
42
+
43
+// 更新数据库结构,检查并添加新字段
44
+const updateDbStructure = async (db) => {
45
+  // 检查book表是否有style字段
46
+  const hasStyleColumn = await db.schema.hasColumn('book', 'style');
47
+  if (!hasStyleColumn) {
48
+    console.log('添加style字段到book表');
49
+    await db.schema.table('book', table => {
50
+      table.string('style').nullable();
51
+    });
52
+  }
53
+
54
+  // 检查book_info表是否有image_path字段
55
+  const hasImagePathColumn = await db.schema.hasColumn('book_info', 'image_path');
56
+  if (!hasImagePathColumn) {
57
+    console.log('添加image_path字段到book_info表');
58
+    await db.schema.table('book_info', table => {
59
+      table.string('image_path').nullable();
60
+    });
61
+  }
62
+
63
+  // 检查book_info表是否有description字段
64
+  const hasDescriptionColumn = await db.schema.hasColumn('book_info', 'description');
65
+  if (!hasDescriptionColumn) {
66
+    console.log('添加description字段到book_info表');
67
+    await db.schema.table('book_info', table => {
68
+      table.text('description').nullable();
69
+    });
70
+  }
71
+
72
+  // 检查book_info表是否有draw_status字段
73
+  const hasDrawStatusColumn = await db.schema.hasColumn('book_info', 'draw_status');
74
+  if (!hasDrawStatusColumn) {
75
+    console.log('添加draw_status字段到book_info表');
76
+    await db.schema.table('book_info', table => {
77
+      table.integer('draw_status').defaultTo(2); // 默认为2(完成),对于已有的项目不需要重新绘制
78
+    });
79
+  }
80
+};
81
+
82
+// 初始化数据库
83
+const initDatabase = async (forceUpdate = false) => {
84
+  console.log(`开始初始化数据库,forceUpdate=${forceUpdate}`);
85
+  try {
86
+    // 获取数据库路径
87
+    const dbPath = await getDbPath();
88
+    
89
+    // 确保数据库目录存在
90
+    const dbDir = path.dirname(dbPath);
91
+    if (!fs.existsSync(dbDir)) {
92
+      fs.mkdirSync(dbDir, { recursive: true });
93
+    }
94
+    
95
+    console.log(`初始化数据库,路径: ${dbPath}`);
96
+    
97
+    // 创建数据库连接
98
+    const db = knex({
99
+      client: 'sqlite3',
100
+      connection: {
101
+        filename: dbPath,
102
+      },
103
+      useNullAsDefault: true,
104
+    });
105
+    
106
+    // 如果数据库已存在但需要强制更新
107
+    if (forceUpdate) {
108
+      await updateDbStructure(db);
109
+      return true;
110
+    }
111
+    
112
+    // 检查表是否已存在
113
+    const exists = await db.schema.hasTable('book');
114
+    if (!exists) {
115
+      console.log('创建book表...');
116
+      
117
+      // 创建图书表
118
+      await db.schema.createTable('book', function(table) {
119
+        table.increments('id').primary();
120
+        table.string('title').notNullable();
121
+        table.string('video_path').nullable();
122
+        table.string('subtitle_path').nullable();
123
+        table.string('style').nullable();
124
+        table.timestamp('created_at').defaultTo(db.fn.now());
125
+        table.timestamp('updated_at').defaultTo(db.fn.now());
126
+      });
127
+      
128
+      console.log('创建book_info表...');
129
+      
130
+      // 创建图书信息表
131
+      await db.schema.createTable('book_info', function(table) {
132
+        table.increments('id').primary();
133
+        table.integer('book_id').unsigned().references('id').inTable('book').onDelete('CASCADE');
134
+        table.integer('index').notNullable();
135
+        table.text('text').nullable();
136
+        table.string('start_time').nullable();
137
+        table.string('end_time').nullable();
138
+        table.string('audio_path').nullable();
139
+        table.string('image_path').nullable();
140
+        table.string('video_path').nullable();
141
+        table.text('description').nullable();
142
+        table.integer('draw_status').defaultTo(2); // 添加绘图状态字段,默认为已完成
143
+        table.boolean('is_merged').defaultTo(false);
144
+        table.timestamp('created_at').defaultTo(db.fn.now());
145
+        table.timestamp('updated_at').defaultTo(db.fn.now());
146
+      });
147
+    } else {
148
+      // 如果表已存在,检查是否需要更新结构
149
+      await updateDbStructure(db);
150
+    }
151
+    
152
+    console.log('数据库初始化完成');
153
+    return true;
154
+  } catch (error) {
155
+    console.error('初始化数据库失败:', error);
156
+    return false;
157
+  }
158
+};
159
+
160
+// 处理Book相关操作
161
+const handleBookOperations = {
162
+  // 创建新项目
163
+  async createBook(bookData) {
164
+    try {
165
+      const now = new Date().toISOString();
166
+      const book = {
167
+        title: bookData.title,
168
+        video_path: bookData.video_path || null,
169
+        subtitle_path: bookData.subtitle_path || null,
170
+        created_at: now,
171
+        updated_at: now
172
+      };
173
+      
174
+      // 插入数据并返回ID
175
+      const [id] = await db('book').insert(book);
176
+      return { success: true, id };
177
+    } catch (error) {
178
+      console.error('创建项目失败:', error);
179
+      return { success: false, error: error.message };
180
+    }
181
+  },
182
+
183
+  // 获取所有项目
184
+  async getAllBooks() {
185
+    try {
186
+      // 按创建时间降序排列
187
+      const books = await db('book').orderBy('created_at', 'desc');
188
+      return { success: true, books };
189
+    } catch (error) {
190
+      console.error('获取项目列表失败:', error);
191
+      return { success: false, error: error.message };
192
+    }
193
+  },
194
+
195
+  // 根据ID获取项目
196
+  async getBookById(id) {
197
+    try {
198
+      const book = await db('book').where({ id }).first();
199
+      return { success: true, book };
200
+    } catch (error) {
201
+      console.error(`获取项目(ID: ${id})失败:`, error);
202
+      return { success: false, error: error.message };
203
+    }
204
+  },
205
+
206
+  // 更新项目信息
207
+  async updateBook(id, bookData) {
208
+    try {
209
+      const book = await db('book').where({ id }).first();
210
+      if (!book) {
211
+        return { success: false, error: `项目(ID: ${id})不存在` };
212
+      }
213
+      
214
+      const updatedBook = {
215
+        ...bookData,
216
+        updated_at: new Date().toISOString()
217
+      };
218
+      
219
+      await db('book').where({ id }).update(updatedBook);
220
+      return { success: true };
221
+    } catch (error) {
222
+      console.error(`更新项目(ID: ${id})失败:`, error);
223
+      return { success: false, error: error.message };
224
+    }
225
+  },
226
+
227
+  // 删除项目
228
+  async deleteBook(id) {
229
+    try {
230
+      // 由于外键约束,删除book会自动删除关联的book_info
231
+      await db('book').where({ id }).delete();
232
+      return { success: true };
233
+    } catch (error) {
234
+      console.error(`删除项目(ID: ${id})失败:`, error);
235
+      return { success: false, error: error.message };
236
+    }
237
+  }
238
+};
239
+
240
+// 处理BookInfo相关操作
241
+const handleBookInfoOperations = {
242
+  // 创建项目详细信息
243
+  async createBookInfo(bookInfoData) {
244
+    try {
245
+      const now = new Date().toISOString();
246
+      
247
+      // 处理merged_from字段,如果是数组则转换为JSON字符串
248
+      let mergedFrom = bookInfoData.merged_from;
249
+      if (mergedFrom && Array.isArray(mergedFrom)) {
250
+        mergedFrom = JSON.stringify(mergedFrom);
251
+      }
252
+      
253
+      const bookInfo = {
254
+        book_id: bookInfoData.book_id,
255
+        segment_id: bookInfoData.segment_id || null,
256
+        start_time: bookInfoData.start_time || null,
257
+        end_time: bookInfoData.end_time || null,
258
+        duration: bookInfoData.duration || null,
259
+        text: bookInfoData.text || null,
260
+        audio_path: bookInfoData.audio_path || null,
261
+        image_path: bookInfoData.image_path || null,
262
+        description: bookInfoData.description || null,
263
+        video_path: bookInfoData.video_path || null,
264
+        is_merged: bookInfoData.is_merged || false,
265
+        merged_from: mergedFrom || null,
266
+        created_at: now,
267
+        updated_at: now
268
+      };
269
+      
270
+      // 插入数据并返回ID
271
+      const [id] = await db('book_info').insert(bookInfo);
272
+      return { success: true, id };
273
+    } catch (error) {
274
+      console.error('创建项目详细信息失败:', error);
275
+      return { success: false, error: error.message };
276
+    }
277
+  },
278
+
279
+  // 根据项目ID获取详细信息
280
+  async getBookInfoByBookId(bookId) {
281
+    try {
282
+      // 获取该项目的所有字幕段落
283
+      const segments = await db('book_info')
284
+        .where({ book_id: bookId })
285
+        .orderBy('segment_id', 'asc');
286
+      
287
+      return { success: true, bookInfo: segments };
288
+    } catch (error) {
289
+      console.error(`获取项目详细信息(BookID: ${bookId})失败:`, error);
290
+      return { success: false, error: error.message };
291
+    }
292
+  },
293
+
294
+  // 更新项目详细信息
295
+  async updateBookInfo(bookId, bookInfoData) {
296
+    try {
297
+      // 检查是否存在对应的book_info记录
298
+      // 当传入的bookId是分镜ID时,直接使用id字段查询
299
+      let exists;
300
+      if (bookInfoData.id) {
301
+        exists = await db('book_info').where({ id: bookInfoData.id }).first();
302
+      } else {
303
+        // 兼容旧代码,当传入的bookId是项目ID时,使用book_id查询
304
+        exists = await db('book_info').where({ book_id: bookId }).first();
305
+      }
306
+      
307
+      if (!exists) {
308
+        return { success: false, error: `项目详细信息不存在,bookId: ${bookId}, id: ${bookInfoData.id || '未指定'}` };
309
+      }
310
+      
311
+      // 处理merged_from字段,如果是数组则转换为JSON字符串
312
+      let updateData = { ...bookInfoData };
313
+      if (updateData.merged_from && Array.isArray(updateData.merged_from)) {
314
+        updateData.merged_from = JSON.stringify(updateData.merged_from);
315
+      }
316
+      
317
+      // 移除id字段,避免尝试更新主键
318
+      if (updateData.id) {
319
+        const { id, ...dataToUpdate } = updateData;
320
+        updateData = dataToUpdate;
321
+      }
322
+      
323
+      updateData.updated_at = new Date().toISOString();
324
+      
325
+      // 使用正确的ID进行更新
326
+      if (bookInfoData.id) {
327
+        // 如果有指定id,则使用id更新特定分镜
328
+        await db('book_info').where({ id: bookInfoData.id }).update(updateData);
329
+      } else {
330
+        // 兼容旧代码,使用book_id更新所有与该项目相关的分镜
331
+        await db('book_info').where({ book_id: bookId }).update(updateData);
332
+      }
333
+      return { success: true };
334
+    } catch (error) {
335
+      console.error(`更新项目详细信息失败:`, error);
336
+      return { success: false, error: error.message };
337
+    }
338
+  },
339
+
340
+  // 删除项目详细信息
341
+  async deleteBookInfo(bookId) {
342
+    try {
343
+      // 检查输入参数是否为项目ID还是分镜ID
344
+      const bookRecord = await db('book').where({ id: bookId }).first();
345
+      
346
+      if (bookRecord) {
347
+        // 如果是项目ID,删除项目下所有分镜
348
+        await db('book_info').where({ book_id: bookId }).delete();
349
+      } else {
350
+        // 如果是分镜ID,只删除指定分镜
351
+        await db('book_info').where({ id: bookId }).delete();
352
+      }
353
+      
354
+      return { success: true };
355
+    } catch (error) {
356
+      console.error(`删除项目详细信息失败:`, error);
357
+      return { success: false, error: error.message };
358
+    }
359
+  }
360
+};
361
+
362
+module.exports = {
363
+  getDbPath,
364
+  initDatabase,
365
+  handleBookOperations,
366
+  handleBookInfoOperations
367
+}; 

+ 47 - 0
src/nodeapi/drafts/add_audio.js

@@ -0,0 +1,47 @@
1
+//创建音频内容
2
+const { v4: uuidv4 } = require('uuid');
3
+const path = require('path');
4
+
5
+//增加一个文字轨道 ,返回内容和轨道ID
6
+// type 值  text  文字
7
+// video 视频
8
+// effect 特效
9
+// audio 音频
10
+// 返回新的草稿内容和轨道ID
11
+async function add_audio(draft_content,audio_path,duration){
12
+    let audio = {
13
+        "app_id": 0,
14
+        "category_id": "",
15
+        "category_name": "local",
16
+        "check_flag": 1,
17
+        "duration": duration,
18
+        "effect_id": "",
19
+        "formula_id": "",
20
+        "id": uuidv4(),
21
+        "intensifies_path": "",
22
+        "local_material_id": uuidv4(),
23
+        "music_id": uuidv4(),
24
+        "name": path.basename(audio_path),
25
+        "path": audio_path,
26
+        "request_id": "",
27
+        "resource_id": "",
28
+        "source_platform": 0,
29
+        "team_id": "",
30
+        "text_id": "",
31
+        "tone_category_id": "",
32
+        "tone_category_name": "",
33
+        "tone_effect_id": "",
34
+        "tone_effect_name": "",
35
+        "tone_speaker": "",
36
+        "tone_type": "",
37
+        "type": "extract_music",
38
+        "video_id": "",
39
+        "wave_points": []
40
+      };
41
+    
42
+    draft_content.materials.audios.push(audio);
43
+    return audio
44
+}
45
+
46
+
47
+module.exports = { add_audio };

+ 293 - 0
src/nodeapi/drafts/add_keyframes_v2.js

@@ -0,0 +1,293 @@
1
+//创建文字动画
2
+const { v4: uuidv4 } = require('uuid');
3
+
4
+//创建一个文字动画返回资源
5
+async function add_keyframes (draft_content, track, imageId, magnification=15,animation=1,   start=0,duration=0) {
6
+
7
+  
8
+  /**
9
+  * 更改xy坐标
10
+  * 
11
+  */
12
+  time_offset = duration;
13
+  let _materialsVideoId = uuidv4()
14
+  let _canvasesVideoId = uuidv4()
15
+  let _soundVideoId = uuidv4()
16
+  let _speedsVideoId = uuidv4()
17
+  let _keyframeRefsId_v1 = uuidv4()
18
+  let _keyframeRefsId_v2 = uuidv4()
19
+  let scale_v1 = {
20
+    "x": 0.0,
21
+    "y": 0.0
22
+  }
23
+  let scale_v2 = {
24
+    "x": 0.0,
25
+    "y": 0.0
26
+  }
27
+  let scale_v3 = {
28
+    "x": Number(magnification) / 100 + 1,
29
+    "y": Number(magnification) / 100 + 1
30
+  }
31
+  let scale_v4 = {
32
+    "x": Number(magnification) / 100 + 1,
33
+    "y": Number(magnification) / 100 + 1
34
+  }
35
+  switch (animation) {
36
+    case 0:
37
+      scale_v1 = {
38
+        "x": 0.0,
39
+        "y": 0.0
40
+      }
41
+      scale_v2 = {
42
+        "x": 0.0,
43
+        "y": 0.0
44
+      }
45
+      break;
46
+    case 1:
47
+      scale_v1 = {
48
+        "x": - Number(magnification) / 100,
49
+        "y": 0.0
50
+      }
51
+      scale_v2 = {
52
+        "x": Number(magnification) / 100,
53
+        "y": 0.0
54
+      }
55
+      break;
56
+    case 2:
57
+      scale_v1 = {
58
+        "x": Number(magnification) / 100,
59
+        "y": 0.0
60
+      }
61
+      scale_v2 = {
62
+        "x": - Number(magnification) / 100,
63
+        "y": 0.0
64
+      }
65
+      break;
66
+    case 3:
67
+      scale_v1 = {
68
+        "x": 0.0,
69
+        "y": - Number(magnification) / 100
70
+      }
71
+      scale_v2 = {
72
+        "x": 0.0,
73
+        "y": Number(magnification) / 100
74
+      }
75
+      break;
76
+    case 4:
77
+      scale_v1 = {
78
+        "x": 0.0,
79
+        "y": Number(magnification) / 100
80
+      }
81
+      scale_v2 = {
82
+        "x": 0.0,
83
+        "y": - Number(magnification) / 100
84
+      }
85
+      break;
86
+    case 5:
87
+      scale_v3 = {
88
+        "x": 1,
89
+        "y": 1
90
+      }
91
+      scale_v4 = {
92
+        "x": Number(magnification) / 100 + 1,
93
+        "y": Number(magnification) / 100 + 1
94
+      }
95
+      break;
96
+    case 6:
97
+      scale_v3 = {
98
+        "x": Number(magnification) / 100 + 1,
99
+        "y": Number(magnification) / 100 + 1
100
+
101
+      }
102
+      scale_v4 = {
103
+        "x": 1,
104
+        "y": 1
105
+      }
106
+      break;
107
+
108
+  }
109
+
110
+  //开始的位置
111
+  let _videoInfo_v1 = {
112
+    "alpha": 1.0,
113
+    "brightness_value": 0.0,
114
+    "chroma_intensity": 0.0,
115
+    "chroma_shadow": 0.0,
116
+    "contrast_value": 0.0,
117
+    "effect_adjust_param_1": 1.0,
118
+    "effect_adjust_param_2": 1.0,
119
+    "effect_adjust_param_3": 1.0,
120
+    "fade_value": 0.0,
121
+    "figure_slim": null,
122
+    "figure_stretch": null,
123
+    "figure_zoom": null,
124
+    "filter_value": 1.0,
125
+    "flags": 7,
126
+    "graph": null,
127
+    "highlight_value": 0.0,
128
+    "id": _keyframeRefsId_v1,
129
+    "last_volume": 1.0,
130
+    "light_sensation_value": 0.0,
131
+    "log_color_wheels_intensity": 1.0,
132
+    "lut_value": 0.0,
133
+    "mask_config": null,
134
+    "particle_value": 0.0,
135
+    "position": scale_v1,
136
+    "primary_color_wheels_intensity": 1.0,
137
+    "rotation": 0.0,
138
+    "saturation_value": 0.0,
139
+    "scale": scale_v3,
140
+    "shadow_value": 0.0,
141
+    "sharpen_value": 0.0,
142
+    "smart_color_adjust_value": 0.0,
143
+    "temperature_value": 0.0,
144
+    "time_offset": 0,
145
+    "tone_value": 0.0,
146
+    "type": "video",
147
+    "vignetting_value": 0.0,
148
+    "volume": 1.0
149
+  }
150
+
151
+  //结束的位置
152
+  let _videoInfo_v2 = {
153
+    "alpha": 1.0,
154
+    "brightness_value": 0.0,
155
+    "chroma_intensity": 0.0,
156
+    "chroma_shadow": 0.0,
157
+    "contrast_value": 0.0,
158
+    "effect_adjust_param_1": 1.0,
159
+    "effect_adjust_param_2": 1.0,
160
+    "effect_adjust_param_3": 1.0,
161
+    "fade_value": 0.0,
162
+    "figure_slim": null,
163
+    "figure_stretch": null,
164
+    "figure_zoom": null,
165
+    "filter_value": 1.0,
166
+    "flags": 7,
167
+    "graph": null,
168
+    "highlight_value": 0.0,
169
+    "id": _keyframeRefsId_v2,
170
+    "last_volume": 1.0,
171
+    "light_sensation_value": 0.0,
172
+    "log_color_wheels_intensity": 1.0,
173
+    "lut_value": 0.0,
174
+    "mask_config": null,
175
+    "particle_value": 0.0,
176
+    "position": scale_v2,
177
+    "primary_color_wheels_intensity": 1.0,
178
+    "rotation": 0.0,
179
+    "saturation_value": 0.0,
180
+    "scale": scale_v4,
181
+    "shadow_value": 0.0,
182
+    "sharpen_value": 0.0,
183
+    "smart_color_adjust_value": 0.0,
184
+    "temperature_value": 0.0,
185
+    "time_offset": time_offset,
186
+    "tone_value": 0.0,
187
+    "type": "video",
188
+    "vignetting_value": 0.0,
189
+    "volume": 1.0
190
+  }
191
+
192
+  let canvasesInfo = {
193
+    "album_image": "",
194
+    "blur": 0.0,
195
+    "color": "",
196
+    "id": _canvasesVideoId,
197
+    "image": "",
198
+    "image_id": "",
199
+    "image_name": "",
200
+    "source_platform": 0,
201
+    "team_id": "",
202
+    "type": "canvas_color"
203
+  }
204
+
205
+  let _sound_channel_mappingsInfo = {
206
+    "audio_channel_mapping": 0,
207
+    "id": _speedsVideoId,
208
+    "is_config_open": false,
209
+    "type": "none"
210
+  }
211
+  let _speeds = {
212
+    "curve_speed": null,
213
+    "id": _soundVideoId,
214
+    "mode": 0,
215
+    "speed": 1.0,
216
+    "type": "speed"
217
+  }
218
+  let _segmentsInfo = {
219
+    "cartoon": false,
220
+    "clip": {
221
+      "alpha": 1.0,
222
+      "flip": {
223
+        "horizontal": false,
224
+        "vertical": false
225
+      },
226
+      "rotation": 0.0,
227
+      "scale": {
228
+        "x": Number(magnification) / 100 + 1,
229
+        "y": Number(magnification) / 100 + 1,
230
+      },
231
+      "transform": {
232
+        "x": 0.0,
233
+        "y": 0.0
234
+      }
235
+    },
236
+    "common_keyframes": [],
237
+    "enable_adjust": true,
238
+    "enable_color_curves": true,
239
+    "enable_color_wheels": true,
240
+    "enable_lut": true,
241
+    "enable_smart_color_adjust": false,
242
+    "extra_material_refs": [
243
+      _soundVideoId,
244
+      _canvasesVideoId,
245
+      _speedsVideoId
246
+    ],
247
+    "group_id": "",
248
+    "hdr_settings": {
249
+      "intensity": 1.0,
250
+      "mode": 1,
251
+      "nits": 1000
252
+    },
253
+    "id": uuidv4(),
254
+    "intensifies_audio": false,
255
+    "is_placeholder": false,
256
+    "is_tone_modify": false,
257
+    "keyframe_refs": [
258
+      _videoInfo_v1.id,
259
+      _videoInfo_v2.id
260
+    ],
261
+    "last_nonzero_volume": 1.0,
262
+    "material_id": imageId,
263
+    "render_index": 0,
264
+    "reverse": false,
265
+    "source_timerange": {
266
+      "duration": duration,
267
+      "start":  0
268
+    },
269
+    "speed": 1.0,
270
+    "target_timerange": {
271
+      "duration": duration,
272
+      "start":  start
273
+    },
274
+    "template_id": "",
275
+    "template_scene": "default",
276
+    "track_attribute": 0,
277
+    "track_render_index": 0,
278
+    "visible": true,
279
+    "volume": 1.0
280
+  }
281
+  draft_content.keyframes.videos.push(_videoInfo_v1)
282
+  draft_content.keyframes.videos.push(_videoInfo_v2)
283
+  draft_content.materials.canvases.push(canvasesInfo)
284
+  draft_content.materials.sound_channel_mappings.push(_sound_channel_mappingsInfo)
285
+  draft_content.materials.speeds.push(_speeds)
286
+  track.segments.push(_segmentsInfo)
287
+
288
+}
289
+
290
+
291
+
292
+
293
+module.exports = { add_keyframes };

+ 125 - 0
src/nodeapi/drafts/add_text.js

@@ -0,0 +1,125 @@
1
+//创建文字内容
2
+const { v4: uuidv4 } = require('uuid');
3
+
4
+//增加一个文字轨道 ,返回内容和轨道ID
5
+// type 值  text  文字
6
+// video 视频
7
+// effect 特效
8
+// audio 音频
9
+// 返回新的草稿内容和轨道ID
10
+async function add_text(draft_content,content){
11
+    let text =  {
12
+        "add_type": 2,
13
+        "alignment": 1,
14
+        "background_alpha": 1.0,
15
+        "background_color": "",
16
+        "background_height": 0.14,
17
+        "background_horizontal_offset": 0.0,
18
+        "background_round_radius": 0.0,
19
+        "background_style": 0,
20
+        "background_vertical_offset": 0.0,
21
+        "background_width": 0.14,
22
+        "base_content": "",
23
+        "bold_width": 0.0,
24
+        "border_alpha": 1.0,
25
+        "border_color": "",
26
+        "border_width": 0.08,
27
+        "caption_template_info": {
28
+            "category_id": "",
29
+            "category_name": "",
30
+            "effect_id": "",
31
+            "is_new": false,
32
+            "path": "",
33
+            "request_id": "",
34
+            "resource_id": "",
35
+            "resource_name": "",
36
+            "source_platform": 0
37
+        },
38
+        "check_flag": 7,
39
+        "combo_info": {
40
+            "text_templates": []
41
+        },
42
+        "content": "<useLetterColor><size=15><color=(1,1,1,1)>[" + content + "]</color></size></useLetterColor>" ,
43
+        "fixed_height": -1.0,
44
+        "fixed_width": -1.0,
45
+        "font_category_id": "",
46
+        "font_category_name": "",
47
+        "font_id": "",
48
+        "font_name": "",
49
+        "font_path": "/Applications/VideoFusion-macOS.app/Contents/Resources/Font/SystemFont/zh-hans.ttf",
50
+        "font_resource_id": "",
51
+        "font_size": 15.0,
52
+        "font_source_platform": 0,
53
+        "font_team_id": "",
54
+        "font_title": "none",
55
+        "font_url": "",
56
+        "fonts": [],
57
+        "force_apply_line_max_width": false,
58
+        "global_alpha": 1.0,
59
+        "group_id": "",
60
+        "has_shadow": false,
61
+        "id": uuidv4(),
62
+        "initial_scale": 1.0,
63
+        "inner_padding": -1.0,
64
+        "is_rich_text": true,
65
+        "italic_degree": 0,
66
+        "ktv_color": "",
67
+        "language": "",
68
+        "layer_weight": 1,
69
+        "letter_spacing": 0.0,
70
+        "line_feed": 1,
71
+        "line_max_width": 0.82,
72
+        "line_spacing": 0.02,
73
+        "multi_language_current": "none",
74
+        "name": "",
75
+        "original_size": [],
76
+        "preset_category": "",
77
+        "preset_category_id": "",
78
+        "preset_has_set_alignment": false,
79
+        "preset_id": "",
80
+        "preset_index": 0,
81
+        "preset_name": "",
82
+        "recognize_task_id": "",
83
+        "recognize_type": 0,
84
+        "relevance_segment": [],
85
+        "shadow_alpha": 0.9,
86
+        "shadow_angle": -45.0,
87
+        "shadow_color": "",
88
+        "shadow_distance": 5.0,
89
+        "shadow_point": {
90
+            "x": 0.6363961030678928,
91
+            "y": -0.6363961030678927
92
+        },
93
+        "shadow_smoothing": 0.45,
94
+        "shape_clip_x": false,
95
+        "shape_clip_y": false,
96
+        "source_from": "",
97
+        "style_name": "",
98
+        "sub_type": 0,
99
+        "subtitle_keywords": null,
100
+        "subtitle_template_original_fontsize": 0.0,
101
+        "text_alpha": 1.0,
102
+        "text_color": "#ffde00",
103
+        "text_curve": null,
104
+        "text_preset_resource_id": "",
105
+        "text_size": 30,
106
+        "text_to_audio_ids": [],
107
+        "tts_auto_update": false,
108
+        "type": "subtitle",
109
+        "typesetting": 0,
110
+        "underline": false,
111
+        "underline_offset": 0.22,
112
+        "underline_width": 0.05,
113
+        "use_effect_default_color": false,
114
+        "words": {
115
+            "end_time": [],
116
+            "start_time": [],
117
+            "text": []
118
+        }
119
+    };
120
+    draft_content.materials.texts.push(text);
121
+    return text
122
+}
123
+
124
+
125
+module.exports = { add_text };

+ 35 - 0
src/nodeapi/drafts/add_text_animations.js

@@ -0,0 +1,35 @@
1
+//创建文字动画
2
+const { v4: uuidv4 } = require('uuid');
3
+const { find_ruchang_animation_by_resource_id } = require('./data/text/ruchang');
4
+const { find_chuchang_animation_by_resource_id } = require('./data/text/chuchang');
5
+const { find_xunhuan_animation_by_resource_id } = require('./data/text/xunhuan');
6
+
7
+//创建一个文字动画返回资源
8
+async function add_text_animations(draft_content,ruchang_resource_id='',chuchang_resource_id="",xuhuan_resource_id=""){
9
+    let text_animations = []
10
+    if(ruchang_resource_id){
11
+        let ruchang_ani =  find_ruchang_animation_by_resource_id(ruchang_resource_id);
12
+        text_animations.push(ruchang_ani)
13
+    }
14
+    if(chuchang_resource_id){
15
+        let chuchang_ani = find_chuchang_animation_by_resource_id(chuchang_resource_id);
16
+        text_animations.push(chuchang_ani)
17
+    }
18
+    if(xuhuan_resource_id){
19
+        let loop_ani = find_xunhuan_animation_by_resource_id(xuhuan_resource_id);
20
+        text_animations.push(loop_ani)
21
+    }
22
+    let animations =  {
23
+        "animations": text_animations,
24
+        "id": uuidv4(),
25
+        "multi_language_current": "none",
26
+        "type": "sticker_animation"
27
+    };
28
+    draft_content.materials.material_animations.push(animations);
29
+    return animations
30
+}
31
+
32
+
33
+
34
+
35
+module.exports = { add_text_animations };

+ 23 - 0
src/nodeapi/drafts/add_tracks.js

@@ -0,0 +1,23 @@
1
+//增加一条轨道
2
+const { v4: uuidv4 } = require('uuid');
3
+
4
+//增加一个文字轨道 ,返回内容和轨道ID
5
+// type 值  text  文字
6
+// video 视频
7
+// effect 特效
8
+// audio 音频
9
+// 返回新的草稿内容和轨道ID
10
+async function add_new_tracks(draft_content,type){
11
+    let track = {
12
+        "attribute": 0,
13
+        "flag": 1,
14
+        "id": uuidv4(),
15
+        "segments": [],
16
+        "type": type
17
+    };
18
+    draft_content.tracks.push(track);
19
+    return track
20
+}
21
+
22
+
23
+module.exports = { add_new_tracks };

+ 90 - 0
src/nodeapi/drafts/add_tracks_segments.js

@@ -0,0 +1,90 @@
1
+//把数据内容增加到轨道上面
2
+const { v4: uuidv4 } = require('uuid');
3
+
4
+//增加一个文字轨道 ,返回内容和轨道ID
5
+// type 值  text  文字
6
+// video 视频
7
+// effect 特效
8
+// audio 音频
9
+// 返回新的草稿内容和轨道ID
10
+async function add_new_segments(track,material_id,start,duration){
11
+    let segments = {
12
+        "caption_info": null,
13
+        "cartoon": false,
14
+        "clip": {
15
+            "alpha": 1.0,
16
+            "flip": {
17
+                "horizontal": false,
18
+                "vertical": false
19
+            },
20
+            "rotation": 0.0,
21
+            "scale": {
22
+                "x": 1.0,
23
+                "y": 1.0
24
+            },
25
+            "transform": {
26
+                "x": 0.0,
27
+                "y": 0.0
28
+            }
29
+        },
30
+        "common_keyframes": [],
31
+        "enable_adjust": true,
32
+        "enable_color_correct_adjust": false,
33
+        "enable_color_curves": true,
34
+        "enable_color_match_adjust": false,
35
+        "enable_color_wheels": true,
36
+        "enable_lut": true,
37
+        "enable_smart_color_adjust": false,
38
+        "extra_material_refs": [
39
+        ],
40
+        "group_id": "",
41
+        "hdr_settings": {
42
+            "intensity": 1.0,
43
+            "mode": 1,
44
+            "nits": 1000
45
+        },
46
+        "id": uuidv4(),
47
+        "intensifies_audio": false,
48
+        "is_placeholder": false,
49
+        "is_tone_modify": false,
50
+        "keyframe_refs": [],
51
+        "last_nonzero_volume": 1.0,
52
+        "material_id": material_id,
53
+        "render_index": 1,
54
+        "responsive_layout": {
55
+            "enable": false,
56
+            "horizontal_pos_layout": 0,
57
+            "size_layout": 0,
58
+            "target_follow": "",
59
+            "vertical_pos_layout": 0
60
+        },
61
+        "reverse": false,
62
+        "source_timerange": {
63
+            "duration": duration,
64
+            "start": 0
65
+        },
66
+        "speed": 1.0,
67
+        "target_timerange": {
68
+            "duration": duration,
69
+            "start": start
70
+        },
71
+        "template_id": "",
72
+        "template_scene": "default",
73
+        "track_attribute": 0,
74
+        "track_render_index": 3,
75
+        "uniform_scale": {
76
+            "on": true,
77
+            "value": 1.0
78
+        },
79
+        "visible": true,
80
+        "volume": 1.0
81
+    };
82
+
83
+
84
+    track.segments.push(segments);
85
+
86
+    return segments
87
+}
88
+
89
+
90
+module.exports = { add_new_segments };

+ 93 - 0
src/nodeapi/drafts/add_video.js

@@ -0,0 +1,93 @@
1
+//给轨道增加视频或者图片
2
+const { v4: uuidv4 } = require('uuid');
3
+const path = require('path');
4
+
5
+// 返回新的视频内容
6
+async function add_video(draft_content,video_path,duration,width,height,is_video=1){
7
+    let video = {
8
+        "aigc_type": "none",
9
+        "audio_fade": null,
10
+        "cartoon_path": "",
11
+        "category_id": "",
12
+        "category_name": "",
13
+        "check_flag": 63487,
14
+        "crop": {
15
+            "lower_left_x": 0.0,
16
+            "lower_left_y": 1.0,
17
+            "lower_right_x": 1.0,
18
+            "lower_right_y": 1.0,
19
+            "upper_left_x": 0.0,
20
+            "upper_left_y": 0.0,
21
+            "upper_right_x": 1.0,
22
+            "upper_right_y": 0.0
23
+        },
24
+        "crop_ratio": "free",
25
+        "crop_scale": 1.0,
26
+        "duration": duration,
27
+        "extra_type_option": 0,
28
+        "formula_id": "",
29
+        "freeze": null,
30
+        "has_audio": false,
31
+        "height": height,
32
+        "id": uuidv4(),
33
+        "intensifies_audio_path": "",
34
+        "intensifies_path": "",
35
+        "is_ai_generate_content": false,
36
+        "is_copyright": false,
37
+        "is_text_edit_overdub": false,
38
+        "is_unified_beauty_mode": false,
39
+        "local_id": "",
40
+        "local_material_id": "",
41
+        "material_id": "",
42
+        "material_name": path.basename(video_path),
43
+        "material_url": "",
44
+        "matting": {
45
+            "flag": 0,
46
+            "has_use_quick_brush": false,
47
+            "has_use_quick_eraser": false,
48
+            "interactiveTime": [],
49
+            "path": "",
50
+            "strokes": []
51
+        },
52
+        "media_path": "",
53
+        "object_locked": null,
54
+        "origin_material_id": "",
55
+        "path": video_path,
56
+        "picture_from": "none",
57
+        "picture_set_category_id": "",
58
+        "picture_set_category_name": "",
59
+        "request_id": "",
60
+        "reverse_intensifies_path": "",
61
+        "reverse_path": "",
62
+        "smart_motion": null,
63
+        "source": 0,
64
+        "source_platform": 0,
65
+        "stable": {
66
+            "matrix_path": "",
67
+            "stable_level": 0,
68
+            "time_range": {
69
+                "duration": duration,
70
+                "start": 0
71
+            }
72
+        },
73
+        "team_id": "",
74
+        "type": is_video? "video": "photo",//video//photo
75
+        "video_algorithm": {
76
+            "algorithms": [],
77
+            "complement_frame_config": null,
78
+            "deflicker": null,
79
+            "gameplay_configs": [],
80
+            "motion_blur_config": null,
81
+            "noise_reduction": null,
82
+            "path": "",
83
+            "quality_enhance": null,
84
+            "time_range": null
85
+        },
86
+        "width": width
87
+    };
88
+    draft_content.materials.videos.push(video);
89
+    return video
90
+}
91
+
92
+
93
+module.exports = { add_video };

+ 36 - 0
src/nodeapi/drafts/add_video_animations.js

@@ -0,0 +1,36 @@
1
+//创建文字动画
2
+const { v4: uuidv4 } = require('uuid');
3
+const { find_ruchang_animation_by_resource_id } = require('./data/video/ins');
4
+const { find_out_animation_by_resource_id } = require('./data/video/out');
5
+const { find_group_animation_by_resource_id } = require('./data/video/group');
6
+
7
+
8
+//创建一个文字动画返回资源
9
+async function add_video_animations(draft_content,in_resource_id='',out_resource_id="",loop_resource_id=""){
10
+    let video_animations = []
11
+    if(in_resource_id){
12
+        let ruchang_ani =  find_ruchang_animation_by_resource_id(in_resource_id);
13
+        video_animations.push(ruchang_ani)
14
+    }
15
+    if(out_resource_id){
16
+        let chuchang_ani = find_out_animation_by_resource_id(out_resource_id);
17
+        video_animations.push(chuchang_ani)
18
+    }
19
+    if(loop_resource_id){
20
+        let loop_ani = find_group_animation_by_resource_id(loop_resource_id);
21
+        video_animations.push(loop_ani)
22
+    }
23
+    let animations =  {
24
+        "animations": video_animations,
25
+        "id": uuidv4(),
26
+        "multi_language_current": "none",
27
+        "type": "sticker_animation"
28
+    };
29
+    draft_content.materials.material_animations.push(animations);
30
+    return animations
31
+}
32
+
33
+
34
+
35
+
36
+module.exports = { add_video_animations };

+ 11 - 0
src/nodeapi/drafts/add_video_effects.js

@@ -0,0 +1,11 @@
1
+//创建特效
2
+const { find_texiao_animation_by_resource_id } = require('./data/texiao/texiao');
3
+
4
+// 返回新的特效
5
+async function add_video_effects(draft_content,resource_id){
6
+    let effect = await find_texiao_animation_by_resource_id(resource_id)
7
+    draft_content.materials.video_effects.push(effect);
8
+    return effect
9
+}
10
+
11
+module.exports = { add_video_effects };

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 2555 - 0
src/nodeapi/drafts/data/texiao/aixin.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 2909 - 0
src/nodeapi/drafts/data/texiao/anhei.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 5906 - 0
src/nodeapi/drafts/data/texiao/biankuang.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 4171 - 0
src/nodeapi/drafts/data/texiao/bling.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1560 - 0
src/nodeapi/drafts/data/texiao/chaoku.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 522 - 0
src/nodeapi/drafts/data/texiao/dianyin.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 6157 - 0
src/nodeapi/drafts/data/texiao/donggan.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1796 - 0
src/nodeapi/drafts/data/texiao/dv.json


+ 712 - 0
src/nodeapi/drafts/data/texiao/fenpin.json

@@ -0,0 +1,712 @@
1
+{
2
+    "data": {
3
+        "UrlPrefix": [
4
+            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/",
5
+            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/"
6
+        ],
7
+        "CategoryEffects": {
8
+            "HasMore": false,
9
+            "Cursor": 9,
10
+            "SortingPosition": 9,
11
+            "Version": "1542138587848,1336096379104,900,0",
12
+            "Effects": [
13
+                {
14
+                    "EffectType": 0,
15
+                    "Source": 0,
16
+                    "IsFavorite": false,
17
+                    "Subtype": 0,
18
+                    "IsBusiness": false,
19
+                    "IsPoi": false,
20
+                    "SyncId": "1570397",
21
+                    "ResourceId": "7065593660921877028",
22
+                    "Channel": 1,
23
+                    "PublishStatus": 1,
24
+                    "Ptime": "1645211030000",
25
+                    "ChallengeId": "0",
26
+                    "HintFileFormat": 0,
27
+                    "IsEst": false,
28
+                    "AppID": 1059,
29
+                    "HasProfileInfo": false,
30
+                    "Name": "动态格",
31
+                    "Hint": "",
32
+                    "SdkVersion": "10.1.0",
33
+                    "AppVersion": "",
34
+                    "FileUrl": {
35
+                        "Uri": "eb35001e4b8d3d9e2c7b797578d1e97c",
36
+                        "UrlList": [
37
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/eb35001e4b8d3d9e2c7b797578d1e97c",
38
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/eb35001e4b8d3d9e2c7b797578d1e97c"
39
+                        ]
40
+                    },
41
+                    "IconUrl": {
42
+                        "Uri": "feeb1874d61b8314e0247cd6e7617078",
43
+                        "UrlList": [
44
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/feeb1874d61b8314e0247cd6e7617078",
45
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/feeb1874d61b8314e0247cd6e7617078"
46
+                        ]
47
+                    },
48
+                    "Id": "eb35001e4b8d3d9e2c7b797578d1e97c",
49
+                    "EffectId": "1570398",
50
+                    "DevicePlatform": "all",
51
+                    "Types": [
52
+                        "AmazingFeature"
53
+                    ],
54
+                    "Tags": [],
55
+                    "TagsUpdatedAt": "1645115525000",
56
+                    "Parent": "",
57
+                    "Children": [],
58
+                    "HintIcon": {
59
+                        "Uri": "",
60
+                        "UrlList": []
61
+                    },
62
+                    "Music": [],
63
+                    "DesignerId": "",
64
+                    "Schema": "",
65
+                    "Description": "",
66
+                    "OriginalEffectId": "",
67
+                    "Requirements": [
68
+                        "blit"
69
+                    ],
70
+                    "Extra": "{\"effect_duration\":3000,\"hover_icon\":\"3c7f547f9cb05b6a3b8818c7083909fc\",\"is_business\":true,\"is_vip\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
71
+                    "Countrys": [],
72
+                    "PoiId": "0",
73
+                    "DesignerEncryptedId": "",
74
+                    "SdkExtra": "{\"setting\":{\"effect_adjust_params\":[{\"effect_key\":\"effects_adjust_size\",\"default\":1,\"max\":1,\"min\":0},{\"effect_key\":\"effects_adjust_speed\",\"default\":0.33,\"max\":1,\"min\":0}]}}",
75
+                    "AdRawData": "",
76
+                    "BindIds": [],
77
+                    "GradeKey": "",
78
+                    "ComposerParams": "",
79
+                    "Panel": "effects2",
80
+                    "ModelNames": "",
81
+                    "HintFile": {
82
+                        "Uri": "",
83
+                        "UrlList": []
84
+                    },
85
+                    "SystemList": [
86
+                        "BehaviorSystem",
87
+                        "CameraSystem",
88
+                        "EventSystem",
89
+                        "MeshRendererSystem",
90
+                        "ScriptSystem",
91
+                        "TransformSystem"
92
+                    ],
93
+                    "OriginalExtra": "",
94
+                    "NameTransKey": "",
95
+                    "HintTextTransKey": ""
96
+                },
97
+                {
98
+                    "EffectType": 0,
99
+                    "Source": 0,
100
+                    "IsFavorite": false,
101
+                    "Subtype": 0,
102
+                    "IsBusiness": false,
103
+                    "IsPoi": false,
104
+                    "SyncId": "1594945",
105
+                    "ResourceId": "7069602912057430558",
106
+                    "Channel": 1,
107
+                    "PublishStatus": 1,
108
+                    "Ptime": "1646161845000",
109
+                    "ChallengeId": "0",
110
+                    "HintFileFormat": 0,
111
+                    "IsEst": false,
112
+                    "AppID": 1059,
113
+                    "HasProfileInfo": false,
114
+                    "Name": "两屏分割",
115
+                    "Hint": "",
116
+                    "SdkVersion": "9.5.0",
117
+                    "AppVersion": "",
118
+                    "FileUrl": {
119
+                        "Uri": "2eba26aa15c0e44d2c258ce63a38d243",
120
+                        "UrlList": [
121
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/2eba26aa15c0e44d2c258ce63a38d243",
122
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/2eba26aa15c0e44d2c258ce63a38d243"
123
+                        ]
124
+                    },
125
+                    "IconUrl": {
126
+                        "Uri": "60e93ba3f20b306291cb9995987c5764",
127
+                        "UrlList": [
128
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/60e93ba3f20b306291cb9995987c5764",
129
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/60e93ba3f20b306291cb9995987c5764"
130
+                        ]
131
+                    },
132
+                    "Id": "2eba26aa15c0e44d2c258ce63a38d243",
133
+                    "EffectId": "1594946",
134
+                    "DevicePlatform": "all",
135
+                    "Types": [
136
+                        "AmazingFeature"
137
+                    ],
138
+                    "Tags": [],
139
+                    "TagsUpdatedAt": "1646049001000",
140
+                    "Parent": "",
141
+                    "Children": [],
142
+                    "HintIcon": {
143
+                        "Uri": "",
144
+                        "UrlList": []
145
+                    },
146
+                    "Music": [],
147
+                    "DesignerId": "",
148
+                    "Schema": "",
149
+                    "Description": "",
150
+                    "OriginalEffectId": "",
151
+                    "Requirements": [
152
+                        "texture_blit"
153
+                    ],
154
+                    "Extra": "{\"effect_duration\":3000,\"hover_icon\":\"dcbbf50ba892cb66b47b238fd284beb2\",\"is_business\":true,\"is_vip\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
155
+                    "Countrys": [],
156
+                    "PoiId": "0",
157
+                    "DesignerEncryptedId": "",
158
+                    "SdkExtra": "{\"setting\":{\"effect_adjust_params\":[{\"effect_key\":\"effects_adjust_speed\",\"default\":0.33,\"max\":1,\"min\":0},{\"effect_key\":\"effects_adjust_filter\",\"default\":0.8,\"max\":1,\"min\":0},{\"effect_key\":\"effects_adjust_range\",\"default\":0.1,\"max\":1,\"min\":0}]}}",
159
+                    "AdRawData": "",
160
+                    "BindIds": [],
161
+                    "GradeKey": "",
162
+                    "ComposerParams": "",
163
+                    "Panel": "effects2",
164
+                    "ModelNames": "",
165
+                    "HintFile": {
166
+                        "Uri": "",
167
+                        "UrlList": []
168
+                    },
169
+                    "SystemList": [
170
+                        "BehaviorSystem",
171
+                        "CameraSystem",
172
+                        "EventSystem",
173
+                        "MeshRendererSystem",
174
+                        "ScriptSystem",
175
+                        "TransformSystem"
176
+                    ],
177
+                    "OriginalExtra": "",
178
+                    "NameTransKey": "",
179
+                    "HintTextTransKey": ""
180
+                },
181
+                {
182
+                    "EffectType": 0,
183
+                    "Source": 0,
184
+                    "IsFavorite": false,
185
+                    "Subtype": 0,
186
+                    "IsBusiness": false,
187
+                    "IsPoi": false,
188
+                    "SyncId": "635024",
189
+                    "ResourceId": "6706773500796867075",
190
+                    "Channel": 1,
191
+                    "PublishStatus": 1,
192
+                    "Ptime": "1586375831000",
193
+                    "ChallengeId": "0",
194
+                    "HintFileFormat": 0,
195
+                    "IsEst": false,
196
+                    "AppID": 1059,
197
+                    "HasProfileInfo": false,
198
+                    "Name": "两屏",
199
+                    "Hint": "",
200
+                    "SdkVersion": "6.6.0",
201
+                    "AppVersion": "",
202
+                    "FileUrl": {
203
+                        "Uri": "69926ac7983e4e234c1b833e8c50896a",
204
+                        "UrlList": [
205
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/69926ac7983e4e234c1b833e8c50896a",
206
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/69926ac7983e4e234c1b833e8c50896a"
207
+                        ]
208
+                    },
209
+                    "IconUrl": {
210
+                        "Uri": "b9c681113f0d40c948f82b03a2597638",
211
+                        "UrlList": [
212
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/b9c681113f0d40c948f82b03a2597638",
213
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/b9c681113f0d40c948f82b03a2597638"
214
+                        ]
215
+                    },
216
+                    "Id": "69926ac7983e4e234c1b833e8c50896a",
217
+                    "EffectId": "635025",
218
+                    "DevicePlatform": "all",
219
+                    "Types": [
220
+                        "AmazingFeature"
221
+                    ],
222
+                    "Tags": [],
223
+                    "TagsUpdatedAt": "1583949995000",
224
+                    "Parent": "",
225
+                    "Children": [],
226
+                    "HintIcon": {
227
+                        "Uri": "",
228
+                        "UrlList": []
229
+                    },
230
+                    "Music": [],
231
+                    "DesignerId": "",
232
+                    "Schema": "",
233
+                    "Description": "",
234
+                    "OriginalEffectId": "",
235
+                    "Requirements": [],
236
+                    "Extra": "{\"hover_icon\":\"a807f4c61e9b12b8abe88fc10bd31370\",\"effect_duration\":3000,\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
237
+                    "Countrys": [],
238
+                    "PoiId": "0",
239
+                    "DesignerEncryptedId": "",
240
+                    "SdkExtra": "",
241
+                    "AdRawData": "",
242
+                    "BindIds": [],
243
+                    "GradeKey": "",
244
+                    "ComposerParams": "",
245
+                    "Panel": "effects2",
246
+                    "ModelNames": "",
247
+                    "HintFile": {
248
+                        "Uri": "",
249
+                        "UrlList": []
250
+                    },
251
+                    "OriginalExtra": "",
252
+                    "NameTransKey": "",
253
+                    "HintTextTransKey": ""
254
+                },
255
+                {
256
+                    "EffectType": 0,
257
+                    "Source": 0,
258
+                    "IsFavorite": false,
259
+                    "Subtype": 0,
260
+                    "IsBusiness": false,
261
+                    "IsPoi": false,
262
+                    "SyncId": "635028",
263
+                    "ResourceId": "6706773500209664515",
264
+                    "Channel": 1,
265
+                    "PublishStatus": 1,
266
+                    "Ptime": "1586375831000",
267
+                    "ChallengeId": "0",
268
+                    "HintFileFormat": 0,
269
+                    "IsEst": false,
270
+                    "AppID": 1059,
271
+                    "HasProfileInfo": false,
272
+                    "Name": "三屏",
273
+                    "Hint": "",
274
+                    "SdkVersion": "6.6.0",
275
+                    "AppVersion": "",
276
+                    "FileUrl": {
277
+                        "Uri": "a753c93aef7a37f2e86870529f2cd06c",
278
+                        "UrlList": [
279
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/a753c93aef7a37f2e86870529f2cd06c",
280
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/a753c93aef7a37f2e86870529f2cd06c"
281
+                        ]
282
+                    },
283
+                    "IconUrl": {
284
+                        "Uri": "393b33047f1a45c964a2afc51ff3d42d",
285
+                        "UrlList": [
286
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/393b33047f1a45c964a2afc51ff3d42d",
287
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/393b33047f1a45c964a2afc51ff3d42d"
288
+                        ]
289
+                    },
290
+                    "Id": "a753c93aef7a37f2e86870529f2cd06c",
291
+                    "EffectId": "635029",
292
+                    "DevicePlatform": "all",
293
+                    "Types": [
294
+                        "AmazingFeature"
295
+                    ],
296
+                    "Tags": [],
297
+                    "TagsUpdatedAt": "1583950034000",
298
+                    "Parent": "",
299
+                    "Children": [],
300
+                    "HintIcon": {
301
+                        "Uri": "",
302
+                        "UrlList": []
303
+                    },
304
+                    "Music": [],
305
+                    "DesignerId": "",
306
+                    "Schema": "",
307
+                    "Description": "",
308
+                    "OriginalEffectId": "",
309
+                    "Requirements": [],
310
+                    "Extra": "{\"hover_icon\":\"e36b488ef5507c8b4518a7d30f4ec066\",\"effect_duration\":3000,\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
311
+                    "Countrys": [],
312
+                    "PoiId": "0",
313
+                    "DesignerEncryptedId": "",
314
+                    "SdkExtra": "",
315
+                    "AdRawData": "",
316
+                    "BindIds": [],
317
+                    "GradeKey": "",
318
+                    "ComposerParams": "",
319
+                    "Panel": "effects2",
320
+                    "ModelNames": "",
321
+                    "HintFile": {
322
+                        "Uri": "",
323
+                        "UrlList": []
324
+                    },
325
+                    "OriginalExtra": "",
326
+                    "NameTransKey": "",
327
+                    "HintTextTransKey": ""
328
+                },
329
+                {
330
+                    "EffectType": 0,
331
+                    "Source": 0,
332
+                    "IsFavorite": false,
333
+                    "Subtype": 0,
334
+                    "IsBusiness": false,
335
+                    "IsPoi": false,
336
+                    "SyncId": "635026",
337
+                    "ResourceId": "6706773500490682888",
338
+                    "Channel": 1,
339
+                    "PublishStatus": 1,
340
+                    "Ptime": "1586375831000",
341
+                    "ChallengeId": "0",
342
+                    "HintFileFormat": 0,
343
+                    "IsEst": false,
344
+                    "AppID": 1059,
345
+                    "HasProfileInfo": false,
346
+                    "Name": "四屏",
347
+                    "Hint": "",
348
+                    "SdkVersion": "6.6.0",
349
+                    "AppVersion": "",
350
+                    "FileUrl": {
351
+                        "Uri": "f0074ead79e0a8dd9a10518667beb0f1",
352
+                        "UrlList": [
353
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/f0074ead79e0a8dd9a10518667beb0f1",
354
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/f0074ead79e0a8dd9a10518667beb0f1"
355
+                        ]
356
+                    },
357
+                    "IconUrl": {
358
+                        "Uri": "1d4c74a464c8b1d76e3b04ba39a58fdc",
359
+                        "UrlList": [
360
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/1d4c74a464c8b1d76e3b04ba39a58fdc",
361
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/1d4c74a464c8b1d76e3b04ba39a58fdc"
362
+                        ]
363
+                    },
364
+                    "Id": "f0074ead79e0a8dd9a10518667beb0f1",
365
+                    "EffectId": "635027",
366
+                    "DevicePlatform": "all",
367
+                    "Types": [
368
+                        "AmazingFeature"
369
+                    ],
370
+                    "Tags": [],
371
+                    "TagsUpdatedAt": "1583950016000",
372
+                    "Parent": "",
373
+                    "Children": [],
374
+                    "HintIcon": {
375
+                        "Uri": "",
376
+                        "UrlList": []
377
+                    },
378
+                    "Music": [],
379
+                    "DesignerId": "",
380
+                    "Schema": "",
381
+                    "Description": "",
382
+                    "OriginalEffectId": "",
383
+                    "Requirements": [],
384
+                    "Extra": "{\"hover_icon\":\"7f66ab3b3fbdda5f9137f16c7735883c\",\"effect_duration\":3000,\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
385
+                    "Countrys": [],
386
+                    "PoiId": "0",
387
+                    "DesignerEncryptedId": "",
388
+                    "SdkExtra": "",
389
+                    "AdRawData": "",
390
+                    "BindIds": [],
391
+                    "GradeKey": "",
392
+                    "ComposerParams": "",
393
+                    "Panel": "effects2",
394
+                    "ModelNames": "",
395
+                    "HintFile": {
396
+                        "Uri": "",
397
+                        "UrlList": []
398
+                    },
399
+                    "OriginalExtra": "",
400
+                    "NameTransKey": "",
401
+                    "HintTextTransKey": ""
402
+                },
403
+                {
404
+                    "EffectType": 0,
405
+                    "Source": 0,
406
+                    "IsFavorite": false,
407
+                    "Subtype": 0,
408
+                    "IsBusiness": false,
409
+                    "IsPoi": false,
410
+                    "SyncId": "635016",
411
+                    "ResourceId": "6719657002571665934",
412
+                    "Channel": 1,
413
+                    "PublishStatus": 1,
414
+                    "Ptime": "1586375831000",
415
+                    "ChallengeId": "0",
416
+                    "HintFileFormat": 0,
417
+                    "IsEst": false,
418
+                    "AppID": 1059,
419
+                    "HasProfileInfo": false,
420
+                    "Name": "黑白三格",
421
+                    "Hint": "",
422
+                    "SdkVersion": "6.6.0",
423
+                    "AppVersion": "",
424
+                    "FileUrl": {
425
+                        "Uri": "e4022fb9e226f41f58c33d255c647eed",
426
+                        "UrlList": [
427
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/e4022fb9e226f41f58c33d255c647eed",
428
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/e4022fb9e226f41f58c33d255c647eed"
429
+                        ]
430
+                    },
431
+                    "IconUrl": {
432
+                        "Uri": "8128de096fb4d38130098395a4a8a268",
433
+                        "UrlList": [
434
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/8128de096fb4d38130098395a4a8a268",
435
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/8128de096fb4d38130098395a4a8a268"
436
+                        ]
437
+                    },
438
+                    "Id": "e4022fb9e226f41f58c33d255c647eed",
439
+                    "EffectId": "635017",
440
+                    "DevicePlatform": "all",
441
+                    "Types": [
442
+                        "AmazingFeature"
443
+                    ],
444
+                    "Tags": [],
445
+                    "TagsUpdatedAt": "1583949972000",
446
+                    "Parent": "",
447
+                    "Children": [],
448
+                    "HintIcon": {
449
+                        "Uri": "",
450
+                        "UrlList": []
451
+                    },
452
+                    "Music": [],
453
+                    "DesignerId": "",
454
+                    "Schema": "",
455
+                    "Description": "",
456
+                    "OriginalEffectId": "",
457
+                    "Requirements": [],
458
+                    "Extra": "{\"hover_icon\":\"30e9d1e850ac1a77361b43921dee94fc\",\"effect_duration\":3000,\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
459
+                    "Countrys": [],
460
+                    "PoiId": "0",
461
+                    "DesignerEncryptedId": "",
462
+                    "SdkExtra": "",
463
+                    "AdRawData": "",
464
+                    "BindIds": [],
465
+                    "GradeKey": "",
466
+                    "ComposerParams": "",
467
+                    "Panel": "effects2",
468
+                    "ModelNames": "",
469
+                    "HintFile": {
470
+                        "Uri": "",
471
+                        "UrlList": []
472
+                    },
473
+                    "OriginalExtra": "",
474
+                    "NameTransKey": "",
475
+                    "HintTextTransKey": ""
476
+                },
477
+                {
478
+                    "EffectType": 0,
479
+                    "Source": 0,
480
+                    "IsFavorite": false,
481
+                    "Subtype": 0,
482
+                    "IsBusiness": false,
483
+                    "IsPoi": false,
484
+                    "SyncId": "635012",
485
+                    "ResourceId": "6719657243039502851",
486
+                    "Channel": 1,
487
+                    "PublishStatus": 1,
488
+                    "Ptime": "1586375831000",
489
+                    "ChallengeId": "0",
490
+                    "HintFileFormat": 0,
491
+                    "IsEst": false,
492
+                    "AppID": 1059,
493
+                    "HasProfileInfo": false,
494
+                    "Name": "六屏",
495
+                    "Hint": "",
496
+                    "SdkVersion": "6.6.0",
497
+                    "AppVersion": "",
498
+                    "FileUrl": {
499
+                        "Uri": "95d23405c9441a388784c0749ab99471",
500
+                        "UrlList": [
501
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/95d23405c9441a388784c0749ab99471",
502
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/95d23405c9441a388784c0749ab99471"
503
+                        ]
504
+                    },
505
+                    "IconUrl": {
506
+                        "Uri": "678da0dc576cc136408baeabe4a25d51",
507
+                        "UrlList": [
508
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/678da0dc576cc136408baeabe4a25d51",
509
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/678da0dc576cc136408baeabe4a25d51"
510
+                        ]
511
+                    },
512
+                    "Id": "95d23405c9441a388784c0749ab99471",
513
+                    "EffectId": "635013",
514
+                    "DevicePlatform": "all",
515
+                    "Types": [
516
+                        "AmazingFeature"
517
+                    ],
518
+                    "Tags": [],
519
+                    "TagsUpdatedAt": "1583949944000",
520
+                    "Parent": "",
521
+                    "Children": [],
522
+                    "HintIcon": {
523
+                        "Uri": "",
524
+                        "UrlList": []
525
+                    },
526
+                    "Music": [],
527
+                    "DesignerId": "",
528
+                    "Schema": "",
529
+                    "Description": "",
530
+                    "OriginalEffectId": "",
531
+                    "Requirements": [],
532
+                    "Extra": "{\"hover_icon\":\"713a92c941ef23dc921d0efec114fe35\",\"effect_duration\":3000,\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
533
+                    "Countrys": [],
534
+                    "PoiId": "0",
535
+                    "DesignerEncryptedId": "",
536
+                    "SdkExtra": "",
537
+                    "AdRawData": "",
538
+                    "BindIds": [],
539
+                    "GradeKey": "",
540
+                    "ComposerParams": "",
541
+                    "Panel": "effects2",
542
+                    "ModelNames": "",
543
+                    "HintFile": {
544
+                        "Uri": "",
545
+                        "UrlList": []
546
+                    },
547
+                    "OriginalExtra": "",
548
+                    "NameTransKey": "",
549
+                    "HintTextTransKey": ""
550
+                },
551
+                {
552
+                    "EffectType": 0,
553
+                    "Source": 0,
554
+                    "IsFavorite": false,
555
+                    "Subtype": 0,
556
+                    "IsBusiness": false,
557
+                    "IsPoi": false,
558
+                    "SyncId": "635010",
559
+                    "ResourceId": "6719657094741496333",
560
+                    "Channel": 1,
561
+                    "PublishStatus": 1,
562
+                    "Ptime": "1586375831000",
563
+                    "ChallengeId": "0",
564
+                    "HintFileFormat": 0,
565
+                    "IsEst": false,
566
+                    "AppID": 1059,
567
+                    "HasProfileInfo": false,
568
+                    "Name": "九屏",
569
+                    "Hint": "",
570
+                    "SdkVersion": "6.6.0",
571
+                    "AppVersion": "",
572
+                    "FileUrl": {
573
+                        "Uri": "8abb86f5699f22f9d2c8d1647458b55a",
574
+                        "UrlList": [
575
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/8abb86f5699f22f9d2c8d1647458b55a",
576
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/8abb86f5699f22f9d2c8d1647458b55a"
577
+                        ]
578
+                    },
579
+                    "IconUrl": {
580
+                        "Uri": "ff2091d52675cd500302611411fed4fb",
581
+                        "UrlList": [
582
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/ff2091d52675cd500302611411fed4fb",
583
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/ff2091d52675cd500302611411fed4fb"
584
+                        ]
585
+                    },
586
+                    "Id": "8abb86f5699f22f9d2c8d1647458b55a",
587
+                    "EffectId": "635011",
588
+                    "DevicePlatform": "all",
589
+                    "Types": [
590
+                        "AmazingFeature"
591
+                    ],
592
+                    "Tags": [],
593
+                    "TagsUpdatedAt": "1583949909000",
594
+                    "Parent": "",
595
+                    "Children": [],
596
+                    "HintIcon": {
597
+                        "Uri": "",
598
+                        "UrlList": []
599
+                    },
600
+                    "Music": [],
601
+                    "DesignerId": "",
602
+                    "Schema": "",
603
+                    "Description": "",
604
+                    "OriginalEffectId": "",
605
+                    "Requirements": [],
606
+                    "Extra": "{\"hover_icon\":\"af30912076d9f4ef8cb35c589ad68415\",\"effect_duration\":3000,\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
607
+                    "Countrys": [],
608
+                    "PoiId": "0",
609
+                    "DesignerEncryptedId": "",
610
+                    "SdkExtra": "",
611
+                    "AdRawData": "",
612
+                    "BindIds": [],
613
+                    "GradeKey": "",
614
+                    "ComposerParams": "",
615
+                    "Panel": "effects2",
616
+                    "ModelNames": "",
617
+                    "HintFile": {
618
+                        "Uri": "",
619
+                        "UrlList": []
620
+                    },
621
+                    "OriginalExtra": "",
622
+                    "NameTransKey": "",
623
+                    "HintTextTransKey": ""
624
+                },
625
+                {
626
+                    "EffectType": 0,
627
+                    "Source": 0,
628
+                    "IsFavorite": false,
629
+                    "Subtype": 0,
630
+                    "IsBusiness": false,
631
+                    "IsPoi": false,
632
+                    "SyncId": "635030",
633
+                    "ResourceId": "6726773973683540491",
634
+                    "Channel": 1,
635
+                    "PublishStatus": 1,
636
+                    "Ptime": "1586375831000",
637
+                    "ChallengeId": "0",
638
+                    "HintFileFormat": 0,
639
+                    "IsEst": false,
640
+                    "AppID": 1059,
641
+                    "HasProfileInfo": false,
642
+                    "Name": "九屏跑马灯",
643
+                    "Hint": "",
644
+                    "SdkVersion": "6.6.0",
645
+                    "AppVersion": "",
646
+                    "FileUrl": {
647
+                        "Uri": "0bc85f7544b92909bfef4d20ad17c256",
648
+                        "UrlList": [
649
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/0bc85f7544b92909bfef4d20ad17c256",
650
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/0bc85f7544b92909bfef4d20ad17c256"
651
+                        ]
652
+                    },
653
+                    "IconUrl": {
654
+                        "Uri": "aaae32cd63bda83f7158da779b43b2df",
655
+                        "UrlList": [
656
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/aaae32cd63bda83f7158da779b43b2df",
657
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/aaae32cd63bda83f7158da779b43b2df"
658
+                        ]
659
+                    },
660
+                    "Id": "0bc85f7544b92909bfef4d20ad17c256",
661
+                    "EffectId": "635031",
662
+                    "DevicePlatform": "all",
663
+                    "Types": [
664
+                        "AmazingFeature"
665
+                    ],
666
+                    "Tags": [],
667
+                    "TagsUpdatedAt": "1583950096000",
668
+                    "Parent": "",
669
+                    "Children": [],
670
+                    "HintIcon": {
671
+                        "Uri": "",
672
+                        "UrlList": []
673
+                    },
674
+                    "Music": [],
675
+                    "DesignerId": "",
676
+                    "Schema": "",
677
+                    "Description": "",
678
+                    "OriginalEffectId": "",
679
+                    "Requirements": [],
680
+                    "Extra": "{\"hover_icon\":\"1c3f295553dfe95b8a15e4510b44cfc7\",\"effect_duration\":3000,\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
681
+                    "Countrys": [],
682
+                    "PoiId": "0",
683
+                    "DesignerEncryptedId": "",
684
+                    "SdkExtra": "",
685
+                    "AdRawData": "",
686
+                    "BindIds": [],
687
+                    "GradeKey": "",
688
+                    "ComposerParams": "",
689
+                    "Panel": "effects2",
690
+                    "ModelNames": "",
691
+                    "HintFile": {
692
+                        "Uri": "",
693
+                        "UrlList": []
694
+                    },
695
+                    "OriginalExtra": "",
696
+                    "NameTransKey": "",
697
+                    "HintTextTransKey": ""
698
+                }
699
+            ],
700
+            "Collection": [],
701
+            "CategoryKey": "split",
702
+            "BindEffects": []
703
+        }
704
+    },
705
+    "extra": {
706
+        "RecId": "202406151625416BA1900F12C59B091F23"
707
+    },
708
+    "BaseResp": {
709
+        "StatusMessage": "success",
710
+        "StatusCode": 0
711
+    }
712
+}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 4405 - 0
src/nodeapi/drafts/data/texiao/fenwei.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 4472 - 0
src/nodeapi/drafts/data/texiao/fugu.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 2297 - 0
src/nodeapi/drafts/data/texiao/guang.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 4929 - 0
src/nodeapi/drafts/data/texiao/jichu.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1712 - 0
src/nodeapi/drafts/data/texiao/jinfen.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1700 - 0
src/nodeapi/drafts/data/texiao/manhua.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 708 - 0
src/nodeapi/drafts/data/texiao/niuqu.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 7147 - 0
src/nodeapi/drafts/data/texiao/remen.json


+ 124 - 0
src/nodeapi/drafts/data/texiao/texiao.js

@@ -0,0 +1,124 @@
1
+const fs = require('fs').promises;
2
+const path = require('path');
3
+const { v4: uuidv4 } = require('uuid');
4
+
5
+/**
6
+ * 读取当前目录下所有的 .json 文件并返回其内容的数组
7
+ * @returns {Promise<Array<Object>>} 包含所有 JSON 文件内容的数组
8
+ */
9
+async function readAllJsonFiles() {
10
+    try {
11
+        // 获取当前脚本目录路径
12
+        const directoryPath = __dirname;
13
+
14
+        // 读取目录内容
15
+        const files = await fs.readdir(directoryPath);
16
+
17
+        // 过滤出 .json 文件
18
+        const jsonFiles = files.filter(file => path.extname(file).toLowerCase() === '.json');
19
+
20
+        // 创建一个读取 JSON 文件的 Promise 数组
21
+        const readPromises = jsonFiles.map(async (file) => {
22
+            const filePath = path.join(directoryPath, file);
23
+
24
+            // 异步读取 JSON 文件
25
+            const data = await fs.readFile(filePath, 'utf8');
26
+            return JSON.parse(data);
27
+        });
28
+
29
+        // 等待所有 JSON 文件读取完成并返回内容数组
30
+        return await Promise.all(readPromises);
31
+    } catch (err) {
32
+        console.error("Error reading JSON files:", err);
33
+        throw err;
34
+    }
35
+}
36
+
37
+//mode = 0 非vip  mode = 1 vip  mode = 2 all 
38
+async function get_all_texiao_Effects(mode=0){
39
+
40
+    let vip_effects = []
41
+    let effects = []
42
+    const contents = await readAllJsonFiles();
43
+    for (let content of contents) {
44
+
45
+        let tmp_effects = content.data.CategoryEffects.Effects;
46
+
47
+        for (let effect of tmp_effects) {
48
+            let adjust_params = []
49
+            if(effect.SdkExtra){
50
+                adjust_params = JSON.parse(effect.SdkExtra).setting.effect_adjust_params
51
+            }
52
+            let tmp = {
53
+                "adjust_params": adjust_params,
54
+                "algorithm_artifact_path": "",
55
+                "apply_target_type": 2,
56
+                "apply_time_range": null,
57
+                "category_id": "",
58
+                "category_name": "",
59
+                "common_keyframes": [],
60
+                "disable_effect_faces": [],
61
+                "effect_id": effect.EffectId,
62
+                "formula_id": "",
63
+                "id": uuidv4(),
64
+                "name": effect.Name,
65
+                "path": "",
66
+                "platform": "all",
67
+                "render_index": 0,
68
+                "request_id": "",
69
+                "resource_id": effect.ResourceId,
70
+                "source_platform": 0,
71
+                "time_range": null,
72
+                "track_render_index": 0,
73
+                "type": "video_effect",
74
+                "value": 1.0,
75
+                "version": "",
76
+                "icon_url":effect.IconUrl.UrlList[0]
77
+            }
78
+
79
+            let extra = JSON.parse(effect.Extra)
80
+            if (extra.is_vip) {
81
+                tmp.is_vip = 1
82
+                vip_effects.push(tmp)
83
+            } else {
84
+                tmp.is_vip = 0
85
+                effects.push(tmp)
86
+            }
87
+
88
+        }
89
+
90
+    }
91
+
92
+    if(mode==0 ){
93
+        return effects
94
+    }else if(mode == 1){
95
+        return vip_effects
96
+    }else{
97
+        return [...vip_effects,...effects]
98
+    }
99
+}
100
+
101
+async function find_texiao_animation_by_resource_id(resource_id){
102
+    let effects = await get_all_texiao_Effects(2);
103
+    for(let info of effects){
104
+        if(info.resource_id == resource_id){
105
+            return info
106
+        }
107
+    }
108
+    return null
109
+
110
+}
111
+
112
+
113
+
114
+// (async () => {
115
+//     try {
116
+//         const contents = await find_texiao_animation_by_resource_id('7348707427165934107')
117
+//         console.log(" contents:", contents);
118
+//     } catch (err) {
119
+//         console.error(err);
120
+//     }
121
+// })();
122
+
123
+
124
+module.exports = { get_all_texiao_Effects , find_texiao_animation_by_resource_id };

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 2354 - 0
src/nodeapi/drafts/data/texiao/touyin.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 2118 - 0
src/nodeapi/drafts/data/texiao/wenli.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 2882 - 0
src/nodeapi/drafts/data/texiao/ziran.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 2287 - 0
src/nodeapi/drafts/data/texiao/zongyi.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 4550 - 0
src/nodeapi/drafts/data/text/chuchang.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 5368 - 0
src/nodeapi/drafts/data/text/ruchang.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 3439 - 0
src/nodeapi/drafts/data/text/xunhuan.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 7499 - 0
src/nodeapi/drafts/data/video/group.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 3050 - 0
src/nodeapi/drafts/data/video/ins.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1643 - 0
src/nodeapi/drafts/data/video/out.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1138 - 0
src/nodeapi/drafts/data/zhuanchang/diehua123.json


+ 322 - 0
src/nodeapi/drafts/data/zhuanchang/fenge123.json

@@ -0,0 +1,322 @@
1
+{
2
+    "data": {
3
+        "UrlPrefix": [
4
+            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/",
5
+            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/"
6
+        ],
7
+        "CategoryEffects": {
8
+            "HasMore": false,
9
+            "Cursor": 4,
10
+            "SortingPosition": 4,
11
+            "Version": "1844556325045,1378906947054,900,0",
12
+            "Effects": [
13
+                {
14
+                    "EffectType": 0,
15
+                    "Source": 0,
16
+                    "IsFavorite": false,
17
+                    "Subtype": 0,
18
+                    "IsBusiness": false,
19
+                    "IsPoi": false,
20
+                    "SyncId": "4211678",
21
+                    "ResourceId": "6968372308419285540",
22
+                    "Channel": 1,
23
+                    "PublishStatus": 1,
24
+                    "Ptime": "1661354564000",
25
+                    "ChallengeId": "0",
26
+                    "HintFileFormat": 0,
27
+                    "IsEst": false,
28
+                    "AppID": 1059,
29
+                    "HasProfileInfo": false,
30
+                    "Name": "分割",
31
+                    "Hint": "",
32
+                    "SdkVersion": "5.4.0",
33
+                    "AppVersion": "",
34
+                    "FileUrl": {
35
+                        "Uri": "c90cd8813df7e6a869a467f4d29a5623",
36
+                        "UrlList": [
37
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c90cd8813df7e6a869a467f4d29a5623",
38
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c90cd8813df7e6a869a467f4d29a5623"
39
+                        ]
40
+                    },
41
+                    "IconUrl": {
42
+                        "Uri": "e5043b740dd931226079337e5f2c31a4",
43
+                        "UrlList": [
44
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/e5043b740dd931226079337e5f2c31a4",
45
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/e5043b740dd931226079337e5f2c31a4"
46
+                        ]
47
+                    },
48
+                    "Id": "c90cd8813df7e6a869a467f4d29a5623",
49
+                    "EffectId": "4211683",
50
+                    "DevicePlatform": "all",
51
+                    "Types": [
52
+                        "GeneralEffect"
53
+                    ],
54
+                    "Tags": [],
55
+                    "TagsUpdatedAt": "1661255096000",
56
+                    "Parent": "",
57
+                    "Children": [],
58
+                    "HintIcon": {
59
+                        "Uri": "",
60
+                        "UrlList": []
61
+                    },
62
+                    "Music": [],
63
+                    "DesignerId": "",
64
+                    "Schema": "",
65
+                    "Description": "",
66
+                    "OriginalEffectId": "",
67
+                    "Requirements": [],
68
+                    "Extra": "{\"hover_icon\":\"d76b67e614b949b3974685a14d777e85\",\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
69
+                    "Countrys": [],
70
+                    "PoiId": "0",
71
+                    "DesignerEncryptedId": "",
72
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
73
+                    "AdRawData": "",
74
+                    "BindIds": [],
75
+                    "GradeKey": "",
76
+                    "ComposerParams": "",
77
+                    "Panel": "transitions",
78
+                    "ModelNames": "",
79
+                    "HintFile": {
80
+                        "Uri": "",
81
+                        "UrlList": []
82
+                    },
83
+                    "OriginalExtra": "",
84
+                    "NameTransKey": "",
85
+                    "HintTextTransKey": ""
86
+                },
87
+                {
88
+                    "EffectType": 0,
89
+                    "Source": 0,
90
+                    "IsFavorite": false,
91
+                    "Subtype": 0,
92
+                    "IsBusiness": false,
93
+                    "IsPoi": false,
94
+                    "SyncId": "4211733",
95
+                    "ResourceId": "6969782622868214302",
96
+                    "Channel": 1,
97
+                    "PublishStatus": 1,
98
+                    "Ptime": "1661354125000",
99
+                    "ChallengeId": "0",
100
+                    "HintFileFormat": 0,
101
+                    "IsEst": false,
102
+                    "AppID": 1059,
103
+                    "HasProfileInfo": false,
104
+                    "Name": "分割 II",
105
+                    "Hint": "",
106
+                    "SdkVersion": "5.4.0",
107
+                    "AppVersion": "",
108
+                    "FileUrl": {
109
+                        "Uri": "8809623e72363cadcf533ae49671a6f4",
110
+                        "UrlList": [
111
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/8809623e72363cadcf533ae49671a6f4",
112
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/8809623e72363cadcf533ae49671a6f4"
113
+                        ]
114
+                    },
115
+                    "IconUrl": {
116
+                        "Uri": "366048fceb5ba4ed9842da978e543a93",
117
+                        "UrlList": [
118
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/366048fceb5ba4ed9842da978e543a93",
119
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/366048fceb5ba4ed9842da978e543a93"
120
+                        ]
121
+                    },
122
+                    "Id": "8809623e72363cadcf533ae49671a6f4",
123
+                    "EffectId": "4211740",
124
+                    "DevicePlatform": "all",
125
+                    "Types": [
126
+                        "GeneralEffect"
127
+                    ],
128
+                    "Tags": [],
129
+                    "TagsUpdatedAt": "1661255412000",
130
+                    "Parent": "",
131
+                    "Children": [],
132
+                    "HintIcon": {
133
+                        "Uri": "",
134
+                        "UrlList": []
135
+                    },
136
+                    "Music": [],
137
+                    "DesignerId": "",
138
+                    "Schema": "",
139
+                    "Description": "",
140
+                    "OriginalEffectId": "",
141
+                    "Requirements": [],
142
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"c7abe1be99a153c7aab69f2d9649fa03\",\"is_business\":true}",
143
+                    "Countrys": [],
144
+                    "PoiId": "0",
145
+                    "DesignerEncryptedId": "",
146
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
147
+                    "AdRawData": "",
148
+                    "BindIds": [],
149
+                    "GradeKey": "",
150
+                    "ComposerParams": "",
151
+                    "Panel": "transitions",
152
+                    "ModelNames": "",
153
+                    "HintFile": {
154
+                        "Uri": "",
155
+                        "UrlList": []
156
+                    },
157
+                    "OriginalExtra": "",
158
+                    "NameTransKey": "",
159
+                    "HintTextTransKey": ""
160
+                },
161
+                {
162
+                    "EffectType": 0,
163
+                    "Source": 0,
164
+                    "IsFavorite": false,
165
+                    "Subtype": 0,
166
+                    "IsBusiness": false,
167
+                    "IsPoi": false,
168
+                    "SyncId": "4211732",
169
+                    "ResourceId": "6969793843403166215",
170
+                    "Channel": 1,
171
+                    "PublishStatus": 1,
172
+                    "Ptime": "1661354565000",
173
+                    "ChallengeId": "0",
174
+                    "HintFileFormat": 0,
175
+                    "IsEst": false,
176
+                    "AppID": 1059,
177
+                    "HasProfileInfo": false,
178
+                    "Name": "分割 III",
179
+                    "Hint": "",
180
+                    "SdkVersion": "5.4.0",
181
+                    "AppVersion": "",
182
+                    "FileUrl": {
183
+                        "Uri": "bd826dba57320355231354e9d791a77a",
184
+                        "UrlList": [
185
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/bd826dba57320355231354e9d791a77a",
186
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/bd826dba57320355231354e9d791a77a"
187
+                        ]
188
+                    },
189
+                    "IconUrl": {
190
+                        "Uri": "c32472a5e818f16f1f17c0f3634cf787",
191
+                        "UrlList": [
192
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c32472a5e818f16f1f17c0f3634cf787",
193
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c32472a5e818f16f1f17c0f3634cf787"
194
+                        ]
195
+                    },
196
+                    "Id": "bd826dba57320355231354e9d791a77a",
197
+                    "EffectId": "4211739",
198
+                    "DevicePlatform": "all",
199
+                    "Types": [
200
+                        "GeneralEffect"
201
+                    ],
202
+                    "Tags": [],
203
+                    "TagsUpdatedAt": "1661255412000",
204
+                    "Parent": "",
205
+                    "Children": [],
206
+                    "HintIcon": {
207
+                        "Uri": "",
208
+                        "UrlList": []
209
+                    },
210
+                    "Music": [],
211
+                    "DesignerId": "",
212
+                    "Schema": "",
213
+                    "Description": "",
214
+                    "OriginalEffectId": "",
215
+                    "Requirements": [],
216
+                    "Extra": "{\"hover_icon\":\"2c1a77f7f4df7d530bacdb5990b00f3c\",\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
217
+                    "Countrys": [],
218
+                    "PoiId": "0",
219
+                    "DesignerEncryptedId": "",
220
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
221
+                    "AdRawData": "",
222
+                    "BindIds": [],
223
+                    "GradeKey": "",
224
+                    "ComposerParams": "",
225
+                    "Panel": "transitions",
226
+                    "ModelNames": "",
227
+                    "HintFile": {
228
+                        "Uri": "",
229
+                        "UrlList": []
230
+                    },
231
+                    "OriginalExtra": "",
232
+                    "NameTransKey": "",
233
+                    "HintTextTransKey": ""
234
+                },
235
+                {
236
+                    "EffectType": 0,
237
+                    "Source": 0,
238
+                    "IsFavorite": false,
239
+                    "Subtype": 0,
240
+                    "IsBusiness": false,
241
+                    "IsPoi": false,
242
+                    "SyncId": "4211731",
243
+                    "ResourceId": "6969793934356648455",
244
+                    "Channel": 1,
245
+                    "PublishStatus": 1,
246
+                    "Ptime": "1661354564000",
247
+                    "ChallengeId": "0",
248
+                    "HintFileFormat": 0,
249
+                    "IsEst": false,
250
+                    "AppID": 1059,
251
+                    "HasProfileInfo": false,
252
+                    "Name": "分割 IV",
253
+                    "Hint": "",
254
+                    "SdkVersion": "5.4.0",
255
+                    "AppVersion": "",
256
+                    "FileUrl": {
257
+                        "Uri": "5f0b9ca9682e890a4c9320266965bce7",
258
+                        "UrlList": [
259
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/5f0b9ca9682e890a4c9320266965bce7",
260
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/5f0b9ca9682e890a4c9320266965bce7"
261
+                        ]
262
+                    },
263
+                    "IconUrl": {
264
+                        "Uri": "16f63b06285d47e36138487683ccae54",
265
+                        "UrlList": [
266
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/16f63b06285d47e36138487683ccae54",
267
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/16f63b06285d47e36138487683ccae54"
268
+                        ]
269
+                    },
270
+                    "Id": "5f0b9ca9682e890a4c9320266965bce7",
271
+                    "EffectId": "4211738",
272
+                    "DevicePlatform": "all",
273
+                    "Types": [
274
+                        "GeneralEffect"
275
+                    ],
276
+                    "Tags": [],
277
+                    "TagsUpdatedAt": "1661255412000",
278
+                    "Parent": "",
279
+                    "Children": [],
280
+                    "HintIcon": {
281
+                        "Uri": "",
282
+                        "UrlList": []
283
+                    },
284
+                    "Music": [],
285
+                    "DesignerId": "",
286
+                    "Schema": "",
287
+                    "Description": "",
288
+                    "OriginalEffectId": "",
289
+                    "Requirements": [],
290
+                    "Extra": "{\"hover_icon\":\"086cfb091e862b551a3a23c0bd089dd9\",\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
291
+                    "Countrys": [],
292
+                    "PoiId": "0",
293
+                    "DesignerEncryptedId": "",
294
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
295
+                    "AdRawData": "",
296
+                    "BindIds": [],
297
+                    "GradeKey": "",
298
+                    "ComposerParams": "",
299
+                    "Panel": "transitions",
300
+                    "ModelNames": "",
301
+                    "HintFile": {
302
+                        "Uri": "",
303
+                        "UrlList": []
304
+                    },
305
+                    "OriginalExtra": "",
306
+                    "NameTransKey": "",
307
+                    "HintTextTransKey": ""
308
+                }
309
+            ],
310
+            "Collection": [],
311
+            "CategoryKey": "fenge123",
312
+            "BindEffects": []
313
+        }
314
+    },
315
+    "extra": {
316
+        "RecId": "202406151640541CA9F95EC644380868B8"
317
+    },
318
+    "BaseResp": {
319
+        "StatusMessage": "success",
320
+        "StatusCode": 0
321
+    }
322
+}

+ 618 - 0
src/nodeapi/drafts/data/zhuanchang/guangxiao123.json

@@ -0,0 +1,618 @@
1
+{
2
+    "data": {
3
+        "UrlPrefix": [
4
+            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/",
5
+            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/"
6
+        ],
7
+        "CategoryEffects": {
8
+            "HasMore": false,
9
+            "Cursor": 8,
10
+            "SortingPosition": 8,
11
+            "Version": "1555765446492,9347624909042,900,0",
12
+            "Effects": [
13
+                {
14
+                    "EffectType": 0,
15
+                    "Source": 0,
16
+                    "IsFavorite": false,
17
+                    "Subtype": 0,
18
+                    "IsBusiness": false,
19
+                    "IsPoi": false,
20
+                    "SyncId": "4202519",
21
+                    "ResourceId": "6982127832042312206",
22
+                    "Channel": 1,
23
+                    "PublishStatus": 1,
24
+                    "Ptime": "1661354712000",
25
+                    "ChallengeId": "0",
26
+                    "HintFileFormat": 0,
27
+                    "IsEst": false,
28
+                    "AppID": 1059,
29
+                    "HasProfileInfo": false,
30
+                    "Name": "光束",
31
+                    "Hint": "",
32
+                    "SdkVersion": "5.4.0",
33
+                    "AppVersion": "",
34
+                    "FileUrl": {
35
+                        "Uri": "ce590414be455521a856357be5231400",
36
+                        "UrlList": [
37
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/ce590414be455521a856357be5231400",
38
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/ce590414be455521a856357be5231400"
39
+                        ]
40
+                    },
41
+                    "IconUrl": {
42
+                        "Uri": "cc16c8b38acde6a4c914a1309caf232d",
43
+                        "UrlList": [
44
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/cc16c8b38acde6a4c914a1309caf232d",
45
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/cc16c8b38acde6a4c914a1309caf232d"
46
+                        ]
47
+                    },
48
+                    "Id": "ce590414be455521a856357be5231400",
49
+                    "EffectId": "4202531",
50
+                    "DevicePlatform": "all",
51
+                    "Types": [
52
+                        "GeneralEffect"
53
+                    ],
54
+                    "Tags": [],
55
+                    "TagsUpdatedAt": "1661195086000",
56
+                    "Parent": "",
57
+                    "Children": [],
58
+                    "HintIcon": {
59
+                        "Uri": "",
60
+                        "UrlList": []
61
+                    },
62
+                    "Music": [],
63
+                    "DesignerId": "",
64
+                    "Schema": "",
65
+                    "Description": "",
66
+                    "OriginalEffectId": "",
67
+                    "Requirements": [],
68
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"3c79fbc89569c4117e47aec561138255\",\"is_business\":true,\"is_vip\":true}",
69
+                    "Countrys": [],
70
+                    "PoiId": "0",
71
+                    "DesignerEncryptedId": "",
72
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
73
+                    "AdRawData": "",
74
+                    "BindIds": [],
75
+                    "GradeKey": "",
76
+                    "ComposerParams": "",
77
+                    "Panel": "transitions",
78
+                    "ModelNames": "",
79
+                    "HintFile": {
80
+                        "Uri": "",
81
+                        "UrlList": []
82
+                    },
83
+                    "OriginalExtra": "",
84
+                    "NameTransKey": "",
85
+                    "HintTextTransKey": ""
86
+                },
87
+                {
88
+                    "EffectType": 0,
89
+                    "Source": 0,
90
+                    "IsFavorite": false,
91
+                    "Subtype": 0,
92
+                    "IsBusiness": false,
93
+                    "IsPoi": false,
94
+                    "SyncId": "4202516",
95
+                    "ResourceId": "6949828109663212045",
96
+                    "Channel": 1,
97
+                    "PublishStatus": 1,
98
+                    "Ptime": "1661354711000",
99
+                    "ChallengeId": "0",
100
+                    "HintFileFormat": 0,
101
+                    "IsEst": false,
102
+                    "AppID": 1059,
103
+                    "HasProfileInfo": false,
104
+                    "Name": "泛白",
105
+                    "Hint": "",
106
+                    "SdkVersion": "5.4.0",
107
+                    "AppVersion": "",
108
+                    "FileUrl": {
109
+                        "Uri": "3075d1561cac57a821e5d46a9125f7e6",
110
+                        "UrlList": [
111
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/3075d1561cac57a821e5d46a9125f7e6",
112
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/3075d1561cac57a821e5d46a9125f7e6"
113
+                        ]
114
+                    },
115
+                    "IconUrl": {
116
+                        "Uri": "246972421758a26ef2cf133828497ca2",
117
+                        "UrlList": [
118
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/246972421758a26ef2cf133828497ca2",
119
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/246972421758a26ef2cf133828497ca2"
120
+                        ]
121
+                    },
122
+                    "Id": "3075d1561cac57a821e5d46a9125f7e6",
123
+                    "EffectId": "4202528",
124
+                    "DevicePlatform": "all",
125
+                    "Types": [
126
+                        "GeneralEffect"
127
+                    ],
128
+                    "Tags": [],
129
+                    "TagsUpdatedAt": "1661195086000",
130
+                    "Parent": "",
131
+                    "Children": [],
132
+                    "HintIcon": {
133
+                        "Uri": "",
134
+                        "UrlList": []
135
+                    },
136
+                    "Music": [],
137
+                    "DesignerId": "",
138
+                    "Schema": "",
139
+                    "Description": "",
140
+                    "OriginalEffectId": "",
141
+                    "Requirements": [],
142
+                    "Extra": "{\"hover_icon\":\"044e5c1efc4aad55a530d33034e6ad98\",\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
143
+                    "Countrys": [],
144
+                    "PoiId": "0",
145
+                    "DesignerEncryptedId": "",
146
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":1,\"isOverlap\":false}}",
147
+                    "AdRawData": "",
148
+                    "BindIds": [],
149
+                    "GradeKey": "",
150
+                    "ComposerParams": "",
151
+                    "Panel": "transitions",
152
+                    "ModelNames": "",
153
+                    "HintFile": {
154
+                        "Uri": "",
155
+                        "UrlList": []
156
+                    },
157
+                    "OriginalExtra": "",
158
+                    "NameTransKey": "",
159
+                    "HintTextTransKey": ""
160
+                },
161
+                {
162
+                    "EffectType": 0,
163
+                    "Source": 0,
164
+                    "IsFavorite": false,
165
+                    "Subtype": 0,
166
+                    "IsBusiness": false,
167
+                    "IsPoi": false,
168
+                    "SyncId": "4202512",
169
+                    "ResourceId": "6726707814028284423",
170
+                    "Channel": 1,
171
+                    "PublishStatus": 1,
172
+                    "Ptime": "1661354711000",
173
+                    "ChallengeId": "0",
174
+                    "HintFileFormat": 0,
175
+                    "IsEst": false,
176
+                    "AppID": 1059,
177
+                    "HasProfileInfo": false,
178
+                    "Name": "炫光",
179
+                    "Hint": "",
180
+                    "SdkVersion": "5.0.0",
181
+                    "AppVersion": "",
182
+                    "FileUrl": {
183
+                        "Uri": "bfa8f64407cb5c3c1d78ca0c45499273",
184
+                        "UrlList": [
185
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/bfa8f64407cb5c3c1d78ca0c45499273",
186
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/bfa8f64407cb5c3c1d78ca0c45499273"
187
+                        ]
188
+                    },
189
+                    "IconUrl": {
190
+                        "Uri": "3e6e029c79bdebe61699a734f379d78d",
191
+                        "UrlList": [
192
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/3e6e029c79bdebe61699a734f379d78d",
193
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/3e6e029c79bdebe61699a734f379d78d"
194
+                        ]
195
+                    },
196
+                    "Id": "bfa8f64407cb5c3c1d78ca0c45499273",
197
+                    "EffectId": "4202524",
198
+                    "DevicePlatform": "all",
199
+                    "Types": [
200
+                        "GeneralEffect"
201
+                    ],
202
+                    "Tags": [],
203
+                    "TagsUpdatedAt": "1661195086000",
204
+                    "Parent": "",
205
+                    "Children": [],
206
+                    "HintIcon": {
207
+                        "Uri": "",
208
+                        "UrlList": []
209
+                    },
210
+                    "Music": [],
211
+                    "DesignerId": "",
212
+                    "Schema": "",
213
+                    "Description": "",
214
+                    "OriginalEffectId": "",
215
+                    "Requirements": [],
216
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"6ff05d72c2ff6309f64dbeffbda33c17\",\"is_business\":true,\"is_vip\":true}",
217
+                    "Countrys": [],
218
+                    "PoiId": "0",
219
+                    "DesignerEncryptedId": "",
220
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
221
+                    "AdRawData": "",
222
+                    "BindIds": [],
223
+                    "GradeKey": "",
224
+                    "ComposerParams": "",
225
+                    "Panel": "transitions",
226
+                    "ModelNames": "",
227
+                    "HintFile": {
228
+                        "Uri": "",
229
+                        "UrlList": []
230
+                    },
231
+                    "OriginalExtra": "",
232
+                    "NameTransKey": "",
233
+                    "HintTextTransKey": ""
234
+                },
235
+                {
236
+                    "EffectType": 0,
237
+                    "Source": 0,
238
+                    "IsFavorite": false,
239
+                    "Subtype": 0,
240
+                    "IsBusiness": false,
241
+                    "IsPoi": false,
242
+                    "SyncId": "4202513",
243
+                    "ResourceId": "6777178510050988551",
244
+                    "Channel": 1,
245
+                    "PublishStatus": 1,
246
+                    "Ptime": "1661354711000",
247
+                    "ChallengeId": "0",
248
+                    "HintFileFormat": 0,
249
+                    "IsEst": false,
250
+                    "AppID": 1059,
251
+                    "HasProfileInfo": false,
252
+                    "Name": "闪动光斑",
253
+                    "Hint": "",
254
+                    "SdkVersion": "5.0.0",
255
+                    "AppVersion": "",
256
+                    "FileUrl": {
257
+                        "Uri": "8858cf2ad00f38a1944435f35c127770",
258
+                        "UrlList": [
259
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/8858cf2ad00f38a1944435f35c127770",
260
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/8858cf2ad00f38a1944435f35c127770"
261
+                        ]
262
+                    },
263
+                    "IconUrl": {
264
+                        "Uri": "c8b99e096fe3c7ac0d26336eab212cf8",
265
+                        "UrlList": [
266
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c8b99e096fe3c7ac0d26336eab212cf8",
267
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c8b99e096fe3c7ac0d26336eab212cf8"
268
+                        ]
269
+                    },
270
+                    "Id": "8858cf2ad00f38a1944435f35c127770",
271
+                    "EffectId": "4202525",
272
+                    "DevicePlatform": "all",
273
+                    "Types": [
274
+                        "GeneralEffect"
275
+                    ],
276
+                    "Tags": [],
277
+                    "TagsUpdatedAt": "1661195086000",
278
+                    "Parent": "",
279
+                    "Children": [],
280
+                    "HintIcon": {
281
+                        "Uri": "",
282
+                        "UrlList": []
283
+                    },
284
+                    "Music": [],
285
+                    "DesignerId": "",
286
+                    "Schema": "",
287
+                    "Description": "",
288
+                    "OriginalEffectId": "",
289
+                    "Requirements": [],
290
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"6c2b1ed94f89add7a2f5e7c888411703\",\"is_business\":true,\"is_vip\":true}",
291
+                    "Countrys": [],
292
+                    "PoiId": "0",
293
+                    "DesignerEncryptedId": "",
294
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":false}}",
295
+                    "AdRawData": "",
296
+                    "BindIds": [],
297
+                    "GradeKey": "",
298
+                    "ComposerParams": "",
299
+                    "Panel": "transitions",
300
+                    "ModelNames": "",
301
+                    "HintFile": {
302
+                        "Uri": "",
303
+                        "UrlList": []
304
+                    },
305
+                    "OriginalExtra": "",
306
+                    "NameTransKey": "",
307
+                    "HintTextTransKey": ""
308
+                },
309
+                {
310
+                    "EffectType": 0,
311
+                    "Source": 0,
312
+                    "IsFavorite": false,
313
+                    "Subtype": 0,
314
+                    "IsBusiness": false,
315
+                    "IsPoi": false,
316
+                    "SyncId": "4202518",
317
+                    "ResourceId": "6950255790762496548",
318
+                    "Channel": 1,
319
+                    "PublishStatus": 1,
320
+                    "Ptime": "1661354711000",
321
+                    "ChallengeId": "0",
322
+                    "HintFileFormat": 0,
323
+                    "IsEst": false,
324
+                    "AppID": 1059,
325
+                    "HasProfileInfo": false,
326
+                    "Name": "炫光 II",
327
+                    "Hint": "",
328
+                    "SdkVersion": "5.4.0",
329
+                    "AppVersion": "",
330
+                    "FileUrl": {
331
+                        "Uri": "13cd1ceede9d5aa8a486d800ce74b1af",
332
+                        "UrlList": [
333
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/13cd1ceede9d5aa8a486d800ce74b1af",
334
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/13cd1ceede9d5aa8a486d800ce74b1af"
335
+                        ]
336
+                    },
337
+                    "IconUrl": {
338
+                        "Uri": "9a16cfc2038e4222b6e73996989167e6",
339
+                        "UrlList": [
340
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/9a16cfc2038e4222b6e73996989167e6",
341
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/9a16cfc2038e4222b6e73996989167e6"
342
+                        ]
343
+                    },
344
+                    "Id": "13cd1ceede9d5aa8a486d800ce74b1af",
345
+                    "EffectId": "4202530",
346
+                    "DevicePlatform": "all",
347
+                    "Types": [
348
+                        "GeneralEffect"
349
+                    ],
350
+                    "Tags": [],
351
+                    "TagsUpdatedAt": "1661195086000",
352
+                    "Parent": "",
353
+                    "Children": [],
354
+                    "HintIcon": {
355
+                        "Uri": "",
356
+                        "UrlList": []
357
+                    },
358
+                    "Music": [],
359
+                    "DesignerId": "",
360
+                    "Schema": "",
361
+                    "Description": "",
362
+                    "OriginalEffectId": "",
363
+                    "Requirements": [],
364
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"a05a64136b34fddf288b78d663cf96b5\",\"is_business\":true,\"is_vip\":true}",
365
+                    "Countrys": [],
366
+                    "PoiId": "0",
367
+                    "DesignerEncryptedId": "",
368
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":false}}",
369
+                    "AdRawData": "",
370
+                    "BindIds": [],
371
+                    "GradeKey": "",
372
+                    "ComposerParams": "",
373
+                    "Panel": "transitions",
374
+                    "ModelNames": "",
375
+                    "HintFile": {
376
+                        "Uri": "",
377
+                        "UrlList": []
378
+                    },
379
+                    "OriginalExtra": "",
380
+                    "NameTransKey": "",
381
+                    "HintTextTransKey": ""
382
+                },
383
+                {
384
+                    "EffectType": 0,
385
+                    "Source": 0,
386
+                    "IsFavorite": false,
387
+                    "Subtype": 0,
388
+                    "IsBusiness": false,
389
+                    "IsPoi": false,
390
+                    "SyncId": "4202517",
391
+                    "ResourceId": "6950255930160189988",
392
+                    "Channel": 1,
393
+                    "PublishStatus": 1,
394
+                    "Ptime": "1661354711000",
395
+                    "ChallengeId": "0",
396
+                    "HintFileFormat": 0,
397
+                    "IsEst": false,
398
+                    "AppID": 1059,
399
+                    "HasProfileInfo": false,
400
+                    "Name": "炫光 III",
401
+                    "Hint": "",
402
+                    "SdkVersion": "5.4.0",
403
+                    "AppVersion": "",
404
+                    "FileUrl": {
405
+                        "Uri": "9fc36423c6a972696e159d7204c7fde5",
406
+                        "UrlList": [
407
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/9fc36423c6a972696e159d7204c7fde5",
408
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/9fc36423c6a972696e159d7204c7fde5"
409
+                        ]
410
+                    },
411
+                    "IconUrl": {
412
+                        "Uri": "f3f83922ea84986135233afba58a30a9",
413
+                        "UrlList": [
414
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/f3f83922ea84986135233afba58a30a9",
415
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/f3f83922ea84986135233afba58a30a9"
416
+                        ]
417
+                    },
418
+                    "Id": "9fc36423c6a972696e159d7204c7fde5",
419
+                    "EffectId": "4202529",
420
+                    "DevicePlatform": "all",
421
+                    "Types": [
422
+                        "GeneralEffect"
423
+                    ],
424
+                    "Tags": [],
425
+                    "TagsUpdatedAt": "1661195086000",
426
+                    "Parent": "",
427
+                    "Children": [],
428
+                    "HintIcon": {
429
+                        "Uri": "",
430
+                        "UrlList": []
431
+                    },
432
+                    "Music": [],
433
+                    "DesignerId": "",
434
+                    "Schema": "",
435
+                    "Description": "",
436
+                    "OriginalEffectId": "",
437
+                    "Requirements": [],
438
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"d945b946bb6c150f925738756bfb5ef3\",\"is_business\":true,\"is_vip\":true}",
439
+                    "Countrys": [],
440
+                    "PoiId": "0",
441
+                    "DesignerEncryptedId": "",
442
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":false}}",
443
+                    "AdRawData": "",
444
+                    "BindIds": [],
445
+                    "GradeKey": "",
446
+                    "ComposerParams": "",
447
+                    "Panel": "transitions",
448
+                    "ModelNames": "",
449
+                    "HintFile": {
450
+                        "Uri": "",
451
+                        "UrlList": []
452
+                    },
453
+                    "OriginalExtra": "",
454
+                    "NameTransKey": "",
455
+                    "HintTextTransKey": ""
456
+                },
457
+                {
458
+                    "EffectType": 0,
459
+                    "Source": 0,
460
+                    "IsFavorite": false,
461
+                    "Subtype": 0,
462
+                    "IsBusiness": false,
463
+                    "IsPoi": false,
464
+                    "SyncId": "4202520",
465
+                    "ResourceId": "6986584807543149063",
466
+                    "Channel": 1,
467
+                    "PublishStatus": 1,
468
+                    "Ptime": "1661354712000",
469
+                    "ChallengeId": "0",
470
+                    "HintFileFormat": 0,
471
+                    "IsEst": false,
472
+                    "AppID": 1059,
473
+                    "HasProfileInfo": false,
474
+                    "Name": "闪光灯",
475
+                    "Hint": "",
476
+                    "SdkVersion": "5.4.0",
477
+                    "AppVersion": "",
478
+                    "FileUrl": {
479
+                        "Uri": "0b3bae116469fbe91ebd951affefac7c",
480
+                        "UrlList": [
481
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/0b3bae116469fbe91ebd951affefac7c",
482
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/0b3bae116469fbe91ebd951affefac7c"
483
+                        ]
484
+                    },
485
+                    "IconUrl": {
486
+                        "Uri": "97265283ce5aceb48fa295e799bd81c9",
487
+                        "UrlList": [
488
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/97265283ce5aceb48fa295e799bd81c9",
489
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/97265283ce5aceb48fa295e799bd81c9"
490
+                        ]
491
+                    },
492
+                    "Id": "0b3bae116469fbe91ebd951affefac7c",
493
+                    "EffectId": "4202532",
494
+                    "DevicePlatform": "all",
495
+                    "Types": [
496
+                        "GeneralEffect"
497
+                    ],
498
+                    "Tags": [],
499
+                    "TagsUpdatedAt": "1661195086000",
500
+                    "Parent": "",
501
+                    "Children": [],
502
+                    "HintIcon": {
503
+                        "Uri": "",
504
+                        "UrlList": []
505
+                    },
506
+                    "Music": [],
507
+                    "DesignerId": "",
508
+                    "Schema": "",
509
+                    "Description": "",
510
+                    "OriginalEffectId": "",
511
+                    "Requirements": [],
512
+                    "Extra": "{\"hover_icon\":\"044e5c1efc4aad55a530d33034e6ad98\",\"is_business\":true,\"is_vip\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
513
+                    "Countrys": [],
514
+                    "PoiId": "0",
515
+                    "DesignerEncryptedId": "",
516
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":1,\"isOverlap\":true}}",
517
+                    "AdRawData": "",
518
+                    "BindIds": [],
519
+                    "GradeKey": "",
520
+                    "ComposerParams": "",
521
+                    "Panel": "transitions",
522
+                    "ModelNames": "",
523
+                    "HintFile": {
524
+                        "Uri": "",
525
+                        "UrlList": []
526
+                    },
527
+                    "OriginalExtra": "",
528
+                    "NameTransKey": "",
529
+                    "HintTextTransKey": ""
530
+                },
531
+                {
532
+                    "EffectType": 0,
533
+                    "Source": 0,
534
+                    "IsFavorite": false,
535
+                    "Subtype": 0,
536
+                    "IsBusiness": false,
537
+                    "IsPoi": false,
538
+                    "SyncId": "4202515",
539
+                    "ResourceId": "6914112263645303303",
540
+                    "Channel": 1,
541
+                    "PublishStatus": 1,
542
+                    "Ptime": "1661354711000",
543
+                    "ChallengeId": "0",
544
+                    "HintFileFormat": 0,
545
+                    "IsEst": false,
546
+                    "AppID": 1059,
547
+                    "HasProfileInfo": false,
548
+                    "Name": "泛光",
549
+                    "Hint": "",
550
+                    "SdkVersion": "5.4.0",
551
+                    "AppVersion": "",
552
+                    "FileUrl": {
553
+                        "Uri": "86dc910df5096fb516e1ed38e33ce8b7",
554
+                        "UrlList": [
555
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/86dc910df5096fb516e1ed38e33ce8b7",
556
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/86dc910df5096fb516e1ed38e33ce8b7"
557
+                        ]
558
+                    },
559
+                    "IconUrl": {
560
+                        "Uri": "d5260cd2765c0b2774e01aa25f03951a",
561
+                        "UrlList": [
562
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/d5260cd2765c0b2774e01aa25f03951a",
563
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/d5260cd2765c0b2774e01aa25f03951a"
564
+                        ]
565
+                    },
566
+                    "Id": "86dc910df5096fb516e1ed38e33ce8b7",
567
+                    "EffectId": "4202527",
568
+                    "DevicePlatform": "all",
569
+                    "Types": [
570
+                        "GeneralEffect"
571
+                    ],
572
+                    "Tags": [],
573
+                    "TagsUpdatedAt": "1661195086000",
574
+                    "Parent": "",
575
+                    "Children": [],
576
+                    "HintIcon": {
577
+                        "Uri": "",
578
+                        "UrlList": []
579
+                    },
580
+                    "Music": [],
581
+                    "DesignerId": "",
582
+                    "Schema": "",
583
+                    "Description": "",
584
+                    "OriginalEffectId": "",
585
+                    "Requirements": [],
586
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"6758fb789bf3848453dc0b553de6f966\",\"is_business\":true}",
587
+                    "Countrys": [],
588
+                    "PoiId": "0",
589
+                    "DesignerEncryptedId": "",
590
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":1,\"isOverlap\":true}}",
591
+                    "AdRawData": "",
592
+                    "BindIds": [],
593
+                    "GradeKey": "",
594
+                    "ComposerParams": "",
595
+                    "Panel": "transitions",
596
+                    "ModelNames": "",
597
+                    "HintFile": {
598
+                        "Uri": "",
599
+                        "UrlList": []
600
+                    },
601
+                    "OriginalExtra": "",
602
+                    "NameTransKey": "",
603
+                    "HintTextTransKey": ""
604
+                }
605
+            ],
606
+            "Collection": [],
607
+            "CategoryKey": "guangxiao123",
608
+            "BindEffects": []
609
+        }
610
+    },
611
+    "extra": {
612
+        "RecId": "20240615163921EAAC65C43E9F810A2A10"
613
+    },
614
+    "BaseResp": {
615
+        "StatusMessage": "success",
616
+        "StatusCode": 0
617
+    }
618
+}

+ 692 - 0
src/nodeapi/drafts/data/zhuanchang/guzhang123.json

@@ -0,0 +1,692 @@
1
+{
2
+    "data": {
3
+        "UrlPrefix": [
4
+            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/",
5
+            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/"
6
+        ],
7
+        "CategoryEffects": {
8
+            "HasMore": false,
9
+            "Cursor": 9,
10
+            "SortingPosition": 9,
11
+            "Version": "1022431250055,1017465960208,900,0",
12
+            "Effects": [
13
+                {
14
+                    "EffectType": 0,
15
+                    "Source": 0,
16
+                    "IsFavorite": false,
17
+                    "Subtype": 0,
18
+                    "IsBusiness": false,
19
+                    "IsPoi": false,
20
+                    "SyncId": "2918067",
21
+                    "ResourceId": "6724239785205961228",
22
+                    "Channel": 1,
23
+                    "PublishStatus": 1,
24
+                    "Ptime": "1655219414000",
25
+                    "ChallengeId": "0",
26
+                    "HintFileFormat": 0,
27
+                    "IsEst": false,
28
+                    "AppID": 1059,
29
+                    "HasProfileInfo": false,
30
+                    "Name": "色差故障",
31
+                    "Hint": "",
32
+                    "SdkVersion": "4.0.0",
33
+                    "AppVersion": "",
34
+                    "FileUrl": {
35
+                        "Uri": "ddad7bbd02f1e7ede39595e236b566e1",
36
+                        "UrlList": [
37
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/ddad7bbd02f1e7ede39595e236b566e1",
38
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/ddad7bbd02f1e7ede39595e236b566e1"
39
+                        ]
40
+                    },
41
+                    "IconUrl": {
42
+                        "Uri": "7df618bcf391aefc84ad14e4b801825b",
43
+                        "UrlList": [
44
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/7df618bcf391aefc84ad14e4b801825b",
45
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/7df618bcf391aefc84ad14e4b801825b"
46
+                        ]
47
+                    },
48
+                    "Id": "ddad7bbd02f1e7ede39595e236b566e1",
49
+                    "EffectId": "2918075",
50
+                    "DevicePlatform": "all",
51
+                    "Types": [
52
+                        "GeneralEffect"
53
+                    ],
54
+                    "Tags": [],
55
+                    "TagsUpdatedAt": "1655218449000",
56
+                    "Parent": "",
57
+                    "Children": [],
58
+                    "HintIcon": {
59
+                        "Uri": "",
60
+                        "UrlList": []
61
+                    },
62
+                    "Music": [],
63
+                    "DesignerId": "",
64
+                    "Schema": "",
65
+                    "Description": "",
66
+                    "OriginalEffectId": "",
67
+                    "Requirements": [],
68
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"b90aab2a2827c2498827bd05108e0a87\",\"is_business\":true,\"is_vip\":true}",
69
+                    "Countrys": [],
70
+                    "PoiId": "0",
71
+                    "DesignerEncryptedId": "",
72
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":1,\"isOverlap\":false}}",
73
+                    "AdRawData": "",
74
+                    "BindIds": [],
75
+                    "GradeKey": "",
76
+                    "ComposerParams": "",
77
+                    "Panel": "transitions",
78
+                    "ModelNames": "",
79
+                    "HintFile": {
80
+                        "Uri": "",
81
+                        "UrlList": []
82
+                    },
83
+                    "OriginalExtra": "",
84
+                    "NameTransKey": "",
85
+                    "HintTextTransKey": ""
86
+                },
87
+                {
88
+                    "EffectType": 0,
89
+                    "Source": 0,
90
+                    "IsFavorite": false,
91
+                    "Subtype": 0,
92
+                    "IsBusiness": false,
93
+                    "IsPoi": false,
94
+                    "SyncId": "2918068",
95
+                    "ResourceId": "6724845810892149251",
96
+                    "Channel": 1,
97
+                    "PublishStatus": 1,
98
+                    "Ptime": "1655219414000",
99
+                    "ChallengeId": "0",
100
+                    "HintFileFormat": 0,
101
+                    "IsEst": false,
102
+                    "AppID": 1059,
103
+                    "HasProfileInfo": false,
104
+                    "Name": "横线",
105
+                    "Hint": "",
106
+                    "SdkVersion": "5.0.0",
107
+                    "AppVersion": "",
108
+                    "FileUrl": {
109
+                        "Uri": "49a39e27ac133f8c7944b1fa3e113657",
110
+                        "UrlList": [
111
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/49a39e27ac133f8c7944b1fa3e113657",
112
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/49a39e27ac133f8c7944b1fa3e113657"
113
+                        ]
114
+                    },
115
+                    "IconUrl": {
116
+                        "Uri": "38b1c88b6fb4f08701e8e330261bdebe",
117
+                        "UrlList": [
118
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/38b1c88b6fb4f08701e8e330261bdebe",
119
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/38b1c88b6fb4f08701e8e330261bdebe"
120
+                        ]
121
+                    },
122
+                    "Id": "49a39e27ac133f8c7944b1fa3e113657",
123
+                    "EffectId": "2918076",
124
+                    "DevicePlatform": "all",
125
+                    "Types": [
126
+                        "GeneralEffect"
127
+                    ],
128
+                    "Tags": [],
129
+                    "TagsUpdatedAt": "1655218449000",
130
+                    "Parent": "",
131
+                    "Children": [],
132
+                    "HintIcon": {
133
+                        "Uri": "",
134
+                        "UrlList": []
135
+                    },
136
+                    "Music": [],
137
+                    "DesignerId": "",
138
+                    "Schema": "",
139
+                    "Description": "",
140
+                    "OriginalEffectId": "",
141
+                    "Requirements": [],
142
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"32b96f595fcdacf006239496394a6227\",\"is_business\":true}",
143
+                    "Countrys": [],
144
+                    "PoiId": "0",
145
+                    "DesignerEncryptedId": "",
146
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
147
+                    "AdRawData": "",
148
+                    "BindIds": [],
149
+                    "GradeKey": "",
150
+                    "ComposerParams": "",
151
+                    "Panel": "transitions",
152
+                    "ModelNames": "",
153
+                    "HintFile": {
154
+                        "Uri": "",
155
+                        "UrlList": []
156
+                    },
157
+                    "OriginalExtra": "",
158
+                    "NameTransKey": "",
159
+                    "HintTextTransKey": ""
160
+                },
161
+                {
162
+                    "EffectType": 0,
163
+                    "Source": 0,
164
+                    "IsFavorite": false,
165
+                    "Subtype": 0,
166
+                    "IsBusiness": false,
167
+                    "IsPoi": false,
168
+                    "SyncId": "2918069",
169
+                    "ResourceId": "6724846536041173511",
170
+                    "Channel": 1,
171
+                    "PublishStatus": 1,
172
+                    "Ptime": "1655219414000",
173
+                    "ChallengeId": "0",
174
+                    "HintFileFormat": 0,
175
+                    "IsEst": false,
176
+                    "AppID": 1059,
177
+                    "HasProfileInfo": false,
178
+                    "Name": "竖线",
179
+                    "Hint": "",
180
+                    "SdkVersion": "5.0.0",
181
+                    "AppVersion": "",
182
+                    "FileUrl": {
183
+                        "Uri": "986891ba759e39181ed0ee258ee5d995",
184
+                        "UrlList": [
185
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/986891ba759e39181ed0ee258ee5d995",
186
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/986891ba759e39181ed0ee258ee5d995"
187
+                        ]
188
+                    },
189
+                    "IconUrl": {
190
+                        "Uri": "aab089221979eefac4781ddf8f82814c",
191
+                        "UrlList": [
192
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/aab089221979eefac4781ddf8f82814c",
193
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/aab089221979eefac4781ddf8f82814c"
194
+                        ]
195
+                    },
196
+                    "Id": "986891ba759e39181ed0ee258ee5d995",
197
+                    "EffectId": "2918077",
198
+                    "DevicePlatform": "all",
199
+                    "Types": [
200
+                        "GeneralEffect"
201
+                    ],
202
+                    "Tags": [],
203
+                    "TagsUpdatedAt": "1655218449000",
204
+                    "Parent": "",
205
+                    "Children": [],
206
+                    "HintIcon": {
207
+                        "Uri": "",
208
+                        "UrlList": []
209
+                    },
210
+                    "Music": [],
211
+                    "DesignerId": "",
212
+                    "Schema": "",
213
+                    "Description": "",
214
+                    "OriginalEffectId": "",
215
+                    "Requirements": [],
216
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"0d3ed7ff9d5f02e2e556b490effcddd5\",\"is_business\":true}",
217
+                    "Countrys": [],
218
+                    "PoiId": "0",
219
+                    "DesignerEncryptedId": "",
220
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
221
+                    "AdRawData": "",
222
+                    "BindIds": [],
223
+                    "GradeKey": "",
224
+                    "ComposerParams": "",
225
+                    "Panel": "transitions",
226
+                    "ModelNames": "",
227
+                    "HintFile": {
228
+                        "Uri": "",
229
+                        "UrlList": []
230
+                    },
231
+                    "OriginalExtra": "",
232
+                    "NameTransKey": "",
233
+                    "HintTextTransKey": ""
234
+                },
235
+                {
236
+                    "EffectType": 0,
237
+                    "Source": 0,
238
+                    "IsFavorite": false,
239
+                    "Subtype": 0,
240
+                    "IsBusiness": false,
241
+                    "IsPoi": false,
242
+                    "SyncId": "2918070",
243
+                    "ResourceId": "6724866346569437710",
244
+                    "Channel": 1,
245
+                    "PublishStatus": 1,
246
+                    "Ptime": "1655219414000",
247
+                    "ChallengeId": "0",
248
+                    "HintFileFormat": 0,
249
+                    "IsEst": false,
250
+                    "AppID": 1059,
251
+                    "HasProfileInfo": false,
252
+                    "Name": "黑色块",
253
+                    "Hint": "",
254
+                    "SdkVersion": "5.0.0",
255
+                    "AppVersion": "",
256
+                    "FileUrl": {
257
+                        "Uri": "5396fcb569cdefd35b367c2a11650169",
258
+                        "UrlList": [
259
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/5396fcb569cdefd35b367c2a11650169",
260
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/5396fcb569cdefd35b367c2a11650169"
261
+                        ]
262
+                    },
263
+                    "IconUrl": {
264
+                        "Uri": "5e0ef5d7f19f8885abc430653506f6ac",
265
+                        "UrlList": [
266
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/5e0ef5d7f19f8885abc430653506f6ac",
267
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/5e0ef5d7f19f8885abc430653506f6ac"
268
+                        ]
269
+                    },
270
+                    "Id": "5396fcb569cdefd35b367c2a11650169",
271
+                    "EffectId": "2918078",
272
+                    "DevicePlatform": "all",
273
+                    "Types": [
274
+                        "GeneralEffect"
275
+                    ],
276
+                    "Tags": [],
277
+                    "TagsUpdatedAt": "1655218449000",
278
+                    "Parent": "",
279
+                    "Children": [],
280
+                    "HintIcon": {
281
+                        "Uri": "",
282
+                        "UrlList": []
283
+                    },
284
+                    "Music": [],
285
+                    "DesignerId": "",
286
+                    "Schema": "",
287
+                    "Description": "",
288
+                    "OriginalEffectId": "",
289
+                    "Requirements": [],
290
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"3c6da8b4de7ec4fc1efb15c0d3587d82\",\"is_business\":true}",
291
+                    "Countrys": [],
292
+                    "PoiId": "0",
293
+                    "DesignerEncryptedId": "",
294
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
295
+                    "AdRawData": "",
296
+                    "BindIds": [],
297
+                    "GradeKey": "",
298
+                    "ComposerParams": "",
299
+                    "Panel": "transitions",
300
+                    "ModelNames": "",
301
+                    "HintFile": {
302
+                        "Uri": "",
303
+                        "UrlList": []
304
+                    },
305
+                    "OriginalExtra": "",
306
+                    "NameTransKey": "",
307
+                    "HintTextTransKey": ""
308
+                },
309
+                {
310
+                    "EffectType": 0,
311
+                    "Source": 0,
312
+                    "IsFavorite": false,
313
+                    "Subtype": 0,
314
+                    "IsBusiness": false,
315
+                    "IsPoi": false,
316
+                    "SyncId": "2918072",
317
+                    "ResourceId": "6725771847444468236",
318
+                    "Channel": 1,
319
+                    "PublishStatus": 1,
320
+                    "Ptime": "1655219414000",
321
+                    "ChallengeId": "0",
322
+                    "HintFileFormat": 0,
323
+                    "IsEst": false,
324
+                    "AppID": 1059,
325
+                    "HasProfileInfo": false,
326
+                    "Name": "故障",
327
+                    "Hint": "",
328
+                    "SdkVersion": "5.0.0",
329
+                    "AppVersion": "",
330
+                    "FileUrl": {
331
+                        "Uri": "4dffd6b3102caa2977906ca1f2b0d832",
332
+                        "UrlList": [
333
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/4dffd6b3102caa2977906ca1f2b0d832",
334
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/4dffd6b3102caa2977906ca1f2b0d832"
335
+                        ]
336
+                    },
337
+                    "IconUrl": {
338
+                        "Uri": "ebb5229e00687d9f2162415056ca7815",
339
+                        "UrlList": [
340
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/ebb5229e00687d9f2162415056ca7815",
341
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/ebb5229e00687d9f2162415056ca7815"
342
+                        ]
343
+                    },
344
+                    "Id": "4dffd6b3102caa2977906ca1f2b0d832",
345
+                    "EffectId": "2918080",
346
+                    "DevicePlatform": "all",
347
+                    "Types": [
348
+                        "GeneralEffect"
349
+                    ],
350
+                    "Tags": [],
351
+                    "TagsUpdatedAt": "1655218449000",
352
+                    "Parent": "",
353
+                    "Children": [],
354
+                    "HintIcon": {
355
+                        "Uri": "",
356
+                        "UrlList": []
357
+                    },
358
+                    "Music": [],
359
+                    "DesignerId": "",
360
+                    "Schema": "",
361
+                    "Description": "",
362
+                    "OriginalEffectId": "",
363
+                    "Requirements": [],
364
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"78bf61fbf86dd76f93f29f2ea4c1cd51\",\"is_business\":true}",
365
+                    "Countrys": [],
366
+                    "PoiId": "0",
367
+                    "DesignerEncryptedId": "",
368
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":1,\"isOverlap\":false}}",
369
+                    "AdRawData": "",
370
+                    "BindIds": [],
371
+                    "GradeKey": "",
372
+                    "ComposerParams": "",
373
+                    "Panel": "transitions",
374
+                    "ModelNames": "",
375
+                    "HintFile": {
376
+                        "Uri": "",
377
+                        "UrlList": []
378
+                    },
379
+                    "OriginalExtra": "",
380
+                    "NameTransKey": "",
381
+                    "HintTextTransKey": ""
382
+                },
383
+                {
384
+                    "EffectType": 0,
385
+                    "Source": 0,
386
+                    "IsFavorite": false,
387
+                    "Subtype": 0,
388
+                    "IsBusiness": false,
389
+                    "IsPoi": false,
390
+                    "SyncId": "2918071",
391
+                    "ResourceId": "6724866446842663431",
392
+                    "Channel": 1,
393
+                    "PublishStatus": 1,
394
+                    "Ptime": "1655219414000",
395
+                    "ChallengeId": "0",
396
+                    "HintFileFormat": 0,
397
+                    "IsEst": false,
398
+                    "AppID": 1059,
399
+                    "HasProfileInfo": false,
400
+                    "Name": "雪花故障",
401
+                    "Hint": "",
402
+                    "SdkVersion": "5.0.0",
403
+                    "AppVersion": "",
404
+                    "FileUrl": {
405
+                        "Uri": "02553952dc0daaf5d3c47fcc00fb68bb",
406
+                        "UrlList": [
407
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/02553952dc0daaf5d3c47fcc00fb68bb",
408
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/02553952dc0daaf5d3c47fcc00fb68bb"
409
+                        ]
410
+                    },
411
+                    "IconUrl": {
412
+                        "Uri": "1882c34f9f4daa78fb432ef59049da56",
413
+                        "UrlList": [
414
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/1882c34f9f4daa78fb432ef59049da56",
415
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/1882c34f9f4daa78fb432ef59049da56"
416
+                        ]
417
+                    },
418
+                    "Id": "02553952dc0daaf5d3c47fcc00fb68bb",
419
+                    "EffectId": "2918079",
420
+                    "DevicePlatform": "all",
421
+                    "Types": [
422
+                        "GeneralEffect"
423
+                    ],
424
+                    "Tags": [],
425
+                    "TagsUpdatedAt": "1655218449000",
426
+                    "Parent": "",
427
+                    "Children": [],
428
+                    "HintIcon": {
429
+                        "Uri": "",
430
+                        "UrlList": []
431
+                    },
432
+                    "Music": [],
433
+                    "DesignerId": "",
434
+                    "Schema": "",
435
+                    "Description": "",
436
+                    "OriginalEffectId": "",
437
+                    "Requirements": [],
438
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"32b96f595fcdacf006239496394a6227\",\"is_business\":true}",
439
+                    "Countrys": [],
440
+                    "PoiId": "0",
441
+                    "DesignerEncryptedId": "",
442
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":1,\"isOverlap\":false}}",
443
+                    "AdRawData": "",
444
+                    "BindIds": [],
445
+                    "GradeKey": "",
446
+                    "ComposerParams": "",
447
+                    "Panel": "transitions",
448
+                    "ModelNames": "",
449
+                    "HintFile": {
450
+                        "Uri": "",
451
+                        "UrlList": []
452
+                    },
453
+                    "OriginalExtra": "",
454
+                    "NameTransKey": "",
455
+                    "HintTextTransKey": ""
456
+                },
457
+                {
458
+                    "EffectType": 0,
459
+                    "Source": 0,
460
+                    "IsFavorite": false,
461
+                    "Subtype": 0,
462
+                    "IsBusiness": false,
463
+                    "IsPoi": false,
464
+                    "SyncId": "2918073",
465
+                    "ResourceId": "7046293801123451405",
466
+                    "Channel": 1,
467
+                    "PublishStatus": 1,
468
+                    "Ptime": "1655219414000",
469
+                    "ChallengeId": "0",
470
+                    "HintFileFormat": 0,
471
+                    "IsEst": false,
472
+                    "AppID": 1059,
473
+                    "HasProfileInfo": false,
474
+                    "Name": "电视故障 I",
475
+                    "Hint": "",
476
+                    "SdkVersion": "5.5.0",
477
+                    "AppVersion": "",
478
+                    "FileUrl": {
479
+                        "Uri": "259244a924c123eb7aab3ebe8119f21b",
480
+                        "UrlList": [
481
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/259244a924c123eb7aab3ebe8119f21b",
482
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/259244a924c123eb7aab3ebe8119f21b"
483
+                        ]
484
+                    },
485
+                    "IconUrl": {
486
+                        "Uri": "61558200f2e008661823f0e220d3dc16",
487
+                        "UrlList": [
488
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/61558200f2e008661823f0e220d3dc16",
489
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/61558200f2e008661823f0e220d3dc16"
490
+                        ]
491
+                    },
492
+                    "Id": "259244a924c123eb7aab3ebe8119f21b",
493
+                    "EffectId": "2918081",
494
+                    "DevicePlatform": "all",
495
+                    "Types": [
496
+                        "GeneralEffect"
497
+                    ],
498
+                    "Tags": [],
499
+                    "TagsUpdatedAt": "1655218449000",
500
+                    "Parent": "",
501
+                    "Children": [],
502
+                    "HintIcon": {
503
+                        "Uri": "",
504
+                        "UrlList": []
505
+                    },
506
+                    "Music": [],
507
+                    "DesignerId": "",
508
+                    "Schema": "",
509
+                    "Description": "",
510
+                    "OriginalEffectId": "",
511
+                    "Requirements": [],
512
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"64c2dc42600d46f4dfa2393c0cd1f35a\",\"is_business\":true}",
513
+                    "Countrys": [],
514
+                    "PoiId": "0",
515
+                    "DesignerEncryptedId": "",
516
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":1.6,\"isOverlap\":true}}",
517
+                    "AdRawData": "",
518
+                    "BindIds": [],
519
+                    "GradeKey": "",
520
+                    "ComposerParams": "",
521
+                    "Panel": "transitions",
522
+                    "ModelNames": "",
523
+                    "HintFile": {
524
+                        "Uri": "",
525
+                        "UrlList": []
526
+                    },
527
+                    "OriginalExtra": "",
528
+                    "NameTransKey": "",
529
+                    "HintTextTransKey": ""
530
+                },
531
+                {
532
+                    "EffectType": 0,
533
+                    "Source": 0,
534
+                    "IsFavorite": false,
535
+                    "Subtype": 0,
536
+                    "IsBusiness": false,
537
+                    "IsPoi": false,
538
+                    "SyncId": "2918074",
539
+                    "ResourceId": "7042278078415901192",
540
+                    "Channel": 1,
541
+                    "PublishStatus": 1,
542
+                    "Ptime": "1655219415000",
543
+                    "ChallengeId": "0",
544
+                    "HintFileFormat": 0,
545
+                    "IsEst": false,
546
+                    "AppID": 1059,
547
+                    "HasProfileInfo": false,
548
+                    "Name": "电视故障 II",
549
+                    "Hint": "",
550
+                    "SdkVersion": "5.5.0",
551
+                    "AppVersion": "",
552
+                    "FileUrl": {
553
+                        "Uri": "b068ddb9f393191716d5057b1f3435a0",
554
+                        "UrlList": [
555
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/b068ddb9f393191716d5057b1f3435a0",
556
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/b068ddb9f393191716d5057b1f3435a0"
557
+                        ]
558
+                    },
559
+                    "IconUrl": {
560
+                        "Uri": "2f995b8891e26abe17cfa3c462269c58",
561
+                        "UrlList": [
562
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/2f995b8891e26abe17cfa3c462269c58",
563
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/2f995b8891e26abe17cfa3c462269c58"
564
+                        ]
565
+                    },
566
+                    "Id": "b068ddb9f393191716d5057b1f3435a0",
567
+                    "EffectId": "2918082",
568
+                    "DevicePlatform": "all",
569
+                    "Types": [
570
+                        "GeneralEffect"
571
+                    ],
572
+                    "Tags": [],
573
+                    "TagsUpdatedAt": "1655218449000",
574
+                    "Parent": "",
575
+                    "Children": [],
576
+                    "HintIcon": {
577
+                        "Uri": "",
578
+                        "UrlList": []
579
+                    },
580
+                    "Music": [],
581
+                    "DesignerId": "",
582
+                    "Schema": "",
583
+                    "Description": "",
584
+                    "OriginalEffectId": "",
585
+                    "Requirements": [],
586
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"8a8ca180d03faa4e21549c3eff7fef2d\",\"is_business\":true}",
587
+                    "Countrys": [],
588
+                    "PoiId": "0",
589
+                    "DesignerEncryptedId": "",
590
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":1.6,\"isOverlap\":true}}",
591
+                    "AdRawData": "",
592
+                    "BindIds": [],
593
+                    "GradeKey": "",
594
+                    "ComposerParams": "",
595
+                    "Panel": "transitions",
596
+                    "ModelNames": "",
597
+                    "HintFile": {
598
+                        "Uri": "",
599
+                        "UrlList": []
600
+                    },
601
+                    "OriginalExtra": "",
602
+                    "NameTransKey": "",
603
+                    "HintTextTransKey": ""
604
+                },
605
+                {
606
+                    "EffectType": 0,
607
+                    "Source": 0,
608
+                    "IsFavorite": false,
609
+                    "Subtype": 0,
610
+                    "IsBusiness": false,
611
+                    "IsPoi": false,
612
+                    "SyncId": "1674709",
613
+                    "ResourceId": "7083767957662208549",
614
+                    "Channel": 1,
615
+                    "PublishStatus": 1,
616
+                    "Ptime": "1655304546000",
617
+                    "ChallengeId": "0",
618
+                    "HintFileFormat": 0,
619
+                    "IsEst": false,
620
+                    "AppID": 1059,
621
+                    "HasProfileInfo": false,
622
+                    "Name": "频闪",
623
+                    "Hint": "",
624
+                    "SdkVersion": "5.4.0",
625
+                    "AppVersion": "",
626
+                    "FileUrl": {
627
+                        "Uri": "e856343892be60e9189673899fd7feaa",
628
+                        "UrlList": [
629
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/e856343892be60e9189673899fd7feaa",
630
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/e856343892be60e9189673899fd7feaa"
631
+                        ]
632
+                    },
633
+                    "IconUrl": {
634
+                        "Uri": "9bd2111d3c3d1d550f269885154067d5",
635
+                        "UrlList": [
636
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/9bd2111d3c3d1d550f269885154067d5",
637
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/9bd2111d3c3d1d550f269885154067d5"
638
+                        ]
639
+                    },
640
+                    "Id": "e856343892be60e9189673899fd7feaa",
641
+                    "EffectId": "1674710",
642
+                    "DevicePlatform": "all",
643
+                    "Types": [
644
+                        "GeneralEffect"
645
+                    ],
646
+                    "Tags": [],
647
+                    "TagsUpdatedAt": "1649347093000",
648
+                    "Parent": "",
649
+                    "Children": [],
650
+                    "HintIcon": {
651
+                        "Uri": "",
652
+                        "UrlList": []
653
+                    },
654
+                    "Music": [],
655
+                    "DesignerId": "",
656
+                    "Schema": "",
657
+                    "Description": "",
658
+                    "OriginalEffectId": "",
659
+                    "Requirements": [],
660
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"37136f111a9faaf150de9c2b0d0df92d\",\"is_business\":true}",
661
+                    "Countrys": [],
662
+                    "PoiId": "0",
663
+                    "DesignerEncryptedId": "",
664
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
665
+                    "AdRawData": "",
666
+                    "BindIds": [],
667
+                    "GradeKey": "",
668
+                    "ComposerParams": "",
669
+                    "Panel": "transitions",
670
+                    "ModelNames": "",
671
+                    "HintFile": {
672
+                        "Uri": "",
673
+                        "UrlList": []
674
+                    },
675
+                    "OriginalExtra": "",
676
+                    "NameTransKey": "",
677
+                    "HintTextTransKey": ""
678
+                }
679
+            ],
680
+            "Collection": [],
681
+            "CategoryKey": "guzhang123",
682
+            "BindEffects": []
683
+        }
684
+    },
685
+    "extra": {
686
+        "RecId": "2024061516403187028D919307CC0A40CD"
687
+    },
688
+    "BaseResp": {
689
+        "StatusMessage": "success",
690
+        "StatusCode": 0
691
+    }
692
+}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1795 - 0
src/nodeapi/drafts/data/zhuanchang/hot.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 2331 - 0
src/nodeapi/drafts/data/zhuanchang/huandengpian123.json


+ 248 - 0
src/nodeapi/drafts/data/zhuanchang/hudongemoji123.json

@@ -0,0 +1,248 @@
1
+{
2
+    "data": {
3
+        "UrlPrefix": [
4
+            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/",
5
+            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/"
6
+        ],
7
+        "CategoryEffects": {
8
+            "HasMore": false,
9
+            "Cursor": 3,
10
+            "SortingPosition": 3,
11
+            "Version": "1755172427816,1446651601718,900,0",
12
+            "Effects": [
13
+                {
14
+                    "EffectType": 0,
15
+                    "Source": 0,
16
+                    "IsFavorite": false,
17
+                    "Subtype": 0,
18
+                    "IsBusiness": false,
19
+                    "IsPoi": false,
20
+                    "SyncId": "1598383",
21
+                    "ResourceId": "7070047850960261668",
22
+                    "Channel": 1,
23
+                    "PublishStatus": 1,
24
+                    "Ptime": "1653647824000",
25
+                    "ChallengeId": "0",
26
+                    "HintFileFormat": 0,
27
+                    "IsEst": false,
28
+                    "AppID": 1059,
29
+                    "HasProfileInfo": false,
30
+                    "Name": "摄像机",
31
+                    "Hint": "",
32
+                    "SdkVersion": "5.4.0",
33
+                    "AppVersion": "",
34
+                    "FileUrl": {
35
+                        "Uri": "320392c9acdfd520144c01c684b9cd86",
36
+                        "UrlList": [
37
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/320392c9acdfd520144c01c684b9cd86",
38
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/320392c9acdfd520144c01c684b9cd86"
39
+                        ]
40
+                    },
41
+                    "IconUrl": {
42
+                        "Uri": "ed7c0aba7e899e9599b7b4492eea4a6c",
43
+                        "UrlList": [
44
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/ed7c0aba7e899e9599b7b4492eea4a6c",
45
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/ed7c0aba7e899e9599b7b4492eea4a6c"
46
+                        ]
47
+                    },
48
+                    "Id": "320392c9acdfd520144c01c684b9cd86",
49
+                    "EffectId": "1598384",
50
+                    "DevicePlatform": "all",
51
+                    "Types": [
52
+                        "GeneralEffect"
53
+                    ],
54
+                    "Tags": [],
55
+                    "TagsUpdatedAt": "1646152613000",
56
+                    "Parent": "",
57
+                    "Children": [],
58
+                    "HintIcon": {
59
+                        "Uri": "",
60
+                        "UrlList": []
61
+                    },
62
+                    "Music": [],
63
+                    "DesignerId": "",
64
+                    "Schema": "",
65
+                    "Description": "",
66
+                    "OriginalEffectId": "",
67
+                    "Requirements": [],
68
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"06fc2747a06c6cbe7b325505f5575d31\",\"is_business\":true,\"is_vip\":true}",
69
+                    "Countrys": [],
70
+                    "PoiId": "0",
71
+                    "DesignerEncryptedId": "",
72
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
73
+                    "AdRawData": "",
74
+                    "BindIds": [],
75
+                    "GradeKey": "",
76
+                    "ComposerParams": "",
77
+                    "Panel": "transitions",
78
+                    "ModelNames": "",
79
+                    "HintFile": {
80
+                        "Uri": "",
81
+                        "UrlList": []
82
+                    },
83
+                    "OriginalExtra": "",
84
+                    "NameTransKey": "",
85
+                    "HintTextTransKey": ""
86
+                },
87
+                {
88
+                    "EffectType": 0,
89
+                    "Source": 0,
90
+                    "IsFavorite": false,
91
+                    "Subtype": 0,
92
+                    "IsBusiness": false,
93
+                    "IsPoi": false,
94
+                    "SyncId": "1600474",
95
+                    "ResourceId": "7070430644563612191",
96
+                    "Channel": 1,
97
+                    "PublishStatus": 1,
98
+                    "Ptime": "1653647825000",
99
+                    "ChallengeId": "0",
100
+                    "HintFileFormat": 0,
101
+                    "IsEst": false,
102
+                    "AppID": 1059,
103
+                    "HasProfileInfo": false,
104
+                    "Name": "喜欢",
105
+                    "Hint": "",
106
+                    "SdkVersion": "5.4.0",
107
+                    "AppVersion": "",
108
+                    "FileUrl": {
109
+                        "Uri": "bb6531e024e85ea6217703b52d781418",
110
+                        "UrlList": [
111
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/bb6531e024e85ea6217703b52d781418",
112
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/bb6531e024e85ea6217703b52d781418"
113
+                        ]
114
+                    },
115
+                    "IconUrl": {
116
+                        "Uri": "67b649809db06fa4c1ee2b078601cc70",
117
+                        "UrlList": [
118
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/67b649809db06fa4c1ee2b078601cc70",
119
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/67b649809db06fa4c1ee2b078601cc70"
120
+                        ]
121
+                    },
122
+                    "Id": "bb6531e024e85ea6217703b52d781418",
123
+                    "EffectId": "1600478",
124
+                    "DevicePlatform": "all",
125
+                    "Types": [
126
+                        "GeneralEffect"
127
+                    ],
128
+                    "Tags": [],
129
+                    "TagsUpdatedAt": "1646241819000",
130
+                    "Parent": "",
131
+                    "Children": [],
132
+                    "HintIcon": {
133
+                        "Uri": "",
134
+                        "UrlList": []
135
+                    },
136
+                    "Music": [],
137
+                    "DesignerId": "",
138
+                    "Schema": "",
139
+                    "Description": "",
140
+                    "OriginalEffectId": "",
141
+                    "Requirements": [],
142
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"2db1effebf1e71d2eea662de603cc7ec\",\"is_business\":true,\"is_vip\":true}",
143
+                    "Countrys": [],
144
+                    "PoiId": "0",
145
+                    "DesignerEncryptedId": "",
146
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
147
+                    "AdRawData": "",
148
+                    "BindIds": [],
149
+                    "GradeKey": "",
150
+                    "ComposerParams": "",
151
+                    "Panel": "transitions",
152
+                    "ModelNames": "",
153
+                    "HintFile": {
154
+                        "Uri": "",
155
+                        "UrlList": []
156
+                    },
157
+                    "OriginalExtra": "",
158
+                    "NameTransKey": "",
159
+                    "HintTextTransKey": ""
160
+                },
161
+                {
162
+                    "EffectType": 0,
163
+                    "Source": 0,
164
+                    "IsFavorite": false,
165
+                    "Subtype": 0,
166
+                    "IsBusiness": false,
167
+                    "IsPoi": false,
168
+                    "SyncId": "1632989",
169
+                    "ResourceId": "7076321483282190878",
170
+                    "Channel": 1,
171
+                    "PublishStatus": 1,
172
+                    "Ptime": "1653647825000",
173
+                    "ChallengeId": "0",
174
+                    "HintFileFormat": 0,
175
+                    "IsEst": false,
176
+                    "AppID": 1059,
177
+                    "HasProfileInfo": false,
178
+                    "Name": "炸弹",
179
+                    "Hint": "",
180
+                    "SdkVersion": "5.4.0",
181
+                    "AppVersion": "",
182
+                    "FileUrl": {
183
+                        "Uri": "4055079ccf525cc8d89b6eaac3639872",
184
+                        "UrlList": [
185
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/4055079ccf525cc8d89b6eaac3639872",
186
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/4055079ccf525cc8d89b6eaac3639872"
187
+                        ]
188
+                    },
189
+                    "IconUrl": {
190
+                        "Uri": "747b49fe1b6aefcf96eb42264672123e",
191
+                        "UrlList": [
192
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/747b49fe1b6aefcf96eb42264672123e",
193
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/747b49fe1b6aefcf96eb42264672123e"
194
+                        ]
195
+                    },
196
+                    "Id": "4055079ccf525cc8d89b6eaac3639872",
197
+                    "EffectId": "1632990",
198
+                    "DevicePlatform": "all",
199
+                    "Types": [
200
+                        "GeneralEffect"
201
+                    ],
202
+                    "Tags": [],
203
+                    "TagsUpdatedAt": "1647613308000",
204
+                    "Parent": "",
205
+                    "Children": [],
206
+                    "HintIcon": {
207
+                        "Uri": "",
208
+                        "UrlList": []
209
+                    },
210
+                    "Music": [],
211
+                    "DesignerId": "",
212
+                    "Schema": "",
213
+                    "Description": "",
214
+                    "OriginalEffectId": "",
215
+                    "Requirements": [],
216
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"96d742be0106499fed4b7c317b5de78f\",\"is_business\":true,\"is_vip\":true}",
217
+                    "Countrys": [],
218
+                    "PoiId": "0",
219
+                    "DesignerEncryptedId": "",
220
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
221
+                    "AdRawData": "",
222
+                    "BindIds": [],
223
+                    "GradeKey": "",
224
+                    "ComposerParams": "",
225
+                    "Panel": "transitions",
226
+                    "ModelNames": "",
227
+                    "HintFile": {
228
+                        "Uri": "",
229
+                        "UrlList": []
230
+                    },
231
+                    "OriginalExtra": "",
232
+                    "NameTransKey": "",
233
+                    "HintTextTransKey": ""
234
+                }
235
+            ],
236
+            "Collection": [],
237
+            "CategoryKey": "hudongemoji123",
238
+            "BindEffects": []
239
+        }
240
+    },
241
+    "extra": {
242
+        "RecId": "2024061516443374DDEECC16D584085DFF"
243
+    },
244
+    "BaseResp": {
245
+        "StatusMessage": "success",
246
+        "StatusCode": 0
247
+    }
248
+}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1136 - 0
src/nodeapi/drafts/data/zhuanchang/mgdonghua123.json


+ 628 - 0
src/nodeapi/drafts/data/zhuanchang/mohu123.json

@@ -0,0 +1,628 @@
1
+{
2
+    "data": {
3
+        "UrlPrefix": [
4
+            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/",
5
+            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/"
6
+        ],
7
+        "CategoryEffects": {
8
+            "HasMore": false,
9
+            "Cursor": 8,
10
+            "SortingPosition": 8,
11
+            "Version": "1278947246232,1476806022885,900,0",
12
+            "Effects": [
13
+                {
14
+                    "EffectType": 0,
15
+                    "Source": 0,
16
+                    "IsFavorite": false,
17
+                    "Subtype": 0,
18
+                    "IsBusiness": false,
19
+                    "IsPoi": false,
20
+                    "SyncId": "3705756",
21
+                    "ResourceId": "7123135366504124936",
22
+                    "Channel": 1,
23
+                    "PublishStatus": 1,
24
+                    "Ptime": "1661354124000",
25
+                    "ChallengeId": "0",
26
+                    "HintFileFormat": 0,
27
+                    "IsEst": false,
28
+                    "AppID": 1059,
29
+                    "HasProfileInfo": false,
30
+                    "Name": "亮点模糊",
31
+                    "Hint": "",
32
+                    "SdkVersion": "9.5.0",
33
+                    "AppVersion": "",
34
+                    "FileUrl": {
35
+                        "Uri": "a6a8a1177e31b78fd7a809df6f363f45",
36
+                        "UrlList": [
37
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/a6a8a1177e31b78fd7a809df6f363f45",
38
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/a6a8a1177e31b78fd7a809df6f363f45"
39
+                        ]
40
+                    },
41
+                    "IconUrl": {
42
+                        "Uri": "3dad8000208a4660fb96817fccc9a6e0",
43
+                        "UrlList": [
44
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/3dad8000208a4660fb96817fccc9a6e0",
45
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/3dad8000208a4660fb96817fccc9a6e0"
46
+                        ]
47
+                    },
48
+                    "Id": "a6a8a1177e31b78fd7a809df6f363f45",
49
+                    "EffectId": "3705757",
50
+                    "DevicePlatform": "all",
51
+                    "Types": [
52
+                        "GeneralEffect"
53
+                    ],
54
+                    "Tags": [],
55
+                    "TagsUpdatedAt": "1658513004000",
56
+                    "Parent": "",
57
+                    "Children": [],
58
+                    "HintIcon": {
59
+                        "Uri": "",
60
+                        "UrlList": []
61
+                    },
62
+                    "Music": [],
63
+                    "DesignerId": "",
64
+                    "Schema": "",
65
+                    "Description": "",
66
+                    "OriginalEffectId": "",
67
+                    "Requirements": [],
68
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"42bb01e58e579e69d218b69896caf1fd\",\"is_business\":true,\"is_vip\":true}",
69
+                    "Countrys": [],
70
+                    "PoiId": "0",
71
+                    "DesignerEncryptedId": "",
72
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":1,\"isOverlap\":true}}",
73
+                    "AdRawData": "",
74
+                    "BindIds": [],
75
+                    "GradeKey": "",
76
+                    "ComposerParams": "",
77
+                    "Panel": "transitions",
78
+                    "ModelNames": "",
79
+                    "HintFile": {
80
+                        "Uri": "",
81
+                        "UrlList": []
82
+                    },
83
+                    "OriginalExtra": "",
84
+                    "NameTransKey": "",
85
+                    "HintTextTransKey": ""
86
+                },
87
+                {
88
+                    "EffectType": 0,
89
+                    "Source": 0,
90
+                    "IsFavorite": false,
91
+                    "Subtype": 0,
92
+                    "IsBusiness": false,
93
+                    "IsPoi": false,
94
+                    "SyncId": "4212627",
95
+                    "ResourceId": "6724239584663704071",
96
+                    "Channel": 1,
97
+                    "PublishStatus": 1,
98
+                    "Ptime": "1661354651000",
99
+                    "ChallengeId": "0",
100
+                    "HintFileFormat": 0,
101
+                    "IsEst": false,
102
+                    "AppID": 1059,
103
+                    "HasProfileInfo": false,
104
+                    "Name": "放射",
105
+                    "Hint": "",
106
+                    "SdkVersion": "4.0.0",
107
+                    "AppVersion": "",
108
+                    "FileUrl": {
109
+                        "Uri": "86908340d6f4fda7a0b8a2047bbf198b",
110
+                        "UrlList": [
111
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/86908340d6f4fda7a0b8a2047bbf198b",
112
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/86908340d6f4fda7a0b8a2047bbf198b"
113
+                        ]
114
+                    },
115
+                    "IconUrl": {
116
+                        "Uri": "240c61768168b7fd5f3b3e592162e9d6",
117
+                        "UrlList": [
118
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/240c61768168b7fd5f3b3e592162e9d6",
119
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/240c61768168b7fd5f3b3e592162e9d6"
120
+                        ]
121
+                    },
122
+                    "Id": "86908340d6f4fda7a0b8a2047bbf198b",
123
+                    "EffectId": "4212630",
124
+                    "DevicePlatform": "all",
125
+                    "Types": [
126
+                        "GeneralEffect"
127
+                    ],
128
+                    "Tags": [],
129
+                    "TagsUpdatedAt": "1661261828000",
130
+                    "Parent": "",
131
+                    "Children": [],
132
+                    "HintIcon": {
133
+                        "Uri": "",
134
+                        "UrlList": []
135
+                    },
136
+                    "Music": [],
137
+                    "DesignerId": "",
138
+                    "Schema": "",
139
+                    "Description": "",
140
+                    "OriginalEffectId": "",
141
+                    "Requirements": [],
142
+                    "Extra": "{\"hover_icon\":\"7f53bb68d0fda423acba6a8d3e52b222\",\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
143
+                    "Countrys": [],
144
+                    "PoiId": "0",
145
+                    "DesignerEncryptedId": "",
146
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":1,\"isOverlap\":true}}",
147
+                    "AdRawData": "",
148
+                    "BindIds": [],
149
+                    "GradeKey": "",
150
+                    "ComposerParams": "",
151
+                    "Panel": "transitions",
152
+                    "ModelNames": "",
153
+                    "HintFile": {
154
+                        "Uri": "",
155
+                        "UrlList": []
156
+                    },
157
+                    "OriginalExtra": "",
158
+                    "NameTransKey": "",
159
+                    "HintTextTransKey": ""
160
+                },
161
+                {
162
+                    "EffectType": 0,
163
+                    "Source": 0,
164
+                    "IsFavorite": false,
165
+                    "Subtype": 0,
166
+                    "IsBusiness": false,
167
+                    "IsPoi": false,
168
+                    "SyncId": "4212595",
169
+                    "ResourceId": "6911569618171597320",
170
+                    "Channel": 1,
171
+                    "PublishStatus": 1,
172
+                    "Ptime": "1661354651000",
173
+                    "ChallengeId": "0",
174
+                    "HintFileFormat": 0,
175
+                    "IsEst": false,
176
+                    "AppID": 1059,
177
+                    "HasProfileInfo": false,
178
+                    "Name": "模糊",
179
+                    "Hint": "",
180
+                    "SdkVersion": "5.4.0",
181
+                    "AppVersion": "",
182
+                    "FileUrl": {
183
+                        "Uri": "3cddea2d9586e92c266ce9b832434f2e",
184
+                        "UrlList": [
185
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/3cddea2d9586e92c266ce9b832434f2e",
186
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/3cddea2d9586e92c266ce9b832434f2e"
187
+                        ]
188
+                    },
189
+                    "IconUrl": {
190
+                        "Uri": "48fb363795ca28c04a443e55b5afe5e2",
191
+                        "UrlList": [
192
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/48fb363795ca28c04a443e55b5afe5e2",
193
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/48fb363795ca28c04a443e55b5afe5e2"
194
+                        ]
195
+                    },
196
+                    "Id": "3cddea2d9586e92c266ce9b832434f2e",
197
+                    "EffectId": "4212596",
198
+                    "DevicePlatform": "all",
199
+                    "Types": [
200
+                        "GeneralEffect"
201
+                    ],
202
+                    "Tags": [],
203
+                    "TagsUpdatedAt": "1661261685000",
204
+                    "Parent": "",
205
+                    "Children": [],
206
+                    "HintIcon": {
207
+                        "Uri": "",
208
+                        "UrlList": []
209
+                    },
210
+                    "Music": [],
211
+                    "DesignerId": "",
212
+                    "Schema": "",
213
+                    "Description": "",
214
+                    "OriginalEffectId": "",
215
+                    "Requirements": [],
216
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"eb4d6b7fcbe4247252869b34b18b0b89\",\"is_business\":true}",
217
+                    "Countrys": [],
218
+                    "PoiId": "0",
219
+                    "DesignerEncryptedId": "",
220
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
221
+                    "AdRawData": "",
222
+                    "BindIds": [],
223
+                    "GradeKey": "",
224
+                    "ComposerParams": "",
225
+                    "Panel": "transitions",
226
+                    "ModelNames": "",
227
+                    "HintFile": {
228
+                        "Uri": "",
229
+                        "UrlList": []
230
+                    },
231
+                    "OriginalExtra": "",
232
+                    "NameTransKey": "",
233
+                    "HintTextTransKey": ""
234
+                },
235
+                {
236
+                    "EffectType": 0,
237
+                    "Source": 0,
238
+                    "IsFavorite": false,
239
+                    "Subtype": 0,
240
+                    "IsBusiness": false,
241
+                    "IsPoi": false,
242
+                    "SyncId": "4212629",
243
+                    "ResourceId": "6855565313715474952",
244
+                    "Channel": 1,
245
+                    "PublishStatus": 1,
246
+                    "Ptime": "1661354651000",
247
+                    "ChallengeId": "0",
248
+                    "HintFileFormat": 0,
249
+                    "IsEst": false,
250
+                    "AppID": 1059,
251
+                    "HasProfileInfo": false,
252
+                    "Name": "粒子",
253
+                    "Hint": "",
254
+                    "SdkVersion": "4.0.0",
255
+                    "AppVersion": "",
256
+                    "FileUrl": {
257
+                        "Uri": "aee4d12355ad33c08fbcdfd74d2558c7",
258
+                        "UrlList": [
259
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/aee4d12355ad33c08fbcdfd74d2558c7",
260
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/aee4d12355ad33c08fbcdfd74d2558c7"
261
+                        ]
262
+                    },
263
+                    "IconUrl": {
264
+                        "Uri": "5b42846e2c5b1f95d98c0d7ab4b62549",
265
+                        "UrlList": [
266
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/5b42846e2c5b1f95d98c0d7ab4b62549",
267
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/5b42846e2c5b1f95d98c0d7ab4b62549"
268
+                        ]
269
+                    },
270
+                    "Id": "aee4d12355ad33c08fbcdfd74d2558c7",
271
+                    "EffectId": "4212632",
272
+                    "DevicePlatform": "all",
273
+                    "Types": [
274
+                        "GeneralEffect"
275
+                    ],
276
+                    "Tags": [],
277
+                    "TagsUpdatedAt": "1661261828000",
278
+                    "Parent": "",
279
+                    "Children": [],
280
+                    "HintIcon": {
281
+                        "Uri": "",
282
+                        "UrlList": []
283
+                    },
284
+                    "Music": [],
285
+                    "DesignerId": "",
286
+                    "Schema": "",
287
+                    "Description": "",
288
+                    "OriginalEffectId": "",
289
+                    "Requirements": [],
290
+                    "Extra": "{\"hover_icon\":\"d2f0bef84d18acccf929e5e78e1e1d74\",\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
291
+                    "Countrys": [],
292
+                    "PoiId": "0",
293
+                    "DesignerEncryptedId": "",
294
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
295
+                    "AdRawData": "",
296
+                    "BindIds": [],
297
+                    "GradeKey": "",
298
+                    "ComposerParams": "",
299
+                    "Panel": "transitions",
300
+                    "ModelNames": "",
301
+                    "HintFile": {
302
+                        "Uri": "",
303
+                        "UrlList": []
304
+                    },
305
+                    "OriginalExtra": "",
306
+                    "NameTransKey": "",
307
+                    "HintTextTransKey": ""
308
+                },
309
+                {
310
+                    "EffectType": 0,
311
+                    "Source": 0,
312
+                    "IsFavorite": false,
313
+                    "Subtype": 0,
314
+                    "IsBusiness": false,
315
+                    "IsPoi": false,
316
+                    "SyncId": "11286536",
317
+                    "ResourceId": "7215424325036282428",
318
+                    "Channel": 1,
319
+                    "PublishStatus": 1,
320
+                    "Ptime": "1680200068000",
321
+                    "ChallengeId": "0",
322
+                    "HintFileFormat": 0,
323
+                    "IsEst": false,
324
+                    "AppID": 1059,
325
+                    "HasProfileInfo": false,
326
+                    "Name": "旋焦",
327
+                    "Hint": "",
328
+                    "SdkVersion": "12.3.0",
329
+                    "AppVersion": "",
330
+                    "FileUrl": {
331
+                        "Uri": "528dad02f17f7bb90cebc1234d5cbd92",
332
+                        "UrlList": [
333
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/528dad02f17f7bb90cebc1234d5cbd92",
334
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/528dad02f17f7bb90cebc1234d5cbd92"
335
+                        ]
336
+                    },
337
+                    "IconUrl": {
338
+                        "Uri": "81dd7b6ced8f13ac7faa1948eebc9303",
339
+                        "UrlList": [
340
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/81dd7b6ced8f13ac7faa1948eebc9303",
341
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/81dd7b6ced8f13ac7faa1948eebc9303"
342
+                        ]
343
+                    },
344
+                    "Id": "528dad02f17f7bb90cebc1234d5cbd92",
345
+                    "EffectId": "11286537",
346
+                    "DevicePlatform": "all",
347
+                    "Types": [
348
+                        "GeneralEffect"
349
+                    ],
350
+                    "Tags": [],
351
+                    "TagsUpdatedAt": "",
352
+                    "Parent": "",
353
+                    "Children": [],
354
+                    "HintIcon": {
355
+                        "Uri": "",
356
+                        "UrlList": []
357
+                    },
358
+                    "Music": [],
359
+                    "DesignerId": "",
360
+                    "Schema": "",
361
+                    "Description": "",
362
+                    "OriginalEffectId": "",
363
+                    "Requirements": [],
364
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"8131e4b08285380a896f3d64aa2111fc\",\"is_business\":true,\"is_vip\":true}",
365
+                    "Countrys": [],
366
+                    "PoiId": "0",
367
+                    "DesignerEncryptedId": "",
368
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true},\"External_Producer\":true}",
369
+                    "AdRawData": "",
370
+                    "BindIds": [],
371
+                    "GradeKey": "",
372
+                    "ComposerParams": "",
373
+                    "Panel": "transitions",
374
+                    "ModelNames": "",
375
+                    "HintFile": {
376
+                        "Uri": "",
377
+                        "UrlList": []
378
+                    },
379
+                    "OriginalExtra": "",
380
+                    "NameTransKey": "",
381
+                    "HintTextTransKey": ""
382
+                },
383
+                {
384
+                    "EffectType": 0,
385
+                    "Source": 0,
386
+                    "IsFavorite": false,
387
+                    "Subtype": 0,
388
+                    "IsBusiness": false,
389
+                    "IsPoi": false,
390
+                    "SyncId": "3796326",
391
+                    "ResourceId": "7125661387568714247",
392
+                    "Channel": 1,
393
+                    "PublishStatus": 1,
394
+                    "Ptime": "1661354124000",
395
+                    "ChallengeId": "0",
396
+                    "HintFileFormat": 0,
397
+                    "IsEst": false,
398
+                    "AppID": 1059,
399
+                    "HasProfileInfo": false,
400
+                    "Name": "竖向模糊",
401
+                    "Hint": "",
402
+                    "SdkVersion": "10.5.0",
403
+                    "AppVersion": "",
404
+                    "FileUrl": {
405
+                        "Uri": "d7065829a5dbbbbb4785b359227c6193",
406
+                        "UrlList": [
407
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/d7065829a5dbbbbb4785b359227c6193",
408
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/d7065829a5dbbbbb4785b359227c6193"
409
+                        ]
410
+                    },
411
+                    "IconUrl": {
412
+                        "Uri": "80e2fa1e33dae7579e30d73cbc7924cc",
413
+                        "UrlList": [
414
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/80e2fa1e33dae7579e30d73cbc7924cc",
415
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/80e2fa1e33dae7579e30d73cbc7924cc"
416
+                        ]
417
+                    },
418
+                    "Id": "d7065829a5dbbbbb4785b359227c6193",
419
+                    "EffectId": "3796327",
420
+                    "DevicePlatform": "all",
421
+                    "Types": [
422
+                        "GeneralEffect"
423
+                    ],
424
+                    "Tags": [],
425
+                    "TagsUpdatedAt": "1659101137000",
426
+                    "Parent": "",
427
+                    "Children": [],
428
+                    "HintIcon": {
429
+                        "Uri": "",
430
+                        "UrlList": []
431
+                    },
432
+                    "Music": [],
433
+                    "DesignerId": "",
434
+                    "Schema": "",
435
+                    "Description": "",
436
+                    "OriginalEffectId": "",
437
+                    "Requirements": [],
438
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"2468aaab3c33226a0e5b041d4815a570\",\"is_business\":true}",
439
+                    "Countrys": [],
440
+                    "PoiId": "0",
441
+                    "DesignerEncryptedId": "",
442
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.8,\"isOverlap\":true}}",
443
+                    "AdRawData": "",
444
+                    "BindIds": [],
445
+                    "GradeKey": "",
446
+                    "ComposerParams": "",
447
+                    "Panel": "transitions",
448
+                    "ModelNames": "",
449
+                    "HintFile": {
450
+                        "Uri": "",
451
+                        "UrlList": []
452
+                    },
453
+                    "OriginalExtra": "",
454
+                    "NameTransKey": "",
455
+                    "HintTextTransKey": ""
456
+                },
457
+                {
458
+                    "EffectType": 0,
459
+                    "Source": 0,
460
+                    "IsFavorite": false,
461
+                    "Subtype": 0,
462
+                    "IsBusiness": false,
463
+                    "IsPoi": false,
464
+                    "SyncId": "4212628",
465
+                    "ResourceId": "6724866519022440967",
466
+                    "Channel": 1,
467
+                    "PublishStatus": 1,
468
+                    "Ptime": "1661354651000",
469
+                    "ChallengeId": "0",
470
+                    "HintFileFormat": 0,
471
+                    "IsEst": false,
472
+                    "AppID": 1059,
473
+                    "HasProfileInfo": false,
474
+                    "Name": "马赛克",
475
+                    "Hint": "",
476
+                    "SdkVersion": "5.0.0",
477
+                    "AppVersion": "",
478
+                    "FileUrl": {
479
+                        "Uri": "c3089a1e96112be103367439d98b0744",
480
+                        "UrlList": [
481
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c3089a1e96112be103367439d98b0744",
482
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c3089a1e96112be103367439d98b0744"
483
+                        ]
484
+                    },
485
+                    "IconUrl": {
486
+                        "Uri": "76797218d3b6822b834244fead8cf84a",
487
+                        "UrlList": [
488
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/76797218d3b6822b834244fead8cf84a",
489
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/76797218d3b6822b834244fead8cf84a"
490
+                        ]
491
+                    },
492
+                    "Id": "c3089a1e96112be103367439d98b0744",
493
+                    "EffectId": "4212631",
494
+                    "DevicePlatform": "all",
495
+                    "Types": [
496
+                        "GeneralEffect"
497
+                    ],
498
+                    "Tags": [],
499
+                    "TagsUpdatedAt": "1661261828000",
500
+                    "Parent": "",
501
+                    "Children": [],
502
+                    "HintIcon": {
503
+                        "Uri": "",
504
+                        "UrlList": []
505
+                    },
506
+                    "Music": [],
507
+                    "DesignerId": "",
508
+                    "Schema": "",
509
+                    "Description": "",
510
+                    "OriginalEffectId": "",
511
+                    "Requirements": [],
512
+                    "Extra": "{\"hover_icon\":\"30ee954da45d92e4d6a47bbe7e9082f2\",\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
513
+                    "Countrys": [],
514
+                    "PoiId": "0",
515
+                    "DesignerEncryptedId": "",
516
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":1,\"isOverlap\":true}}",
517
+                    "AdRawData": "",
518
+                    "BindIds": [],
519
+                    "GradeKey": "",
520
+                    "ComposerParams": "",
521
+                    "Panel": "transitions",
522
+                    "ModelNames": "",
523
+                    "HintFile": {
524
+                        "Uri": "",
525
+                        "UrlList": []
526
+                    },
527
+                    "OriginalExtra": "",
528
+                    "NameTransKey": "",
529
+                    "HintTextTransKey": ""
530
+                },
531
+                {
532
+                    "EffectType": 0,
533
+                    "Source": 0,
534
+                    "IsFavorite": false,
535
+                    "Subtype": 0,
536
+                    "IsBusiness": false,
537
+                    "IsPoi": false,
538
+                    "SyncId": "62284093",
539
+                    "ResourceId": "7366189026677625359",
540
+                    "Channel": 1,
541
+                    "PublishStatus": 1,
542
+                    "Ptime": "1715797274000",
543
+                    "ChallengeId": "0",
544
+                    "HintFileFormat": 0,
545
+                    "IsEst": false,
546
+                    "AppID": 1059,
547
+                    "HasProfileInfo": false,
548
+                    "Name": "烟雾弹",
549
+                    "Hint": "",
550
+                    "SdkVersion": "7.0.0",
551
+                    "AppVersion": "",
552
+                    "FileUrl": {
553
+                        "Uri": "58dced44162cefabdc709058b7583d65",
554
+                        "UrlList": [
555
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/58dced44162cefabdc709058b7583d65",
556
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/58dced44162cefabdc709058b7583d65"
557
+                        ]
558
+                    },
559
+                    "IconUrl": {
560
+                        "Uri": "b5e0f261814279245ac881852385bcee",
561
+                        "UrlList": [
562
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/b5e0f261814279245ac881852385bcee",
563
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/b5e0f261814279245ac881852385bcee"
564
+                        ]
565
+                    },
566
+                    "Id": "58dced44162cefabdc709058b7583d65",
567
+                    "EffectId": "62284094",
568
+                    "DevicePlatform": "all",
569
+                    "Types": [
570
+                        "AmazingFeature"
571
+                    ],
572
+                    "Tags": [],
573
+                    "TagsUpdatedAt": "1715103380000",
574
+                    "Parent": "",
575
+                    "Children": [],
576
+                    "HintIcon": {
577
+                        "Uri": "",
578
+                        "UrlList": []
579
+                    },
580
+                    "Music": [],
581
+                    "DesignerId": "",
582
+                    "Schema": "",
583
+                    "Description": "",
584
+                    "OriginalEffectId": "",
585
+                    "Requirements": [
586
+                        "blit"
587
+                    ],
588
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"f797e84d892091d71125d631cc442f86\",\"is_business\":true,\"is_vip\":true}",
589
+                    "Countrys": [],
590
+                    "PoiId": "0",
591
+                    "DesignerEncryptedId": "",
592
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":1.4,\"isOverlap\":true},\"setting\":{\"effect_adjust_params\":[{\"effect_key\":\"effects_adjust_blur\",\"default\":0.57,\"max\":1,\"min\":0}]}}",
593
+                    "AdRawData": "",
594
+                    "BindIds": [],
595
+                    "GradeKey": "",
596
+                    "ComposerParams": "",
597
+                    "Panel": "transitions",
598
+                    "ModelNames": "",
599
+                    "HintFile": {
600
+                        "Uri": "",
601
+                        "UrlList": []
602
+                    },
603
+                    "SystemList": [
604
+                        "BehaviorSystem",
605
+                        "CameraSystem",
606
+                        "EventSystem",
607
+                        "MeshRendererSystem",
608
+                        "ScriptSystem",
609
+                        "TransformSystem"
610
+                    ],
611
+                    "OriginalExtra": "",
612
+                    "NameTransKey": "",
613
+                    "HintTextTransKey": ""
614
+                }
615
+            ],
616
+            "Collection": [],
617
+            "CategoryKey": "mohu123",
618
+            "BindEffects": []
619
+        }
620
+    },
621
+    "extra": {
622
+        "RecId": "20240615163857AE1238574886430857F9"
623
+    },
624
+    "BaseResp": {
625
+        "StatusMessage": "success",
626
+        "StatusCode": 0
627
+    }
628
+}

+ 470 - 0
src/nodeapi/drafts/data/zhuanchang/niuqu123.json

@@ -0,0 +1,470 @@
1
+{
2
+    "data": {
3
+        "UrlPrefix": [
4
+            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/",
5
+            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/"
6
+        ],
7
+        "CategoryEffects": {
8
+            "HasMore": false,
9
+            "Cursor": 6,
10
+            "SortingPosition": 6,
11
+            "Version": "1398552155686,1393795925926,900,0",
12
+            "Effects": [
13
+                {
14
+                    "EffectType": 0,
15
+                    "Source": 0,
16
+                    "IsFavorite": false,
17
+                    "Subtype": 0,
18
+                    "IsBusiness": false,
19
+                    "IsPoi": false,
20
+                    "SyncId": "4211775",
21
+                    "ResourceId": "6851810799510360583",
22
+                    "Channel": 1,
23
+                    "PublishStatus": 1,
24
+                    "Ptime": "1661354682000",
25
+                    "ChallengeId": "0",
26
+                    "HintFileFormat": 0,
27
+                    "IsEst": false,
28
+                    "AppID": 1059,
29
+                    "HasProfileInfo": false,
30
+                    "Name": "漩涡",
31
+                    "Hint": "",
32
+                    "SdkVersion": "5.0.0",
33
+                    "AppVersion": "",
34
+                    "FileUrl": {
35
+                        "Uri": "de3ad6cc4ef56c78389cda2d638a7fc8",
36
+                        "UrlList": [
37
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/de3ad6cc4ef56c78389cda2d638a7fc8",
38
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/de3ad6cc4ef56c78389cda2d638a7fc8"
39
+                        ]
40
+                    },
41
+                    "IconUrl": {
42
+                        "Uri": "5fa519320f891d4b5766038d6ef0768a",
43
+                        "UrlList": [
44
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/5fa519320f891d4b5766038d6ef0768a",
45
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/5fa519320f891d4b5766038d6ef0768a"
46
+                        ]
47
+                    },
48
+                    "Id": "de3ad6cc4ef56c78389cda2d638a7fc8",
49
+                    "EffectId": "4211780",
50
+                    "DevicePlatform": "all",
51
+                    "Types": [
52
+                        "GeneralEffect"
53
+                    ],
54
+                    "Tags": [],
55
+                    "TagsUpdatedAt": "1661255630000",
56
+                    "Parent": "",
57
+                    "Children": [],
58
+                    "HintIcon": {
59
+                        "Uri": "",
60
+                        "UrlList": []
61
+                    },
62
+                    "Music": [],
63
+                    "DesignerId": "",
64
+                    "Schema": "",
65
+                    "Description": "",
66
+                    "OriginalEffectId": "",
67
+                    "Requirements": [],
68
+                    "Extra": "{\"hover_icon\":\"2f61368220e24d5ab8466362c6e08fe3\",\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
69
+                    "Countrys": [],
70
+                    "PoiId": "0",
71
+                    "DesignerEncryptedId": "",
72
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":1,\"isOverlap\":false}}",
73
+                    "AdRawData": "",
74
+                    "BindIds": [],
75
+                    "GradeKey": "",
76
+                    "ComposerParams": "",
77
+                    "Panel": "transitions",
78
+                    "ModelNames": "",
79
+                    "HintFile": {
80
+                        "Uri": "",
81
+                        "UrlList": []
82
+                    },
83
+                    "OriginalExtra": "",
84
+                    "NameTransKey": "",
85
+                    "HintTextTransKey": ""
86
+                },
87
+                {
88
+                    "EffectType": 0,
89
+                    "Source": 0,
90
+                    "IsFavorite": false,
91
+                    "Subtype": 0,
92
+                    "IsBusiness": false,
93
+                    "IsPoi": false,
94
+                    "SyncId": "4212465",
95
+                    "ResourceId": "6751618376780485133",
96
+                    "Channel": 1,
97
+                    "PublishStatus": 1,
98
+                    "Ptime": "1661354683000",
99
+                    "ChallengeId": "0",
100
+                    "HintFileFormat": 0,
101
+                    "IsEst": false,
102
+                    "AppID": 1059,
103
+                    "HasProfileInfo": false,
104
+                    "Name": "压缩",
105
+                    "Hint": "",
106
+                    "SdkVersion": "5.0.0",
107
+                    "AppVersion": "",
108
+                    "FileUrl": {
109
+                        "Uri": "c459e5d6cbf255afa209622939aaa9d3",
110
+                        "UrlList": [
111
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c459e5d6cbf255afa209622939aaa9d3",
112
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c459e5d6cbf255afa209622939aaa9d3"
113
+                        ]
114
+                    },
115
+                    "IconUrl": {
116
+                        "Uri": "1fb6da57acf014c47e1013b4bdc71c60",
117
+                        "UrlList": [
118
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/1fb6da57acf014c47e1013b4bdc71c60",
119
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/1fb6da57acf014c47e1013b4bdc71c60"
120
+                        ]
121
+                    },
122
+                    "Id": "c459e5d6cbf255afa209622939aaa9d3",
123
+                    "EffectId": "4212466",
124
+                    "DevicePlatform": "all",
125
+                    "Types": [
126
+                        "GeneralEffect"
127
+                    ],
128
+                    "Tags": [],
129
+                    "TagsUpdatedAt": "1661260950000",
130
+                    "Parent": "",
131
+                    "Children": [],
132
+                    "HintIcon": {
133
+                        "Uri": "",
134
+                        "UrlList": []
135
+                    },
136
+                    "Music": [],
137
+                    "DesignerId": "",
138
+                    "Schema": "",
139
+                    "Description": "",
140
+                    "OriginalEffectId": "",
141
+                    "Requirements": [],
142
+                    "Extra": "{\"hover_icon\":\"f254aae340e4be91f62d3b62d63d4c7e\",\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
143
+                    "Countrys": [],
144
+                    "PoiId": "0",
145
+                    "DesignerEncryptedId": "",
146
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
147
+                    "AdRawData": "",
148
+                    "BindIds": [],
149
+                    "GradeKey": "",
150
+                    "ComposerParams": "",
151
+                    "Panel": "transitions",
152
+                    "ModelNames": "",
153
+                    "HintFile": {
154
+                        "Uri": "",
155
+                        "UrlList": []
156
+                    },
157
+                    "OriginalExtra": "",
158
+                    "NameTransKey": "",
159
+                    "HintTextTransKey": ""
160
+                },
161
+                {
162
+                    "EffectType": 0,
163
+                    "Source": 0,
164
+                    "IsFavorite": false,
165
+                    "Subtype": 0,
166
+                    "IsBusiness": false,
167
+                    "IsPoi": false,
168
+                    "SyncId": "4211773",
169
+                    "ResourceId": "6748220149284737550",
170
+                    "Channel": 1,
171
+                    "PublishStatus": 1,
172
+                    "Ptime": "1661354682000",
173
+                    "ChallengeId": "0",
174
+                    "HintFileFormat": 0,
175
+                    "IsEst": false,
176
+                    "AppID": 1059,
177
+                    "HasProfileInfo": false,
178
+                    "Name": "回忆",
179
+                    "Hint": "",
180
+                    "SdkVersion": "5.0.0",
181
+                    "AppVersion": "",
182
+                    "FileUrl": {
183
+                        "Uri": "78d45fd1072079ff2b0db43047478472",
184
+                        "UrlList": [
185
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/78d45fd1072079ff2b0db43047478472",
186
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/78d45fd1072079ff2b0db43047478472"
187
+                        ]
188
+                    },
189
+                    "IconUrl": {
190
+                        "Uri": "e1f3294a54af1feb302930988532a525",
191
+                        "UrlList": [
192
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/e1f3294a54af1feb302930988532a525",
193
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/e1f3294a54af1feb302930988532a525"
194
+                        ]
195
+                    },
196
+                    "Id": "78d45fd1072079ff2b0db43047478472",
197
+                    "EffectId": "4211778",
198
+                    "DevicePlatform": "all",
199
+                    "Types": [
200
+                        "GeneralEffect"
201
+                    ],
202
+                    "Tags": [],
203
+                    "TagsUpdatedAt": "1661255630000",
204
+                    "Parent": "",
205
+                    "Children": [],
206
+                    "HintIcon": {
207
+                        "Uri": "",
208
+                        "UrlList": []
209
+                    },
210
+                    "Music": [],
211
+                    "DesignerId": "",
212
+                    "Schema": "",
213
+                    "Description": "",
214
+                    "OriginalEffectId": "",
215
+                    "Requirements": [],
216
+                    "Extra": "{\"hover_icon\":\"9aeee2df83fccbdb03ab75451cb0dd5f\",\"is_business\":true,\"is_vip\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
217
+                    "Countrys": [],
218
+                    "PoiId": "0",
219
+                    "DesignerEncryptedId": "",
220
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
221
+                    "AdRawData": "",
222
+                    "BindIds": [],
223
+                    "GradeKey": "",
224
+                    "ComposerParams": "",
225
+                    "Panel": "transitions",
226
+                    "ModelNames": "",
227
+                    "HintFile": {
228
+                        "Uri": "",
229
+                        "UrlList": []
230
+                    },
231
+                    "OriginalExtra": "",
232
+                    "NameTransKey": "",
233
+                    "HintTextTransKey": ""
234
+                },
235
+                {
236
+                    "EffectType": 0,
237
+                    "Source": 0,
238
+                    "IsFavorite": false,
239
+                    "Subtype": 0,
240
+                    "IsBusiness": false,
241
+                    "IsPoi": false,
242
+                    "SyncId": "4211774",
243
+                    "ResourceId": "6748220462746046989",
244
+                    "Channel": 1,
245
+                    "PublishStatus": 1,
246
+                    "Ptime": "1661354682000",
247
+                    "ChallengeId": "0",
248
+                    "HintFileFormat": 0,
249
+                    "IsEst": false,
250
+                    "AppID": 1059,
251
+                    "HasProfileInfo": false,
252
+                    "Name": "回忆 II",
253
+                    "Hint": "",
254
+                    "SdkVersion": "5.0.0",
255
+                    "AppVersion": "",
256
+                    "FileUrl": {
257
+                        "Uri": "163ee61b6c062785cb7a93517f448c03",
258
+                        "UrlList": [
259
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/163ee61b6c062785cb7a93517f448c03",
260
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/163ee61b6c062785cb7a93517f448c03"
261
+                        ]
262
+                    },
263
+                    "IconUrl": {
264
+                        "Uri": "e5bfae873ae9d44c59c1f1fe3f8397c8",
265
+                        "UrlList": [
266
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/e5bfae873ae9d44c59c1f1fe3f8397c8",
267
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/e5bfae873ae9d44c59c1f1fe3f8397c8"
268
+                        ]
269
+                    },
270
+                    "Id": "163ee61b6c062785cb7a93517f448c03",
271
+                    "EffectId": "4211779",
272
+                    "DevicePlatform": "all",
273
+                    "Types": [
274
+                        "GeneralEffect"
275
+                    ],
276
+                    "Tags": [],
277
+                    "TagsUpdatedAt": "1661255630000",
278
+                    "Parent": "",
279
+                    "Children": [],
280
+                    "HintIcon": {
281
+                        "Uri": "",
282
+                        "UrlList": []
283
+                    },
284
+                    "Music": [],
285
+                    "DesignerId": "",
286
+                    "Schema": "",
287
+                    "Description": "",
288
+                    "OriginalEffectId": "",
289
+                    "Requirements": [],
290
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"d446d172b5be7ae8cdeab63731043635\",\"is_business\":true,\"is_vip\":true}",
291
+                    "Countrys": [],
292
+                    "PoiId": "0",
293
+                    "DesignerEncryptedId": "",
294
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
295
+                    "AdRawData": "",
296
+                    "BindIds": [],
297
+                    "GradeKey": "",
298
+                    "ComposerParams": "",
299
+                    "Panel": "transitions",
300
+                    "ModelNames": "",
301
+                    "HintFile": {
302
+                        "Uri": "",
303
+                        "UrlList": []
304
+                    },
305
+                    "OriginalExtra": "",
306
+                    "NameTransKey": "",
307
+                    "HintTextTransKey": ""
308
+                },
309
+                {
310
+                    "EffectType": 0,
311
+                    "Source": 0,
312
+                    "IsFavorite": false,
313
+                    "Subtype": 0,
314
+                    "IsBusiness": false,
315
+                    "IsPoi": false,
316
+                    "SyncId": "4211776",
317
+                    "ResourceId": "6987201429622493732",
318
+                    "Channel": 1,
319
+                    "PublishStatus": 1,
320
+                    "Ptime": "1661354682000",
321
+                    "ChallengeId": "0",
322
+                    "HintFileFormat": 0,
323
+                    "IsEst": false,
324
+                    "AppID": 1059,
325
+                    "HasProfileInfo": false,
326
+                    "Name": "向左拉伸",
327
+                    "Hint": "",
328
+                    "SdkVersion": "5.4.0",
329
+                    "AppVersion": "",
330
+                    "FileUrl": {
331
+                        "Uri": "1c1de048a1c1a9b3d1b7cf8c8cba8152",
332
+                        "UrlList": [
333
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/1c1de048a1c1a9b3d1b7cf8c8cba8152",
334
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/1c1de048a1c1a9b3d1b7cf8c8cba8152"
335
+                        ]
336
+                    },
337
+                    "IconUrl": {
338
+                        "Uri": "0740e3d8265ee84835c05bd5bdf8a447",
339
+                        "UrlList": [
340
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/0740e3d8265ee84835c05bd5bdf8a447",
341
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/0740e3d8265ee84835c05bd5bdf8a447"
342
+                        ]
343
+                    },
344
+                    "Id": "1c1de048a1c1a9b3d1b7cf8c8cba8152",
345
+                    "EffectId": "4211781",
346
+                    "DevicePlatform": "all",
347
+                    "Types": [
348
+                        "GeneralEffect"
349
+                    ],
350
+                    "Tags": [],
351
+                    "TagsUpdatedAt": "1661255630000",
352
+                    "Parent": "",
353
+                    "Children": [],
354
+                    "HintIcon": {
355
+                        "Uri": "",
356
+                        "UrlList": []
357
+                    },
358
+                    "Music": [],
359
+                    "DesignerId": "",
360
+                    "Schema": "",
361
+                    "Description": "",
362
+                    "OriginalEffectId": "",
363
+                    "Requirements": [],
364
+                    "Extra": "{\"hover_icon\":\"ed0c57ffb8d1786d749af6fcaf398f73\",\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
365
+                    "Countrys": [],
366
+                    "PoiId": "0",
367
+                    "DesignerEncryptedId": "",
368
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
369
+                    "AdRawData": "",
370
+                    "BindIds": [],
371
+                    "GradeKey": "",
372
+                    "ComposerParams": "",
373
+                    "Panel": "transitions",
374
+                    "ModelNames": "",
375
+                    "HintFile": {
376
+                        "Uri": "",
377
+                        "UrlList": []
378
+                    },
379
+                    "OriginalExtra": "",
380
+                    "NameTransKey": "",
381
+                    "HintTextTransKey": ""
382
+                },
383
+                {
384
+                    "EffectType": 0,
385
+                    "Source": 0,
386
+                    "IsFavorite": false,
387
+                    "Subtype": 0,
388
+                    "IsBusiness": false,
389
+                    "IsPoi": false,
390
+                    "SyncId": "4211777",
391
+                    "ResourceId": "6987299127025472031",
392
+                    "Channel": 1,
393
+                    "PublishStatus": 1,
394
+                    "Ptime": "1661354682000",
395
+                    "ChallengeId": "0",
396
+                    "HintFileFormat": 0,
397
+                    "IsEst": false,
398
+                    "AppID": 1059,
399
+                    "HasProfileInfo": false,
400
+                    "Name": "向右拉伸",
401
+                    "Hint": "",
402
+                    "SdkVersion": "5.4.0",
403
+                    "AppVersion": "",
404
+                    "FileUrl": {
405
+                        "Uri": "eaa581df273e8da0852e17e5d9581d7c",
406
+                        "UrlList": [
407
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/eaa581df273e8da0852e17e5d9581d7c",
408
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/eaa581df273e8da0852e17e5d9581d7c"
409
+                        ]
410
+                    },
411
+                    "IconUrl": {
412
+                        "Uri": "ffd771c9444ad405b950152a113c50b5",
413
+                        "UrlList": [
414
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/ffd771c9444ad405b950152a113c50b5",
415
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/ffd771c9444ad405b950152a113c50b5"
416
+                        ]
417
+                    },
418
+                    "Id": "eaa581df273e8da0852e17e5d9581d7c",
419
+                    "EffectId": "4211782",
420
+                    "DevicePlatform": "all",
421
+                    "Types": [
422
+                        "GeneralEffect"
423
+                    ],
424
+                    "Tags": [],
425
+                    "TagsUpdatedAt": "1661255630000",
426
+                    "Parent": "",
427
+                    "Children": [],
428
+                    "HintIcon": {
429
+                        "Uri": "",
430
+                        "UrlList": []
431
+                    },
432
+                    "Music": [],
433
+                    "DesignerId": "",
434
+                    "Schema": "",
435
+                    "Description": "",
436
+                    "OriginalEffectId": "",
437
+                    "Requirements": [],
438
+                    "Extra": "{\"hover_icon\":\"373a017b014ba360c4db45e65b46a9a8\",\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
439
+                    "Countrys": [],
440
+                    "PoiId": "0",
441
+                    "DesignerEncryptedId": "",
442
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
443
+                    "AdRawData": "",
444
+                    "BindIds": [],
445
+                    "GradeKey": "",
446
+                    "ComposerParams": "",
447
+                    "Panel": "transitions",
448
+                    "ModelNames": "",
449
+                    "HintFile": {
450
+                        "Uri": "",
451
+                        "UrlList": []
452
+                    },
453
+                    "OriginalExtra": "",
454
+                    "NameTransKey": "",
455
+                    "HintTextTransKey": ""
456
+                }
457
+            ],
458
+            "Collection": [],
459
+            "CategoryKey": "niuqu123",
460
+            "BindEffects": []
461
+        }
462
+    },
463
+    "extra": {
464
+        "RecId": "202406151640105F838781246C610A2651"
465
+    },
466
+    "BaseResp": {
467
+        "StatusMessage": "success",
468
+        "StatusCode": 0
469
+    }
470
+}

+ 396 - 0
src/nodeapi/drafts/data/zhuanchang/paishe123.json

@@ -0,0 +1,396 @@
1
+{
2
+    "data": {
3
+        "UrlPrefix": [
4
+            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/",
5
+            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/"
6
+        ],
7
+        "CategoryEffects": {
8
+            "HasMore": false,
9
+            "Cursor": 5,
10
+            "SortingPosition": 5,
11
+            "Version": "1422595692358,1478663655370,900,0",
12
+            "Effects": [
13
+                {
14
+                    "EffectType": 0,
15
+                    "Source": 0,
16
+                    "IsFavorite": false,
17
+                    "Subtype": 0,
18
+                    "IsBusiness": false,
19
+                    "IsPoi": false,
20
+                    "SyncId": "2057167",
21
+                    "ResourceId": "7100849808784495135",
22
+                    "Channel": 1,
23
+                    "PublishStatus": 1,
24
+                    "Ptime": "1655304786000",
25
+                    "ChallengeId": "0",
26
+                    "HintFileFormat": 0,
27
+                    "IsEst": false,
28
+                    "AppID": 1059,
29
+                    "HasProfileInfo": false,
30
+                    "Name": "拍摄器",
31
+                    "Hint": "",
32
+                    "SdkVersion": "9.5.0",
33
+                    "AppVersion": "",
34
+                    "FileUrl": {
35
+                        "Uri": "b0c8792ecd832ebafcb0187b382a8104",
36
+                        "UrlList": [
37
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/b0c8792ecd832ebafcb0187b382a8104",
38
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/b0c8792ecd832ebafcb0187b382a8104"
39
+                        ]
40
+                    },
41
+                    "IconUrl": {
42
+                        "Uri": "09fcbedba214eb4fe0e5ccf8c1b30ddb",
43
+                        "UrlList": [
44
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/09fcbedba214eb4fe0e5ccf8c1b30ddb",
45
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/09fcbedba214eb4fe0e5ccf8c1b30ddb"
46
+                        ]
47
+                    },
48
+                    "Id": "b0c8792ecd832ebafcb0187b382a8104",
49
+                    "EffectId": "2057168",
50
+                    "DevicePlatform": "all",
51
+                    "Types": [
52
+                        "GeneralEffect"
53
+                    ],
54
+                    "Tags": [],
55
+                    "TagsUpdatedAt": "1653324236000",
56
+                    "Parent": "",
57
+                    "Children": [],
58
+                    "HintIcon": {
59
+                        "Uri": "",
60
+                        "UrlList": []
61
+                    },
62
+                    "Music": [],
63
+                    "DesignerId": "",
64
+                    "Schema": "",
65
+                    "Description": "",
66
+                    "OriginalEffectId": "",
67
+                    "Requirements": [],
68
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"19d2387dc7da97fc42a7ac500a37de1e\",\"is_business\":true}",
69
+                    "Countrys": [],
70
+                    "PoiId": "0",
71
+                    "DesignerEncryptedId": "",
72
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
73
+                    "AdRawData": "",
74
+                    "BindIds": [],
75
+                    "GradeKey": "",
76
+                    "ComposerParams": "",
77
+                    "Panel": "transitions",
78
+                    "ModelNames": "",
79
+                    "HintFile": {
80
+                        "Uri": "",
81
+                        "UrlList": []
82
+                    },
83
+                    "OriginalExtra": "",
84
+                    "NameTransKey": "",
85
+                    "HintTextTransKey": ""
86
+                },
87
+                {
88
+                    "EffectType": 0,
89
+                    "Source": 0,
90
+                    "IsFavorite": false,
91
+                    "Subtype": 0,
92
+                    "IsBusiness": false,
93
+                    "IsPoi": false,
94
+                    "SyncId": "2917717",
95
+                    "ResourceId": "6864867302936941064",
96
+                    "Channel": 1,
97
+                    "PublishStatus": 1,
98
+                    "Ptime": "1655218199000",
99
+                    "ChallengeId": "0",
100
+                    "HintFileFormat": 0,
101
+                    "IsEst": false,
102
+                    "AppID": 1059,
103
+                    "HasProfileInfo": false,
104
+                    "Name": "眨眼",
105
+                    "Hint": "",
106
+                    "SdkVersion": "5.4.0",
107
+                    "AppVersion": "",
108
+                    "FileUrl": {
109
+                        "Uri": "d9c964bf87b25739b274dc6b5849754d",
110
+                        "UrlList": [
111
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/d9c964bf87b25739b274dc6b5849754d",
112
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/d9c964bf87b25739b274dc6b5849754d"
113
+                        ]
114
+                    },
115
+                    "IconUrl": {
116
+                        "Uri": "110d1c31750574cae58987cbc39104b1",
117
+                        "UrlList": [
118
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/110d1c31750574cae58987cbc39104b1",
119
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/110d1c31750574cae58987cbc39104b1"
120
+                        ]
121
+                    },
122
+                    "Id": "d9c964bf87b25739b274dc6b5849754d",
123
+                    "EffectId": "2917719",
124
+                    "DevicePlatform": "all",
125
+                    "Types": [
126
+                        "GeneralEffect"
127
+                    ],
128
+                    "Tags": [],
129
+                    "TagsUpdatedAt": "1655217800000",
130
+                    "Parent": "",
131
+                    "Children": [],
132
+                    "HintIcon": {
133
+                        "Uri": "",
134
+                        "UrlList": []
135
+                    },
136
+                    "Music": [],
137
+                    "DesignerId": "",
138
+                    "Schema": "",
139
+                    "Description": "",
140
+                    "OriginalEffectId": "",
141
+                    "Requirements": [],
142
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"8a34d05668da81f85e451ed44cbb8bcf\",\"is_business\":true}",
143
+                    "Countrys": [],
144
+                    "PoiId": "0",
145
+                    "DesignerEncryptedId": "",
146
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
147
+                    "AdRawData": "",
148
+                    "BindIds": [],
149
+                    "GradeKey": "",
150
+                    "ComposerParams": "",
151
+                    "Panel": "transitions",
152
+                    "ModelNames": "",
153
+                    "HintFile": {
154
+                        "Uri": "",
155
+                        "UrlList": []
156
+                    },
157
+                    "OriginalExtra": "",
158
+                    "NameTransKey": "",
159
+                    "HintTextTransKey": ""
160
+                },
161
+                {
162
+                    "EffectType": 0,
163
+                    "Source": 0,
164
+                    "IsFavorite": false,
165
+                    "Subtype": 0,
166
+                    "IsBusiness": false,
167
+                    "IsPoi": false,
168
+                    "SyncId": "2459633",
169
+                    "ResourceId": "7104215831919202853",
170
+                    "Channel": 1,
171
+                    "PublishStatus": 1,
172
+                    "Ptime": "1655304786000",
173
+                    "ChallengeId": "0",
174
+                    "HintFileFormat": 0,
175
+                    "IsEst": false,
176
+                    "AppID": 1059,
177
+                    "HasProfileInfo": false,
178
+                    "Name": "抽象前景",
179
+                    "Hint": "",
180
+                    "SdkVersion": "9.5.0",
181
+                    "AppVersion": "",
182
+                    "FileUrl": {
183
+                        "Uri": "c09a89aba9c9b3b760103fb121702e75",
184
+                        "UrlList": [
185
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c09a89aba9c9b3b760103fb121702e75",
186
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c09a89aba9c9b3b760103fb121702e75"
187
+                        ]
188
+                    },
189
+                    "IconUrl": {
190
+                        "Uri": "8641f221e7fa8a9a42159dc40f32ea35",
191
+                        "UrlList": [
192
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/8641f221e7fa8a9a42159dc40f32ea35",
193
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/8641f221e7fa8a9a42159dc40f32ea35"
194
+                        ]
195
+                    },
196
+                    "Id": "c09a89aba9c9b3b760103fb121702e75",
197
+                    "EffectId": "2459634",
198
+                    "DevicePlatform": "all",
199
+                    "Types": [
200
+                        "GeneralEffect"
201
+                    ],
202
+                    "Tags": [],
203
+                    "TagsUpdatedAt": "1654107950000",
204
+                    "Parent": "",
205
+                    "Children": [],
206
+                    "HintIcon": {
207
+                        "Uri": "",
208
+                        "UrlList": []
209
+                    },
210
+                    "Music": [],
211
+                    "DesignerId": "",
212
+                    "Schema": "",
213
+                    "Description": "",
214
+                    "OriginalEffectId": "",
215
+                    "Requirements": [],
216
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"200fdda38e7fd6651db946a8456af82b\",\"is_business\":true,\"is_vip\":true}",
217
+                    "Countrys": [],
218
+                    "PoiId": "0",
219
+                    "DesignerEncryptedId": "",
220
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
221
+                    "AdRawData": "",
222
+                    "BindIds": [],
223
+                    "GradeKey": "",
224
+                    "ComposerParams": "",
225
+                    "Panel": "transitions",
226
+                    "ModelNames": "",
227
+                    "HintFile": {
228
+                        "Uri": "",
229
+                        "UrlList": []
230
+                    },
231
+                    "OriginalExtra": "",
232
+                    "NameTransKey": "",
233
+                    "HintTextTransKey": ""
234
+                },
235
+                {
236
+                    "EffectType": 0,
237
+                    "Source": 0,
238
+                    "IsFavorite": false,
239
+                    "Subtype": 0,
240
+                    "IsBusiness": false,
241
+                    "IsPoi": false,
242
+                    "SyncId": "2870169",
243
+                    "ResourceId": "7108564115529929229",
244
+                    "Channel": 1,
245
+                    "PublishStatus": 1,
246
+                    "Ptime": "1655304786000",
247
+                    "ChallengeId": "0",
248
+                    "HintFileFormat": 0,
249
+                    "IsEst": false,
250
+                    "AppID": 1059,
251
+                    "HasProfileInfo": false,
252
+                    "Name": "抽象前景 II",
253
+                    "Hint": "",
254
+                    "SdkVersion": "9.5.0",
255
+                    "AppVersion": "",
256
+                    "FileUrl": {
257
+                        "Uri": "30d658ef2de4c2a98b8b81520fddd77f",
258
+                        "UrlList": [
259
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/30d658ef2de4c2a98b8b81520fddd77f",
260
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/30d658ef2de4c2a98b8b81520fddd77f"
261
+                        ]
262
+                    },
263
+                    "IconUrl": {
264
+                        "Uri": "4f04b251d424ccab9b253daf6bb84b91",
265
+                        "UrlList": [
266
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/4f04b251d424ccab9b253daf6bb84b91",
267
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/4f04b251d424ccab9b253daf6bb84b91"
268
+                        ]
269
+                    },
270
+                    "Id": "30d658ef2de4c2a98b8b81520fddd77f",
271
+                    "EffectId": "2870170",
272
+                    "DevicePlatform": "all",
273
+                    "Types": [
274
+                        "GeneralEffect"
275
+                    ],
276
+                    "Tags": [],
277
+                    "TagsUpdatedAt": "1655120365000",
278
+                    "Parent": "",
279
+                    "Children": [],
280
+                    "HintIcon": {
281
+                        "Uri": "",
282
+                        "UrlList": []
283
+                    },
284
+                    "Music": [],
285
+                    "DesignerId": "",
286
+                    "Schema": "",
287
+                    "Description": "",
288
+                    "OriginalEffectId": "",
289
+                    "Requirements": [],
290
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"8a9e3fec9ffe35291f3d0a09b0636334\",\"is_business\":true,\"is_vip\":true}",
291
+                    "Countrys": [],
292
+                    "PoiId": "0",
293
+                    "DesignerEncryptedId": "",
294
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
295
+                    "AdRawData": "",
296
+                    "BindIds": [],
297
+                    "GradeKey": "",
298
+                    "ComposerParams": "",
299
+                    "Panel": "transitions",
300
+                    "ModelNames": "",
301
+                    "HintFile": {
302
+                        "Uri": "",
303
+                        "UrlList": []
304
+                    },
305
+                    "OriginalExtra": "",
306
+                    "NameTransKey": "",
307
+                    "HintTextTransKey": ""
308
+                },
309
+                {
310
+                    "EffectType": 0,
311
+                    "Source": 0,
312
+                    "IsFavorite": false,
313
+                    "Subtype": 0,
314
+                    "IsBusiness": false,
315
+                    "IsPoi": false,
316
+                    "SyncId": "2917718",
317
+                    "ResourceId": "6882983860615778823",
318
+                    "Channel": 1,
319
+                    "PublishStatus": 1,
320
+                    "Ptime": "1655218199000",
321
+                    "ChallengeId": "0",
322
+                    "HintFileFormat": 0,
323
+                    "IsEst": false,
324
+                    "AppID": 1059,
325
+                    "HasProfileInfo": false,
326
+                    "Name": "快门",
327
+                    "Hint": "",
328
+                    "SdkVersion": "5.4.0",
329
+                    "AppVersion": "",
330
+                    "FileUrl": {
331
+                        "Uri": "b4bb93b909e6be8e8ee7d7b22d533f32",
332
+                        "UrlList": [
333
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/b4bb93b909e6be8e8ee7d7b22d533f32",
334
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/b4bb93b909e6be8e8ee7d7b22d533f32"
335
+                        ]
336
+                    },
337
+                    "IconUrl": {
338
+                        "Uri": "c1a544e407e777db796878ae3b60d4b6",
339
+                        "UrlList": [
340
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c1a544e407e777db796878ae3b60d4b6",
341
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c1a544e407e777db796878ae3b60d4b6"
342
+                        ]
343
+                    },
344
+                    "Id": "b4bb93b909e6be8e8ee7d7b22d533f32",
345
+                    "EffectId": "2917720",
346
+                    "DevicePlatform": "all",
347
+                    "Types": [
348
+                        "GeneralEffect"
349
+                    ],
350
+                    "Tags": [],
351
+                    "TagsUpdatedAt": "1655217800000",
352
+                    "Parent": "",
353
+                    "Children": [],
354
+                    "HintIcon": {
355
+                        "Uri": "",
356
+                        "UrlList": []
357
+                    },
358
+                    "Music": [],
359
+                    "DesignerId": "",
360
+                    "Schema": "",
361
+                    "Description": "",
362
+                    "OriginalEffectId": "",
363
+                    "Requirements": [],
364
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"01fb65a3bba37e07278a86176b9be53d\",\"is_business\":true,\"is_vip\":true}",
365
+                    "Countrys": [],
366
+                    "PoiId": "0",
367
+                    "DesignerEncryptedId": "",
368
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":true}}",
369
+                    "AdRawData": "",
370
+                    "BindIds": [],
371
+                    "GradeKey": "",
372
+                    "ComposerParams": "",
373
+                    "Panel": "transitions",
374
+                    "ModelNames": "",
375
+                    "HintFile": {
376
+                        "Uri": "",
377
+                        "UrlList": []
378
+                    },
379
+                    "OriginalExtra": "",
380
+                    "NameTransKey": "",
381
+                    "HintTextTransKey": ""
382
+                }
383
+            ],
384
+            "Collection": [],
385
+            "CategoryKey": "paishe123",
386
+            "BindEffects": []
387
+        }
388
+    },
389
+    "extra": {
390
+        "RecId": "20240615163942B2067FC5E568F50D7575"
391
+    },
392
+    "BaseResp": {
393
+        "StatusMessage": "success",
394
+        "StatusCode": 0
395
+    }
396
+}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1383 - 0
src/nodeapi/drafts/data/zhuanchang/yunjing123.json


+ 334 - 0
src/nodeapi/drafts/data/zhuanchang/ziran123.json

@@ -0,0 +1,334 @@
1
+{
2
+    "data": {
3
+        "UrlPrefix": [
4
+            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/",
5
+            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/"
6
+        ],
7
+        "CategoryEffects": {
8
+            "HasMore": false,
9
+            "Cursor": 4,
10
+            "SortingPosition": 4,
11
+            "Version": "9707227762780,1007584378193,900,0",
12
+            "Effects": [
13
+                {
14
+                    "EffectType": 0,
15
+                    "Source": 0,
16
+                    "IsFavorite": false,
17
+                    "Subtype": 0,
18
+                    "IsBusiness": false,
19
+                    "IsPoi": false,
20
+                    "SyncId": "32838060",
21
+                    "ResourceId": "7309372378096603699",
22
+                    "Channel": 1,
23
+                    "PublishStatus": 1,
24
+                    "Ptime": "1701970054000",
25
+                    "ChallengeId": "0",
26
+                    "HintFileFormat": 0,
27
+                    "IsEst": false,
28
+                    "AppID": 1059,
29
+                    "HasProfileInfo": false,
30
+                    "Name": "雪雾",
31
+                    "Hint": "",
32
+                    "SdkVersion": "10.1.0",
33
+                    "AppVersion": "",
34
+                    "FileUrl": {
35
+                        "Uri": "776c40711e9f0f6f32570bc12ea50f91",
36
+                        "UrlList": [
37
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/776c40711e9f0f6f32570bc12ea50f91",
38
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/776c40711e9f0f6f32570bc12ea50f91"
39
+                        ]
40
+                    },
41
+                    "IconUrl": {
42
+                        "Uri": "0a4666199ce362554f3849f6ef596b83",
43
+                        "UrlList": [
44
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/0a4666199ce362554f3849f6ef596b83",
45
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/0a4666199ce362554f3849f6ef596b83"
46
+                        ]
47
+                    },
48
+                    "Id": "776c40711e9f0f6f32570bc12ea50f91",
49
+                    "EffectId": "32838061",
50
+                    "DevicePlatform": "all",
51
+                    "Types": [
52
+                        "AmazingFeature"
53
+                    ],
54
+                    "Tags": [],
55
+                    "TagsUpdatedAt": "1701874692000",
56
+                    "Parent": "",
57
+                    "Children": [],
58
+                    "HintIcon": {
59
+                        "Uri": "",
60
+                        "UrlList": []
61
+                    },
62
+                    "Music": [],
63
+                    "DesignerId": "",
64
+                    "Schema": "",
65
+                    "Description": "",
66
+                    "OriginalEffectId": "",
67
+                    "Requirements": [
68
+                        "blit"
69
+                    ],
70
+                    "Extra": "{\"hover_icon\":\"76564780f5f709818d9ba1a54d3b39a4\",\"is_business\":true,\"is_vip\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
71
+                    "Countrys": [],
72
+                    "PoiId": "0",
73
+                    "DesignerEncryptedId": "",
74
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":1.7,\"isOverlap\":true}}",
75
+                    "AdRawData": "",
76
+                    "BindIds": [],
77
+                    "GradeKey": "",
78
+                    "ComposerParams": "",
79
+                    "Panel": "transitions",
80
+                    "ModelNames": "",
81
+                    "HintFile": {
82
+                        "Uri": "",
83
+                        "UrlList": []
84
+                    },
85
+                    "SystemList": [
86
+                        "AnimSeqSystem",
87
+                        "BehaviorSystem",
88
+                        "CameraSystem",
89
+                        "EventSystem",
90
+                        "MeshRendererSystem",
91
+                        "RendererSystem",
92
+                        "ScriptSystem",
93
+                        "TransformSystem"
94
+                    ],
95
+                    "OriginalExtra": "",
96
+                    "NameTransKey": "",
97
+                    "HintTextTransKey": ""
98
+                },
99
+                {
100
+                    "EffectType": 0,
101
+                    "Source": 0,
102
+                    "IsFavorite": false,
103
+                    "Subtype": 0,
104
+                    "IsBusiness": false,
105
+                    "IsPoi": false,
106
+                    "SyncId": "1017907",
107
+                    "ResourceId": "6919369228701143559",
108
+                    "Channel": 1,
109
+                    "PublishStatus": 1,
110
+                    "Ptime": "1611945939000",
111
+                    "ChallengeId": "0",
112
+                    "HintFileFormat": 0,
113
+                    "IsEst": false,
114
+                    "AppID": 1059,
115
+                    "HasProfileInfo": false,
116
+                    "Name": "冰雪结晶",
117
+                    "Hint": "",
118
+                    "SdkVersion": "5.4.0",
119
+                    "AppVersion": "",
120
+                    "FileUrl": {
121
+                        "Uri": "acb710522989d8ce742a07ab5b59a2f8",
122
+                        "UrlList": [
123
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/acb710522989d8ce742a07ab5b59a2f8",
124
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/acb710522989d8ce742a07ab5b59a2f8"
125
+                        ]
126
+                    },
127
+                    "IconUrl": {
128
+                        "Uri": "0506e561ff50b88ef70422f3f2320674",
129
+                        "UrlList": [
130
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/0506e561ff50b88ef70422f3f2320674",
131
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/0506e561ff50b88ef70422f3f2320674"
132
+                        ]
133
+                    },
134
+                    "Id": "acb710522989d8ce742a07ab5b59a2f8",
135
+                    "EffectId": "1017910",
136
+                    "DevicePlatform": "all",
137
+                    "Types": [
138
+                        "GeneralEffect"
139
+                    ],
140
+                    "Tags": [],
141
+                    "TagsUpdatedAt": "1611070009000",
142
+                    "Parent": "",
143
+                    "Children": [],
144
+                    "HintIcon": {
145
+                        "Uri": "",
146
+                        "UrlList": []
147
+                    },
148
+                    "Music": [],
149
+                    "DesignerId": "",
150
+                    "Schema": "",
151
+                    "Description": "",
152
+                    "OriginalEffectId": "",
153
+                    "Requirements": [],
154
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"975b3530d8e4413135ea7fc90fd3e554\",\"is_business\":true}",
155
+                    "Countrys": [],
156
+                    "PoiId": "0",
157
+                    "DesignerEncryptedId": "",
158
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":false}}",
159
+                    "AdRawData": "",
160
+                    "BindIds": [],
161
+                    "GradeKey": "",
162
+                    "ComposerParams": "",
163
+                    "Panel": "transitions",
164
+                    "ModelNames": "",
165
+                    "HintFile": {
166
+                        "Uri": "",
167
+                        "UrlList": []
168
+                    },
169
+                    "OriginalExtra": "",
170
+                    "NameTransKey": "",
171
+                    "HintTextTransKey": ""
172
+                },
173
+                {
174
+                    "EffectType": 0,
175
+                    "Source": 0,
176
+                    "IsFavorite": false,
177
+                    "Subtype": 0,
178
+                    "IsBusiness": false,
179
+                    "IsPoi": false,
180
+                    "SyncId": "947662",
181
+                    "ResourceId": "6885646856672514567",
182
+                    "Channel": 1,
183
+                    "PublishStatus": 1,
184
+                    "Ptime": "1603298319000",
185
+                    "ChallengeId": "0",
186
+                    "HintFileFormat": 0,
187
+                    "IsEst": false,
188
+                    "AppID": 1059,
189
+                    "HasProfileInfo": false,
190
+                    "Name": "白色烟雾",
191
+                    "Hint": "",
192
+                    "SdkVersion": "5.4.0",
193
+                    "AppVersion": "",
194
+                    "FileUrl": {
195
+                        "Uri": "3d0f74a7941ff96598b5965db206cffb",
196
+                        "UrlList": [
197
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/3d0f74a7941ff96598b5965db206cffb",
198
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/3d0f74a7941ff96598b5965db206cffb"
199
+                        ]
200
+                    },
201
+                    "IconUrl": {
202
+                        "Uri": "7f48e4e54a41c17046b06123e8328666",
203
+                        "UrlList": [
204
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/7f48e4e54a41c17046b06123e8328666",
205
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/7f48e4e54a41c17046b06123e8328666"
206
+                        ]
207
+                    },
208
+                    "Id": "3d0f74a7941ff96598b5965db206cffb",
209
+                    "EffectId": "947664",
210
+                    "DevicePlatform": "all",
211
+                    "Types": [
212
+                        "GeneralEffect"
213
+                    ],
214
+                    "Tags": [],
215
+                    "TagsUpdatedAt": "1603218449000",
216
+                    "Parent": "",
217
+                    "Children": [],
218
+                    "HintIcon": {
219
+                        "Uri": "",
220
+                        "UrlList": []
221
+                    },
222
+                    "Music": [],
223
+                    "DesignerId": "",
224
+                    "Schema": "",
225
+                    "Description": "",
226
+                    "OriginalEffectId": "",
227
+                    "Requirements": [],
228
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"67f2bc3439cd26b614744e8c6f3b303c\",\"is_business\":true}",
229
+                    "Countrys": [],
230
+                    "PoiId": "0",
231
+                    "DesignerEncryptedId": "",
232
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":false}}",
233
+                    "AdRawData": "",
234
+                    "BindIds": [],
235
+                    "GradeKey": "",
236
+                    "ComposerParams": "",
237
+                    "Panel": "transitions",
238
+                    "ModelNames": "",
239
+                    "HintFile": {
240
+                        "Uri": "",
241
+                        "UrlList": []
242
+                    },
243
+                    "OriginalExtra": "",
244
+                    "NameTransKey": "",
245
+                    "HintTextTransKey": ""
246
+                },
247
+                {
248
+                    "EffectType": 0,
249
+                    "Source": 0,
250
+                    "IsFavorite": false,
251
+                    "Subtype": 0,
252
+                    "IsBusiness": false,
253
+                    "IsPoi": false,
254
+                    "SyncId": "947661",
255
+                    "ResourceId": "6885647017452769805",
256
+                    "Channel": 1,
257
+                    "PublishStatus": 1,
258
+                    "Ptime": "1603298319000",
259
+                    "ChallengeId": "0",
260
+                    "HintFileFormat": 0,
261
+                    "IsEst": false,
262
+                    "AppID": 1059,
263
+                    "HasProfileInfo": false,
264
+                    "Name": "黑色烟雾",
265
+                    "Hint": "",
266
+                    "SdkVersion": "5.4.0",
267
+                    "AppVersion": "",
268
+                    "FileUrl": {
269
+                        "Uri": "5848206e13b9457902ed5a66424799a8",
270
+                        "UrlList": [
271
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/5848206e13b9457902ed5a66424799a8",
272
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/5848206e13b9457902ed5a66424799a8"
273
+                        ]
274
+                    },
275
+                    "IconUrl": {
276
+                        "Uri": "06ff3f0768f45bf8329133c8735b9293",
277
+                        "UrlList": [
278
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/06ff3f0768f45bf8329133c8735b9293",
279
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/06ff3f0768f45bf8329133c8735b9293"
280
+                        ]
281
+                    },
282
+                    "Id": "5848206e13b9457902ed5a66424799a8",
283
+                    "EffectId": "947663",
284
+                    "DevicePlatform": "all",
285
+                    "Types": [
286
+                        "GeneralEffect"
287
+                    ],
288
+                    "Tags": [],
289
+                    "TagsUpdatedAt": "1603218449000",
290
+                    "Parent": "",
291
+                    "Children": [],
292
+                    "HintIcon": {
293
+                        "Uri": "",
294
+                        "UrlList": []
295
+                    },
296
+                    "Music": [],
297
+                    "DesignerId": "",
298
+                    "Schema": "",
299
+                    "Description": "",
300
+                    "OriginalEffectId": "",
301
+                    "Requirements": [],
302
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"a0824ba91737e3fd5ab5032fc2758e99\",\"is_business\":true}",
303
+                    "Countrys": [],
304
+                    "PoiId": "0",
305
+                    "DesignerEncryptedId": "",
306
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":false}}",
307
+                    "AdRawData": "",
308
+                    "BindIds": [],
309
+                    "GradeKey": "",
310
+                    "ComposerParams": "",
311
+                    "Panel": "transitions",
312
+                    "ModelNames": "",
313
+                    "HintFile": {
314
+                        "Uri": "",
315
+                        "UrlList": []
316
+                    },
317
+                    "OriginalExtra": "",
318
+                    "NameTransKey": "",
319
+                    "HintTextTransKey": ""
320
+                }
321
+            ],
322
+            "Collection": [],
323
+            "CategoryKey": "ziran123",
324
+            "BindEffects": []
325
+        }
326
+    },
327
+    "extra": {
328
+        "RecId": "20240615164123FC515C936551040D4972"
329
+    },
330
+    "BaseResp": {
331
+        "StatusMessage": "success",
332
+        "StatusCode": 0
333
+    }
334
+}

+ 396 - 0
src/nodeapi/drafts/data/zhuanchang/zongyi123.json

@@ -0,0 +1,396 @@
1
+{
2
+    "data": {
3
+        "UrlPrefix": [
4
+            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/",
5
+            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/"
6
+        ],
7
+        "CategoryEffects": {
8
+            "HasMore": false,
9
+            "Cursor": 5,
10
+            "SortingPosition": 5,
11
+            "Version": "1423976122935,1825186856914,900,0",
12
+            "Effects": [
13
+                {
14
+                    "EffectType": 0,
15
+                    "Source": 0,
16
+                    "IsFavorite": false,
17
+                    "Subtype": 0,
18
+                    "IsBusiness": false,
19
+                    "IsPoi": false,
20
+                    "SyncId": "1437263",
21
+                    "ResourceId": "7029592645538157086",
22
+                    "Channel": 1,
23
+                    "PublishStatus": 1,
24
+                    "Ptime": "1637352017000",
25
+                    "ChallengeId": "0",
26
+                    "HintFileFormat": 0,
27
+                    "IsEst": false,
28
+                    "AppID": 1059,
29
+                    "HasProfileInfo": false,
30
+                    "Name": "打板转场 II",
31
+                    "Hint": "",
32
+                    "SdkVersion": "5.4.0",
33
+                    "AppVersion": "",
34
+                    "FileUrl": {
35
+                        "Uri": "f50cfd9dfb243a87efc7e8b538e2eabb",
36
+                        "UrlList": [
37
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/f50cfd9dfb243a87efc7e8b538e2eabb",
38
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/f50cfd9dfb243a87efc7e8b538e2eabb"
39
+                        ]
40
+                    },
41
+                    "IconUrl": {
42
+                        "Uri": "624ba96daa07d888c87a54c2b5bcf684",
43
+                        "UrlList": [
44
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/624ba96daa07d888c87a54c2b5bcf684",
45
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/624ba96daa07d888c87a54c2b5bcf684"
46
+                        ]
47
+                    },
48
+                    "Id": "f50cfd9dfb243a87efc7e8b538e2eabb",
49
+                    "EffectId": "1437264",
50
+                    "DevicePlatform": "all",
51
+                    "Types": [
52
+                        "GeneralEffect"
53
+                    ],
54
+                    "Tags": [],
55
+                    "TagsUpdatedAt": "1636733410000",
56
+                    "Parent": "",
57
+                    "Children": [],
58
+                    "HintIcon": {
59
+                        "Uri": "",
60
+                        "UrlList": []
61
+                    },
62
+                    "Music": [],
63
+                    "DesignerId": "",
64
+                    "Schema": "",
65
+                    "Description": "",
66
+                    "OriginalEffectId": "",
67
+                    "Requirements": [],
68
+                    "Extra": "{\"hover_icon\":\"90f843f7179e809c6a7db46b536cb39d\",\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
69
+                    "Countrys": [],
70
+                    "PoiId": "0",
71
+                    "DesignerEncryptedId": "",
72
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":4,\"isOverlap\":false}}",
73
+                    "AdRawData": "",
74
+                    "BindIds": [],
75
+                    "GradeKey": "",
76
+                    "ComposerParams": "",
77
+                    "Panel": "transitions",
78
+                    "ModelNames": "",
79
+                    "HintFile": {
80
+                        "Uri": "",
81
+                        "UrlList": []
82
+                    },
83
+                    "OriginalExtra": "",
84
+                    "NameTransKey": "",
85
+                    "HintTextTransKey": ""
86
+                },
87
+                {
88
+                    "EffectType": 0,
89
+                    "Source": 0,
90
+                    "IsFavorite": false,
91
+                    "Subtype": 0,
92
+                    "IsBusiness": false,
93
+                    "IsPoi": false,
94
+                    "SyncId": "1432321",
95
+                    "ResourceId": "7028143517570437668",
96
+                    "Channel": 1,
97
+                    "PublishStatus": 1,
98
+                    "Ptime": "1637352017000",
99
+                    "ChallengeId": "0",
100
+                    "HintFileFormat": 0,
101
+                    "IsEst": false,
102
+                    "AppID": 1059,
103
+                    "HasProfileInfo": false,
104
+                    "Name": "打板转场 I",
105
+                    "Hint": "",
106
+                    "SdkVersion": "5.4.0",
107
+                    "AppVersion": "",
108
+                    "FileUrl": {
109
+                        "Uri": "4307ef0dc881bb62aeb7793ce7e8cb0e",
110
+                        "UrlList": [
111
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/4307ef0dc881bb62aeb7793ce7e8cb0e",
112
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/4307ef0dc881bb62aeb7793ce7e8cb0e"
113
+                        ]
114
+                    },
115
+                    "IconUrl": {
116
+                        "Uri": "cbd79c711c1fe3831768325af00566af",
117
+                        "UrlList": [
118
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/cbd79c711c1fe3831768325af00566af",
119
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/cbd79c711c1fe3831768325af00566af"
120
+                        ]
121
+                    },
122
+                    "Id": "4307ef0dc881bb62aeb7793ce7e8cb0e",
123
+                    "EffectId": "1432322",
124
+                    "DevicePlatform": "all",
125
+                    "Types": [
126
+                        "GeneralEffect"
127
+                    ],
128
+                    "Tags": [],
129
+                    "TagsUpdatedAt": "1636456291000",
130
+                    "Parent": "",
131
+                    "Children": [],
132
+                    "HintIcon": {
133
+                        "Uri": "",
134
+                        "UrlList": []
135
+                    },
136
+                    "Music": [],
137
+                    "DesignerId": "",
138
+                    "Schema": "",
139
+                    "Description": "",
140
+                    "OriginalEffectId": "",
141
+                    "Requirements": [],
142
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"5c6ecebe69dd83942225620f59c39dc8\",\"is_business\":true}",
143
+                    "Countrys": [],
144
+                    "PoiId": "0",
145
+                    "DesignerEncryptedId": "",
146
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":4,\"isOverlap\":false}}",
147
+                    "AdRawData": "",
148
+                    "BindIds": [],
149
+                    "GradeKey": "",
150
+                    "ComposerParams": "",
151
+                    "Panel": "transitions",
152
+                    "ModelNames": "",
153
+                    "HintFile": {
154
+                        "Uri": "",
155
+                        "UrlList": []
156
+                    },
157
+                    "OriginalExtra": "",
158
+                    "NameTransKey": "",
159
+                    "HintTextTransKey": ""
160
+                },
161
+                {
162
+                    "EffectType": 0,
163
+                    "Source": 0,
164
+                    "IsFavorite": false,
165
+                    "Subtype": 0,
166
+                    "IsBusiness": false,
167
+                    "IsPoi": false,
168
+                    "SyncId": "1441671",
169
+                    "ResourceId": "7030714241359286821",
170
+                    "Channel": 1,
171
+                    "PublishStatus": 1,
172
+                    "Ptime": "1637352018000",
173
+                    "ChallengeId": "0",
174
+                    "HintFileFormat": 0,
175
+                    "IsEst": false,
176
+                    "AppID": 1059,
177
+                    "HasProfileInfo": false,
178
+                    "Name": "冲鸭",
179
+                    "Hint": "",
180
+                    "SdkVersion": "5.4.0",
181
+                    "AppVersion": "",
182
+                    "FileUrl": {
183
+                        "Uri": "187a41282d12285eac2f7e171d7f2518",
184
+                        "UrlList": [
185
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/187a41282d12285eac2f7e171d7f2518",
186
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/187a41282d12285eac2f7e171d7f2518"
187
+                        ]
188
+                    },
189
+                    "IconUrl": {
190
+                        "Uri": "3b82824d659828f3c00005aa3f630945",
191
+                        "UrlList": [
192
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/3b82824d659828f3c00005aa3f630945",
193
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/3b82824d659828f3c00005aa3f630945"
194
+                        ]
195
+                    },
196
+                    "Id": "187a41282d12285eac2f7e171d7f2518",
197
+                    "EffectId": "1441672",
198
+                    "DevicePlatform": "all",
199
+                    "Types": [
200
+                        "GeneralEffect"
201
+                    ],
202
+                    "Tags": [],
203
+                    "TagsUpdatedAt": "",
204
+                    "Parent": "",
205
+                    "Children": [],
206
+                    "HintIcon": {
207
+                        "Uri": "",
208
+                        "UrlList": []
209
+                    },
210
+                    "Music": [],
211
+                    "DesignerId": "",
212
+                    "Schema": "",
213
+                    "Description": "",
214
+                    "OriginalEffectId": "",
215
+                    "Requirements": [],
216
+                    "Extra": "{\"hover_icon\":\"06380f68d066cfb47e91e31d21f1fc00\",\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
217
+                    "Countrys": [],
218
+                    "PoiId": "0",
219
+                    "DesignerEncryptedId": "",
220
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":0.5,\"isOverlap\":false},\"oe_remit_v2\":true,\"isEHEffect\":false,\"triggerJson\":null}",
221
+                    "AdRawData": "",
222
+                    "BindIds": [],
223
+                    "GradeKey": "",
224
+                    "ComposerParams": "",
225
+                    "Panel": "transitions",
226
+                    "ModelNames": "",
227
+                    "HintFile": {
228
+                        "Uri": "",
229
+                        "UrlList": []
230
+                    },
231
+                    "OriginalExtra": "",
232
+                    "NameTransKey": "",
233
+                    "HintTextTransKey": ""
234
+                },
235
+                {
236
+                    "EffectType": 0,
237
+                    "Source": 0,
238
+                    "IsFavorite": false,
239
+                    "Subtype": 0,
240
+                    "IsBusiness": false,
241
+                    "IsPoi": false,
242
+                    "SyncId": "1433949",
243
+                    "ResourceId": "7028877116259176974",
244
+                    "Channel": 1,
245
+                    "PublishStatus": 1,
246
+                    "Ptime": "1637352017000",
247
+                    "ChallengeId": "0",
248
+                    "HintFileFormat": 0,
249
+                    "IsEst": false,
250
+                    "AppID": 1059,
251
+                    "HasProfileInfo": false,
252
+                    "Name": "弹幕转场",
253
+                    "Hint": "",
254
+                    "SdkVersion": "5.4.0",
255
+                    "AppVersion": "",
256
+                    "FileUrl": {
257
+                        "Uri": "c7a62fa8e74daf22f83270bf683de93f",
258
+                        "UrlList": [
259
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c7a62fa8e74daf22f83270bf683de93f",
260
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c7a62fa8e74daf22f83270bf683de93f"
261
+                        ]
262
+                    },
263
+                    "IconUrl": {
264
+                        "Uri": "d928ff3c42afadaa4a5b35fe744c2305",
265
+                        "UrlList": [
266
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/d928ff3c42afadaa4a5b35fe744c2305",
267
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/d928ff3c42afadaa4a5b35fe744c2305"
268
+                        ]
269
+                    },
270
+                    "Id": "c7a62fa8e74daf22f83270bf683de93f",
271
+                    "EffectId": "1433950",
272
+                    "DevicePlatform": "all",
273
+                    "Types": [
274
+                        "GeneralEffect"
275
+                    ],
276
+                    "Tags": [],
277
+                    "TagsUpdatedAt": "1636566797000",
278
+                    "Parent": "",
279
+                    "Children": [],
280
+                    "HintIcon": {
281
+                        "Uri": "",
282
+                        "UrlList": []
283
+                    },
284
+                    "Music": [],
285
+                    "DesignerId": "",
286
+                    "Schema": "",
287
+                    "Description": "",
288
+                    "OriginalEffectId": "",
289
+                    "Requirements": [],
290
+                    "Extra": "{\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true,\"hover_icon\":\"ffe615128b87d0e2b0533c421639bfde\",\"is_business\":true}",
291
+                    "Countrys": [],
292
+                    "PoiId": "0",
293
+                    "DesignerEncryptedId": "",
294
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":4,\"isOverlap\":false}}",
295
+                    "AdRawData": "",
296
+                    "BindIds": [],
297
+                    "GradeKey": "",
298
+                    "ComposerParams": "",
299
+                    "Panel": "transitions",
300
+                    "ModelNames": "",
301
+                    "HintFile": {
302
+                        "Uri": "",
303
+                        "UrlList": []
304
+                    },
305
+                    "OriginalExtra": "",
306
+                    "NameTransKey": "",
307
+                    "HintTextTransKey": ""
308
+                },
309
+                {
310
+                    "EffectType": 0,
311
+                    "Source": 0,
312
+                    "IsFavorite": false,
313
+                    "Subtype": 0,
314
+                    "IsBusiness": false,
315
+                    "IsPoi": false,
316
+                    "SyncId": "1433967",
317
+                    "ResourceId": "7028880945671311903",
318
+                    "Channel": 1,
319
+                    "PublishStatus": 1,
320
+                    "Ptime": "1637352017000",
321
+                    "ChallengeId": "0",
322
+                    "HintFileFormat": 0,
323
+                    "IsEst": false,
324
+                    "AppID": 1059,
325
+                    "HasProfileInfo": false,
326
+                    "Name": "气泡转场",
327
+                    "Hint": "",
328
+                    "SdkVersion": "5.4.0",
329
+                    "AppVersion": "",
330
+                    "FileUrl": {
331
+                        "Uri": "582da0c734d708b7be2b5e852a33ac5f",
332
+                        "UrlList": [
333
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/582da0c734d708b7be2b5e852a33ac5f",
334
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/582da0c734d708b7be2b5e852a33ac5f"
335
+                        ]
336
+                    },
337
+                    "IconUrl": {
338
+                        "Uri": "efd395ff03b1f1d977bcf6afd28509fc",
339
+                        "UrlList": [
340
+                            "https://lf26-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/efd395ff03b1f1d977bcf6afd28509fc",
341
+                            "https://lf3-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/efd395ff03b1f1d977bcf6afd28509fc"
342
+                        ]
343
+                    },
344
+                    "Id": "582da0c734d708b7be2b5e852a33ac5f",
345
+                    "EffectId": "1433968",
346
+                    "DevicePlatform": "all",
347
+                    "Types": [
348
+                        "GeneralEffect"
349
+                    ],
350
+                    "Tags": [],
351
+                    "TagsUpdatedAt": "1636567687000",
352
+                    "Parent": "",
353
+                    "Children": [],
354
+                    "HintIcon": {
355
+                        "Uri": "",
356
+                        "UrlList": []
357
+                    },
358
+                    "Music": [],
359
+                    "DesignerId": "",
360
+                    "Schema": "",
361
+                    "Description": "",
362
+                    "OriginalEffectId": "",
363
+                    "Requirements": [],
364
+                    "Extra": "{\"hover_icon\":\"75e410209d7bbb9d9bed521d489fd5ea\",\"is_business\":true,\"copyright_pay_review_status\":1,\"copyright_pay_auth_status\":1,\"copyright_can_convert_pay\":true,\"copyright_commerce_review_status\":1,\"copyright_commerce_auth_status\":1,\"copyright_can_convert_commerce\":true}",
365
+                    "Countrys": [],
366
+                    "PoiId": "0",
367
+                    "DesignerEncryptedId": "",
368
+                    "SdkExtra": "{\"transition\":{\"defaultDura\":4,\"isOverlap\":false}}",
369
+                    "AdRawData": "",
370
+                    "BindIds": [],
371
+                    "GradeKey": "",
372
+                    "ComposerParams": "",
373
+                    "Panel": "transitions",
374
+                    "ModelNames": "",
375
+                    "HintFile": {
376
+                        "Uri": "",
377
+                        "UrlList": []
378
+                    },
379
+                    "OriginalExtra": "",
380
+                    "NameTransKey": "",
381
+                    "HintTextTransKey": ""
382
+                }
383
+            ],
384
+            "Collection": [],
385
+            "CategoryKey": "zongyi123",
386
+            "BindEffects": []
387
+        }
388
+    },
389
+    "extra": {
390
+        "RecId": "20240615164500B2067FC5E568F50D7D29"
391
+    },
392
+    "BaseResp": {
393
+        "StatusMessage": "success",
394
+        "StatusCode": 0
395
+    }
396
+}

+ 187 - 0
src/nodeapi/drafts/drafts_task.js

@@ -0,0 +1,187 @@
1
+const path = require('path');
2
+const os = require('os');
3
+const fs = require('fs');
4
+const crypto = require('crypto');
5
+const fsex = require('fs-extra');
6
+const { v4: uuidv4 } = require('uuid');
7
+const { add_audio } = require('./add_audio');
8
+const { add_video } = require('./add_video');
9
+const { app } = require('electron');
10
+const { add_text } = require('./add_text');
11
+const {getImageDimensions} = require('./get_image_info');
12
+const { add_new_tracks } = require('./add_tracks');
13
+const { add_new_segments } = require('./add_tracks_segments');
14
+const { getVideoResolution,getVideoDuration,getAudioDuration } = require("../video/ffmpegHandler");
15
+const { add_text_animations } = require('./add_text_animations');
16
+const { add_video_animations } = require('./add_video_animations');
17
+const { add_video_effects } = require('./add_video_effects');
18
+
19
+//创建草稿
20
+//创建新的草稿,并返回草稿路径
21
+async function create_draft_file(draft_path,draft_name) {
22
+    
23
+    draft_path = path.join(draft_path,draft_name)
24
+    if (!fs.existsSync(draft_path)) {
25
+      fs.mkdirSync(draft_path, { recursive: true });
26
+    }
27
+    
28
+    if( app && app.isPackaged){
29
+      tmp_path_name = path.join(process.resourcesPath, 'app.asar.unpacked', 'jianyin/template');
30
+      await copyDirectory(tmp_path_name,draft_path)
31
+    }else{
32
+      await copyDirectory(path.join(__dirname, '../../../jianyin/template'), draft_path);
33
+    }
34
+    
35
+    console.log('创建模版:',draft_path)
36
+
37
+    //修改名字
38
+    let draft_json  =  await get_draft_json(draft_path,1)
39
+    draft_json.draft_fold_path = draft_path;
40
+    draft_json.draft_root_path = draft_path;
41
+    draft_json.draft_name = draft_name;
42
+    save_draft_json(draft_path,draft_json,1)
43
+
44
+    //修改ID
45
+    let template = readJsonFile( path.join( draft_path, "template.tmp"));
46
+    template.id = uuidv4();
47
+    writeJsonFile(path.join( draft_path, "template.tmp"), template);
48
+    
49
+
50
+
51
+    return draft_path
52
+  
53
+}
54
+//复制模版
55
+async function copyDirectory (srcDir, destDir) {
56
+    try {
57
+      await fsex.copy(srcDir, destDir);
58
+      console.log('Directory has been copied successfully');
59
+    } catch (err) {
60
+      console.error(err);
61
+    }
62
+  }
63
+
64
+
65
+  function readJsonFile (filePath) {
66
+    try {
67
+      const data = fs.readFileSync(filePath, 'utf-8');
68
+      const json = JSON.parse(data);
69
+      // console.log(`JSON data:`, json);
70
+      return json;
71
+    } catch (err) {
72
+      console.error(`Error reading or parsing file: ${err}`);
73
+    }
74
+  }
75
+  
76
+  function writeJsonFile (filePath, json) {
77
+    console.log(filePath, 'filePath');
78
+    try {
79
+      const data = JSON.stringify(json, null, 0);
80
+      fs.writeFileSync(filePath, data, 'utf-8');
81
+      console.log(`JSON data has been written to ${filePath}`);
82
+    } catch (err) {
83
+      console.error(`Error writing file: ${err}`);
84
+    }
85
+  }
86
+  
87
+
88
+
89
+//通过草稿路径获取json编辑文件
90
+async function get_draft_json(draft_path,is_meta=0){
91
+    let json_path = path.join( draft_path, "draft_content.json");
92
+    if(is_meta){
93
+        json_path = path.join( draft_path, "draft_meta_info.json");
94
+    }
95
+
96
+    let meta_info = readJsonFile(json_path);
97
+    // console.log(meta_info)
98
+    return meta_info
99
+
100
+}
101
+
102
+//通过草稿路径写入草稿内容
103
+async function save_draft_json(draft_path,draft_content,is_meta=0){
104
+    let json_path = path.join( draft_path, "draft_content.json");
105
+    if(is_meta){
106
+        json_path = path.join( draft_path, "draft_meta_info.json");
107
+    }
108
+    writeJsonFile( json_path ,  draft_content);
109
+    return get_draft_json(draft_path)
110
+
111
+}
112
+
113
+
114
+
115
+async function test_add_image(){
116
+
117
+    //剪映路径
118
+    let draft_path = '/Users/hxc/draw_img/default_jianyin_draft/draft/JianyingPro Drafts';
119
+    draft_path = await create_draft_file(draft_path,'ts-'+new Date().getTime())
120
+    //获取内容
121
+    let draft_content =  await get_draft_json(draft_path)
122
+    
123
+
124
+    //增加图片案例
125
+    let image_path  = '/Users/hxc/Downloads/图片/henbign.png';
126
+    let image_info = await  getImageDimensions(image_path);
127
+    let image = await  add_video(draft_content,image_path,5*1000000,image_info.width,image_info.height,0);
128
+    let image_track =  await add_new_tracks(draft_content,'video')
129
+    //轨道上增加媒体
130
+    await add_new_segments(image_track,image.id,0,5*1000000);
131
+     let seg01 =  await add_new_segments(image_track,image.id,5*1000000,10*1000000);
132
+    //增加动画
133
+    let v_ani01 =  await add_video_animations(draft_content,'6991764455931515422','6798320902548230669','7025952723027628557');
134
+    seg01.extra_material_refs.push(v_ani01.id)
135
+
136
+
137
+    
138
+
139
+    //增加视频案例
140
+    let video_path  = '/Users/hxc/Downloads/solo.mp4'
141
+    let video_duration =  await getVideoDuration(video_path)
142
+    let video_info =  await getVideoResolution(video_path);
143
+    let video_01 = await  add_video(draft_content,video_path,video_duration*1000000,video_info.width,video_info.height,1);
144
+    //增加一条轨道
145
+    let video_track =  await add_new_tracks(draft_content,'video')
146
+    await add_new_segments(video_track,video_01.id , 15*1000000,video_duration*1000000)
147
+
148
+
149
+    //增加音频案例
150
+    let audio_path = '/Users/hxc/draw_img/0/mp3/0-1716193641286.wav'
151
+    let audio_duration = await getAudioDuration(audio_path);
152
+    let audio_01 =  await add_audio(draft_content,audio_path,audio_duration*1000000)
153
+    //增加一条音频轨道
154
+    let audio_track =  await add_new_tracks(draft_content,'audio');
155
+    await add_new_segments(audio_track,audio_01.id,0,audio_duration*1000000);
156
+
157
+
158
+    //增加字幕
159
+    let content = "不要轻易相信任何人"
160
+    let text_01 =  await add_text(draft_content,content);
161
+    //增加一个字幕轨道
162
+    let text_track =  await add_new_tracks(draft_content,'text')
163
+
164
+    //增加一个入场动画
165
+    let animations01 =  await add_text_animations(draft_content,'6724916044072227332','7244102414377161276','6908592686781960717')
166
+    let text_seg01 = await add_new_segments(text_track,text_01.id,0,5*1000000);
167
+    text_seg01.extra_material_refs.push(animations01.id)
168
+
169
+
170
+    //新增一个特效轨道
171
+    let texiao_track = await add_new_tracks(draft_content,'effect')
172
+    let effect01 =  await add_video_effects(draft_content,'7345724656642429452')
173
+    let texiao_seg01 = await add_new_segments(texiao_track,effect01.id,0,5*1000000);
174
+
175
+
176
+    save_draft_json(draft_path,draft_content)
177
+
178
+}
179
+
180
+
181
+
182
+
183
+
184
+// test_add_image()
185
+
186
+
187
+module.exports = { create_draft_file,get_draft_json,save_draft_json };

+ 13 - 0
src/nodeapi/drafts/get_image_info.js

@@ -0,0 +1,13 @@
1
+const sizeOf = require('image-size');
2
+
3
+function getImageDimensions(imagePath) {
4
+    try {
5
+        const dimensions = sizeOf(imagePath);
6
+        console.log(`Width: ${dimensions.width}, Height: ${dimensions.height}`);
7
+        return { width: dimensions.width, height: dimensions.height };
8
+    } catch (error) {
9
+        console.error('Error reading image:', error);
10
+    }
11
+}
12
+
13
+module.exports = { getImageDimensions };

+ 399 - 0
src/nodeapi/ipcHandlers.js

@@ -0,0 +1,399 @@
1
+const { app, ipcMain, dialog, shell, session, BrowserWindow, screen } = require('electron');
2
+const path = require('path');
3
+const fs = require('fs');
4
+const { 
5
+  initDatabase, 
6
+  handleBookOperations, 
7
+  handleBookInfoOperations,
8
+  getDbPath
9
+} = require('./dbHandler');
10
+
11
+console.log(process.versions.electron);
12
+console.log(process.versions.chrome);
13
+
14
+function setupIpcHandlers () {
15
+  ipcMain.on('message-from-renderer', (event, message) => {
16
+    console.log(message); // 输出 'Hello from renderer process'
17
+  });
18
+
19
+  ipcMain.handle('request-data', async (event, data) => {
20
+    console.log(data); // 输出 'some data'
21
+    return 'response from main process';
22
+  });
23
+
24
+  ipcMain.handle('get-app-version', () => {
25
+    return app.getVersion();
26
+  })
27
+
28
+  ipcMain.handle('open-directory-dialog', async (event) => {
29
+    const result = await dialog.showOpenDialog({
30
+      properties: ['openDirectory']
31
+    });
32
+    return result;
33
+  });
34
+
35
+  ipcMain.handle('open-file-path', async (event, base_path) => {
36
+    console.log(base_path);
37
+    if (base_path.startsWith('file://')) {
38
+      base_path = base_path.slice(7); // 去掉 'file://'
39
+    }
40
+    const questionMarkIndex = base_path.indexOf('?');
41
+    if (questionMarkIndex !== -1) {
42
+      base_path = base_path.slice(0, questionMarkIndex); // 去掉 '?' 及其后面的内容
43
+    }
44
+
45
+    shell.showItemInFolder(base_path);
46
+  });
47
+
48
+  ipcMain.handle('open-url', (event, url) => {
49
+    shell.openExternal(url);
50
+  });
51
+
52
+  ipcMain.handle('open-shell-python', async (event, data) => autoScene(event, data))
53
+
54
+  ipcMain.on('open-url', async (event, space) => {
55
+    const { title, url, hash } = space;
56
+    
57
+    // Create a unique session for each space
58
+    const spaceSession = session.fromPartition(`persist:${hash}`);
59
+
60
+    const primaryDisplay = screen.getPrimaryDisplay();
61
+    const { width, height } = primaryDisplay.workAreaSize;
62
+
63
+    // Load cookies for this session
64
+    await loadCookiesForSession(spaceSession, space);
65
+
66
+    // Create a new BrowserWindow with the unique session
67
+    const win = new BrowserWindow({
68
+      width: width,
69
+      height: height,
70
+      webPreferences: {
71
+        session: spaceSession,
72
+        contextIsolation: true,
73
+        enableRemoteModule: true,
74
+        webSecurity: false,
75
+        nodeIntegration: false,
76
+      },
77
+    });
78
+
79
+    win.loadURL(url);
80
+
81
+    // Record browsing history
82
+    recordHistory({ title, url, hash });
83
+  });
84
+
85
+  // 获取文件状态信息
86
+  ipcMain.handle('get-file-stats', async (event, filePath) => {
87
+    try {
88
+      // 确保文件路径存在
89
+      if (!filePath) {
90
+        throw new Error('文件路径不能为空');
91
+      }
92
+
93
+      // 处理file://前缀
94
+      if (filePath.startsWith('file://')) {
95
+        filePath = filePath.slice(7); // 去掉 'file://'
96
+      }
97
+
98
+      // 解码URL编码的路径
99
+      filePath = decodeURIComponent(filePath);
100
+
101
+      // 检查文件是否存在
102
+      if (!fs.existsSync(filePath)) {
103
+        throw new Error(`文件不存在: ${filePath}`);
104
+      }
105
+
106
+      // 获取文件状态
107
+      const stats = fs.statSync(filePath);
108
+      return {
109
+        size: stats.size,
110
+        isFile: stats.isFile(),
111
+        isDirectory: stats.isDirectory(),
112
+        createdAt: stats.birthtime,
113
+        modifiedAt: stats.mtime,
114
+        accessedAt: stats.atime
115
+      };
116
+    } catch (error) {
117
+      console.error('获取文件状态时出错:', error);
118
+      return null;
119
+    }
120
+  });
121
+
122
+  // 数据库初始化
123
+  ipcMain.handle('db:init', async (event, forceUpdate = false) => {
124
+    console.log('初始化数据库...');
125
+    try {
126
+      const result = await initDatabase(forceUpdate);
127
+      return { success: !!result };
128
+    } catch (error) {
129
+      console.error('初始化数据库失败:', error);
130
+      return { success: false, error: error.message };
131
+    }
132
+  });
133
+
134
+  // 获取数据库路径
135
+  ipcMain.handle('db:getPath', () => {
136
+    return getDbPath();
137
+  });
138
+
139
+  // Book操作
140
+  ipcMain.handle('book:create', async (event, bookData) => {
141
+    return await handleBookOperations.createBook(bookData);
142
+  });
143
+
144
+  ipcMain.handle('book:getAll', async () => {
145
+    return await handleBookOperations.getAllBooks();
146
+  });
147
+
148
+  ipcMain.handle('book:getById', async (event, id) => {
149
+    return await handleBookOperations.getBookById(id);
150
+  });
151
+
152
+  ipcMain.handle('book:update', async (event, { id, bookData }) => {
153
+    return await handleBookOperations.updateBook(id, bookData);
154
+  });
155
+
156
+  ipcMain.handle('book:delete', async (event, id) => {
157
+    return await handleBookOperations.deleteBook(id);
158
+  });
159
+
160
+  // BookInfo操作
161
+  ipcMain.handle('bookInfo:create', async (event, bookInfoData) => {
162
+    return await handleBookInfoOperations.createBookInfo(bookInfoData);
163
+  });
164
+
165
+  ipcMain.handle('bookInfo:getByBookId', async (event, bookId) => {
166
+    return await handleBookInfoOperations.getBookInfoByBookId(bookId);
167
+  });
168
+
169
+  ipcMain.handle('bookInfo:update', async (event, { bookId, bookInfoData }) => {
170
+    return await handleBookInfoOperations.updateBookInfo(bookId, bookInfoData);
171
+  });
172
+
173
+  ipcMain.handle('bookInfo:delete', async (event, bookId) => {
174
+    return await handleBookInfoOperations.deleteBookInfo(bookId);
175
+  });
176
+
177
+  // 设置音频处理IPC处理程序
178
+  setupAudioProcessingHandlers();
179
+
180
+  // 保存音频文件
181
+  ipcMain.handle('save-audio-file', async (event, { buffer, fileName, directory, projectId }) => {
182
+    try {
183
+      // 确保目录存在
184
+      const dirPath = directory;
185
+      if (!fs.existsSync(dirPath)) {
186
+        fs.mkdirSync(dirPath, { recursive: true });
187
+        console.log(`创建目录: ${dirPath}`);
188
+      }
189
+      
190
+      // 保存文件
191
+      const filePath = path.join(dirPath, fileName);
192
+      const bufferData = Buffer.from(buffer);
193
+      
194
+      await fs.promises.writeFile(filePath, bufferData);
195
+      
196
+      return {
197
+        success: true,
198
+        filePath: filePath
199
+      };
200
+    } catch (error) {
201
+      console.error('保存音频文件失败:', error);
202
+      return {
203
+        success: false,
204
+        error: error.message
205
+      };
206
+    }
207
+  });
208
+
209
+  // 获取资源目录路径
210
+  ipcMain.handle('get-resources-path', async () => {
211
+    try {
212
+      // 获取数据库所在目录作为基础目录
213
+      const dbPath = getDbPath();
214
+      let basePath = '';
215
+      
216
+      if (dbPath) {
217
+        const lastSlashIndex = Math.max(dbPath.lastIndexOf('/'), dbPath.lastIndexOf('\\'));
218
+        if (lastSlashIndex !== -1) {
219
+          basePath = dbPath.substring(0, lastSlashIndex);
220
+        }
221
+      }
222
+      
223
+      // 添加资源子目录
224
+      const resourcesPath = path.join(basePath, 'resources');
225
+      
226
+      // 确保目录存在
227
+      if (!fs.existsSync(resourcesPath)) {
228
+        fs.mkdirSync(resourcesPath, { recursive: true });
229
+      }
230
+      
231
+      return {
232
+        success: true,
233
+        path: resourcesPath
234
+      };
235
+    } catch (error) {
236
+      console.error('获取资源目录路径失败:', error);
237
+      return {
238
+        success: false,
239
+        error: error.message
240
+      };
241
+    }
242
+  });
243
+}
244
+
245
+// 辅助函数:加载cookies到会话
246
+async function loadCookiesForSession(mySession, space) {
247
+  if (space.cookies) {
248
+    for (let cookie of space.cookies) {
249
+      try {
250
+        if (!cookie.url) {
251
+          cookie.url = space.url;
252
+        }
253
+        await mySession.cookies.set(cookie);
254
+      } catch (error) {
255
+        console.log(error);
256
+      }
257
+    }
258
+  } else {
259
+    console.log('No cookies to load');
260
+  }
261
+}
262
+
263
+// 辅助函数:记录历史
264
+function recordHistory(spaceData) {
265
+  // 实现历史记录逻辑
266
+  console.log('Recording history:', spaceData);
267
+}
268
+
269
+// 辅助函数:自动场景(如果需要)
270
+function autoScene(event, data) {
271
+  // 实现autoScene逻辑
272
+  console.log('Auto scene:', data);
273
+  return { success: true };
274
+}
275
+
276
+// 音频处理相关的IPC处理程序设置
277
+function setupAudioProcessingHandlers() {
278
+  // 获取音频时长
279
+  ipcMain.handle('get-audio-duration', async (event, { audioPath }) => {
280
+    try {
281
+      const duration = await getAudioDuration(audioPath);
282
+      return { success: true, duration };
283
+    } catch (error) {
284
+      console.error('获取音频时长失败:', error);
285
+      return { success: false, error: error.message };
286
+    }
287
+  });
288
+
289
+  // 处理项目音频
290
+  ipcMain.handle('process-project-audio', async (event, { projectId, audioPath, segments, outputDir }) => {
291
+    try {
292
+      // 确保输出目录存在
293
+      const audioDir = path.join(outputDir, 'audio');
294
+      const projectDir = path.join(audioDir, `project_${projectId}`);
295
+      ensureDirectoryExists(projectDir);
296
+      
297
+      // 获取音频总时长
298
+      const audioDuration = await getAudioDuration(audioPath);
299
+      console.log(`音频总时长: ${audioDuration}秒`);
300
+      
301
+      // 按照字幕时间切割音频
302
+      const results = [];
303
+      
304
+      for (const segment of segments) {
305
+        // 解析开始和结束时间
306
+        const startSeconds = timeToSeconds(segment.start_time);
307
+        const endSeconds = timeToSeconds(segment.end_time);
308
+        const segmentDuration = endSeconds - startSeconds;
309
+        
310
+        // 输出文件路径
311
+        const outputFileName = `segment_${segment.id}_${segment.segment_id}.mp3`;
312
+        const outputFilePath = path.join(projectDir, outputFileName);
313
+        
314
+        console.log(`处理片段 ${segment.id}: ${startSeconds}s - ${endSeconds}s (${segmentDuration}s)`);
315
+        
316
+        try {
317
+          // 切割音频
318
+          await cutAudioSegment(audioPath, outputFilePath, startSeconds, segmentDuration);
319
+          
320
+          // 添加到结果
321
+          results.push({
322
+            segmentId: segment.id,
323
+            originalStartTime: segment.start_time,
324
+            originalEndTime: segment.end_time,
325
+            outputPath: outputFilePath,
326
+            relativePath: path.join('audio', `project_${projectId}`, outputFileName)
327
+          });
328
+          
329
+        } catch (error) {
330
+          console.error(`切割片段 ${segment.id} 失败:`, error);
331
+        }
332
+      }
333
+      
334
+      return {
335
+        success: true,
336
+        totalSegments: segments.length,
337
+        processedSegments: results.length,
338
+        segments: results
339
+      };
340
+    } catch (error) {
341
+      console.error('处理项目音频失败:', error);
342
+      return { success: false, error: error.message };
343
+    }
344
+  });
345
+}
346
+
347
+// 确保目录存在
348
+function ensureDirectoryExists(directory) {
349
+  if (!fs.existsSync(directory)) {
350
+    fs.mkdirSync(directory, { recursive: true });
351
+    console.log(`创建目录: ${directory}`);
352
+  }
353
+}
354
+
355
+// 获取音频时长(秒)
356
+function getAudioDuration(audioPath) {
357
+  return new Promise((resolve, reject) => {
358
+    const ffmpeg = require('fluent-ffmpeg');
359
+    ffmpeg.ffprobe(audioPath, (err, metadata) => {
360
+      if (err) {
361
+        return reject(err);
362
+      }
363
+      resolve(metadata.format.duration);
364
+    });
365
+  });
366
+}
367
+
368
+// 转换时间格式为秒
369
+function timeToSeconds(timeString) {
370
+  // 处理SRT格式: 00:00:12,345
371
+  const normalizedTime = timeString.replace(',', '.');
372
+  const [hours, minutes, seconds] = normalizedTime.split(':').map(parseFloat);
373
+  return hours * 3600 + minutes * 60 + seconds;
374
+}
375
+
376
+// 切割音频片段
377
+function cutAudioSegment(inputFile, outputFile, startTime, duration) {
378
+  return new Promise((resolve, reject) => {
379
+    const ffmpeg = require('fluent-ffmpeg');
380
+    ffmpeg(inputFile)
381
+      .setStartTime(startTime)
382
+      .setDuration(duration)
383
+      .output(outputFile)
384
+      .on('end', () => {
385
+        console.log(`音频片段已保存: ${outputFile}`);
386
+        resolve();
387
+      })
388
+      .on('error', (err) => {
389
+        console.error('音频处理错误:', err);
390
+        reject(err);
391
+      })
392
+      .run();
393
+  });
394
+}
395
+
396
+module.exports = {
397
+  setupIpcHandlers,
398
+  setupAudioProcessingHandlers
399
+};

+ 245 - 0
src/nodeapi/plugins/pluginHanlder.js

@@ -0,0 +1,245 @@
1
+const { ipcMain, app } = require('electron');
2
+const path = require('path');
3
+const fs = require('fs');
4
+const crypto = require('crypto');
5
+const fetch = require('node-fetch');
6
+const tar = require('tar');
7
+const { exec } = require('child_process');
8
+
9
+function initPluginHandler(ipcMain) {
10
+
11
+    const isPackaged = app.isPackaged
12
+    const resourcesPath = process.resourcesPath
13
+    let pluginsDir = ""
14
+
15
+    if (isPackaged) {
16
+        pluginsDir = path.join(resourcesPath, 'plugins');
17
+    } else {
18
+        pluginsDir = path.join(__dirname, '../../../plugins');
19
+    }
20
+
21
+    console.log(`Plugins directory set to: ${pluginsDir}`);
22
+
23
+    if (!fs.existsSync(pluginsDir)) {
24
+        fs.mkdirSync(pluginsDir, { recursive: true });
25
+        console.log(`Created plugins directory: ${pluginsDir}`);
26
+    }
27
+
28
+    ipcMain.handle('get-local-plugins', (event) => {
29
+        console.log('Fetching local plugins list...');
30
+        const localPlugins = fs.readdirSync(pluginsDir).reduce((acc, folder) => {
31
+            const pluginInfoPath = path.join(pluginsDir, folder, 'plugin_info.json');
32
+            if (fs.existsSync(pluginInfoPath)) {
33
+                const pluginInfo = JSON.parse(fs.readFileSync(pluginInfoPath, 'utf8'));
34
+                acc[folder] = pluginInfo;
35
+            }
36
+            return acc;
37
+        }, {});
38
+        console.log('Local plugins:', localPlugins);
39
+        return localPlugins;
40
+    });
41
+
42
+    ipcMain.handle('download-plugin', async (event, plugin) => {
43
+        const pluginTarUrl = process.platform === 'win32' ? plugin.plugin_win_url : plugin.plugin_mac_url;
44
+        const pluginTarPath = path.join(pluginsDir, `${plugin.folder_name}.tar.gz`);
45
+        const tempTarPath = `${pluginTarPath}.part`;
46
+
47
+        console.log(`Starting download for plugin: ${plugin.plugin_name}`);
48
+        console.log(`Downloading from URL: ${pluginTarUrl}`);
49
+        console.log(`Temporary tar path: ${tempTarPath}`);
50
+
51
+        let downloadedSize = 0;
52
+
53
+        if (fs.existsSync(tempTarPath)) {
54
+            const stats = fs.statSync(tempTarPath);
55
+            downloadedSize = stats.size;
56
+            console.log(`Resuming download from byte: ${downloadedSize}`);
57
+        }
58
+
59
+        const response = await fetch(pluginTarUrl, {
60
+            headers: {
61
+                'Range': `bytes=${downloadedSize}-`
62
+            }
63
+        });
64
+
65
+        const totalSize = parseInt(response.headers.get('content-length'), 10) + downloadedSize;
66
+        console.log(`Total file size: ${totalSize} bytes`);
67
+
68
+        const fileStream = fs.createWriteStream(tempTarPath, { flags: 'a' });
69
+
70
+        response.body.on('data', (chunk) => {
71
+            downloadedSize += chunk.length;
72
+            event.sender.send('download-progress', {
73
+                pluginName: plugin.folder_name,
74
+                progress: (downloadedSize / totalSize) * 100,
75
+            });
76
+        });
77
+
78
+        await new Promise((resolve, reject) => {
79
+            response.body.pipe(fileStream);
80
+            response.body.on('error', reject);
81
+            fileStream.on('finish', resolve);
82
+        });
83
+
84
+        if (downloadedSize === totalSize) {
85
+            console.log('Download complete. Verifying file integrity...');
86
+            fs.renameSync(tempTarPath, pluginTarPath);
87
+            
88
+            const fileBuffer = fs.readFileSync(pluginTarPath);
89
+            const hashSum = crypto.createHash('md5');
90
+            hashSum.update(fileBuffer);
91
+            const hex = hashSum.digest('hex');
92
+
93
+            const expectedMd5 = process.platform === 'win32' ? plugin.plugin_win_md5 : plugin.plugin_mac_md5;
94
+
95
+            if (hex !== expectedMd5) {
96
+                console.error('MD5 checksum mismatch. File integrity verification failed.');
97
+                throw new Error('文件完整性校验失败');
98
+            } else {
99
+                console.log('File integrity verified successfully.');
100
+            }
101
+
102
+            await extractPlugin(plugin, pluginTarPath);
103
+        } else {
104
+            console.error('Download incomplete. Please try again.');
105
+            throw new Error('下载未完成,请重试');
106
+        }
107
+    });
108
+
109
+    async function extractPlugin(plugin, pluginTarPath) {
110
+        const pluginDir = path.join(pluginsDir, plugin.folder_name);
111
+        console.log(`Extracting plugin to: ${pluginDir}`);
112
+
113
+        // 确保解压目标目录存在
114
+        if (!fs.existsSync(pluginDir)) {
115
+            fs.mkdirSync(pluginDir, { recursive: true });
116
+            console.log(`Created directory for plugin extraction: ${pluginDir}`);
117
+        }
118
+
119
+        await tar.x({
120
+            file: pluginTarPath,
121
+            cwd: pluginDir
122
+        });
123
+
124
+        fs.unlinkSync(pluginTarPath);
125
+        console.log(`Deleted temporary tar file: ${pluginTarPath}`);
126
+
127
+        const pluginInfoPath = path.join(pluginDir, 'plugin_info.json');
128
+        fs.writeFileSync(pluginInfoPath, JSON.stringify({
129
+            plugin_name: plugin.plugin_name,
130
+            version: plugin.version,
131
+            port: plugin.port,
132
+            entry_file: plugin.entry_file
133
+        }));
134
+
135
+        console.log(`Plugin extracted and info saved: ${pluginInfoPath}`);
136
+        return {
137
+            plugin_name: plugin.plugin_name,
138
+            version: plugin.version
139
+        };
140
+    }
141
+
142
+    ipcMain.handle('start-plugin', (event, pluginName) => {
143
+        const pluginDir = path.join(pluginsDir, pluginName);
144
+        const pluginInfoPath = path.join(pluginDir, 'plugin_info.json');
145
+        const pluginInfo = JSON.parse(fs.readFileSync(pluginInfoPath, 'utf8'));
146
+
147
+        console.log(`Starting plugin: ${pluginInfo.plugin_name} from ${pluginDir}`);
148
+
149
+        const condaDir = path.join(pluginDir, 'conda');
150
+        const entryFile = path.join(pluginDir, pluginInfo.entry_file);
151
+        const port = pluginInfo.port
152
+
153
+        // 检查 conda 目录和入口文件是否存在
154
+        if (!fs.existsSync(condaDir) || !fs.existsSync(entryFile)) {
155
+            console.error('Plugin installation is incomplete. Please reinstall the plugin.');
156
+            return;
157
+        }
158
+
159
+        const pythonFilePath = path.join(condaDir, 'bin', 'python');
160
+
161
+        // 处理路径中的空格和特殊字符
162
+        const escapedPythonFilePath = `\\"${pythonFilePath}\\"`;
163
+        const escapedStartFilePath = `\\"${entryFile}\\"`;
164
+
165
+        const command = `${escapedPythonFilePath} ${escapedStartFilePath} ${port}`;
166
+        console.log(`Executing command: ${command}`);
167
+
168
+        // 在不同平台上使用不同的命令打开终端
169
+        if (process.platform === 'win32') {
170
+            exec(`start cmd.exe /K "${command}"`);
171
+        } else if (process.platform === 'darwin') {
172
+            let cmd = `osascript -e 'tell application "Terminal" to do script "${command}"'`;
173
+            console.log(cmd)
174
+            exec(cmd);
175
+            // exec(`open -a Terminal "${command}"`);
176
+        } else if (process.platform === 'linux') {
177
+            exec(`gnome-terminal -- bash -c "${command}; exec bash"`);
178
+        }
179
+    });
180
+
181
+    ipcMain.handle('stop-plugin', (event, pluginName) => {
182
+        const pluginDir = path.join(pluginsDir, pluginName);
183
+        const pluginInfoPath = path.join(pluginDir, 'plugin_info.json');
184
+
185
+        console.log(`Stopping plugin: ${pluginName}`);
186
+
187
+        if (fs.existsSync(pluginInfoPath)) {
188
+            const pluginInfo = JSON.parse(fs.readFileSync(pluginInfoPath, 'utf8'));
189
+            const port = pluginInfo.port;
190
+
191
+            if (process.platform === 'win32') {
192
+                // 在 Windows 上使用 netstat 和 taskkill
193
+                exec(`netstat -ano | findstr :${port}`, (err, stdout, stderr) => {
194
+                    if (err) {
195
+                        console.error(`无法查找使用端口 ${port} 的进程:`, err);
196
+                        return;
197
+                    }
198
+
199
+                    const lines = stdout.trim().split('\n');
200
+                    if (lines.length > 0) {
201
+                        const pid = lines[0].trim().split(/\s+/).pop(); // 获取 PID
202
+
203
+                        if (pid) {
204
+                            exec(`taskkill /PID ${pid} /F`, (err, stdout, stderr) => {
205
+                                if (err) {
206
+                                    console.error(`无法终止进程 ${pid}:`, err);
207
+                                    return;
208
+                                }
209
+                                console.log(`使用端口 ${port} 的进程 (PID: ${pid}) 已停止`);
210
+                            });
211
+                        } else {
212
+                            console.log(`未找到使用端口 ${port} 的进程`);
213
+                        }
214
+                    } else {
215
+                        console.log(`未找到使用端口 ${port} 的进程`);
216
+                    }
217
+                });
218
+            } else {
219
+                // 非 Windows 系统使用 lsof
220
+                exec(`lsof -i :${port} -t`, (err, stdout, stderr) => {
221
+                    if (err) {
222
+                        console.error(`无法查找使用端口 ${port} 的进程:`, err);
223
+                        return;
224
+                    }
225
+
226
+                    const pid = stdout.trim();
227
+                    if (pid) {
228
+                        try {
229
+                            process.kill(pid, 'SIGTERM');
230
+                            console.log(`使用端口 ${port} 的进程 (PID: ${pid}) 已停止`);
231
+                        } catch (error) {
232
+                            console.error(`无法终止进程 ${pid}:`, error);
233
+                        }
234
+                    } else {
235
+                        console.log(`未找到使用端口 ${port} 的进程`);
236
+                    }
237
+                });
238
+            }
239
+        } else {
240
+            console.log(`找不到插件 ${pluginName} 的插件信息文件`);
241
+        }
242
+    });
243
+}
244
+
245
+module.exports = { initPluginHandler };

+ 35 - 0
src/nodeapi/plugins/test_api.js

@@ -0,0 +1,35 @@
1
+const { Client } = require("@gradio/client/dist/client.cjs");
2
+const fs = require("fs");
3
+
4
+const readVideoFile = (filePath) => {
5
+    return new Promise((resolve, reject) => {
6
+        fs.readFile(filePath, (err, data) => {
7
+            if (err) {
8
+                return reject(err);
9
+            }
10
+            const blob = new Blob([data], { type: "video/mp4" });
11
+            resolve(blob);
12
+        });
13
+    });
14
+};
15
+
16
+const processVideo = async (videoPath) => {
17
+    try {
18
+        const videoBlob = await readVideoFile(videoPath);
19
+        const client = await Client.connect("http://0.0.0.0:7860/");
20
+        const result = await client.predict("/gradio_process", { 
21
+            video: videoBlob,
22
+            threshold: 27,
23
+        });
24
+
25
+        console.log(result.data);
26
+
27
+    } catch (error) {
28
+        console.error("Error processing video:", error);
29
+    }
30
+};
31
+
32
+processVideo("/path/to/your/video/file.mp4");
33
+
34
+// 调用方法并传入要处理的视频文件路径
35
+processVideo("/Users/hxc/translate_web/translate_web/plugins/video_scene/video/46c04229-4d04-480a-aa27-ee1cc23e3978.mp4");

+ 0 - 0
src/nodeapi/scene/auto_scene.js


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio