92 lines
2.5 KiB
JavaScript
92 lines
2.5 KiB
JavaScript
/**
|
|
* CapCut API 基础设施层
|
|
*
|
|
* 提供: 配置加载、API 封装、CLI 解析、工具函数
|
|
* 无业务逻辑,纯基础设施。
|
|
*/
|
|
|
|
const axios = require('axios')
|
|
const path = require('path')
|
|
const fs = require('fs')
|
|
const mm = require('music-metadata')
|
|
|
|
const US = 1_000_000
|
|
|
|
let _config = null
|
|
function getConfig() {
|
|
if (_config) return _config
|
|
const configPath = path.join(__dirname, '..', '..', '..', 'config.json')
|
|
if (!fs.existsSync(configPath)) {
|
|
console.error('缺少配置文件: skills/config.json')
|
|
console.error('请运行 node setup.js 生成配置')
|
|
process.exit(1)
|
|
}
|
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'))
|
|
if (!config.jianyingDraftPath || !config.capcutMateDir || !config.capcutMateApiBase) {
|
|
console.error('config.json 需要填写 jianyingDraftPath、capcutMateDir 和 capcutMateApiBase')
|
|
process.exit(1)
|
|
}
|
|
_config = config
|
|
return _config
|
|
}
|
|
|
|
const BASE_URL = getConfig().capcutMateApiBase
|
|
|
|
async function api(endpoint, data = {}, timeout = 60000) {
|
|
const url = `${BASE_URL}/${endpoint}`
|
|
const method = endpoint === 'get_draft' ? 'get' : 'post'
|
|
try {
|
|
const res = method === 'get'
|
|
? await axios.get(url, { params: data, timeout })
|
|
: await axios.post(url, data, { timeout })
|
|
if (res.data.code !== undefined && res.data.code !== 0) {
|
|
throw new Error(`API [${endpoint}] 返回错误: ${res.data.message} | detail: ${JSON.stringify(res.data).slice(0, 300)}`)
|
|
}
|
|
return res.data
|
|
} catch (err) {
|
|
if (err.response) {
|
|
throw new Error(`API [${endpoint}] HTTP ${err.response.status}: ${JSON.stringify(err.response.data)}`)
|
|
}
|
|
throw err
|
|
}
|
|
}
|
|
|
|
function parseArgs(argv) {
|
|
const args = {}
|
|
for (let i = 0; i < argv.length; i++) {
|
|
if (argv[i].startsWith('--')) {
|
|
const key = argv[i].slice(2)
|
|
const value = argv[i + 1]
|
|
if (value && !value.startsWith('--')) {
|
|
args[key] = value
|
|
i++
|
|
} else {
|
|
args[key] = true
|
|
}
|
|
}
|
|
}
|
|
return args
|
|
}
|
|
|
|
function getResolution(format) {
|
|
const map = {
|
|
'9:16': { width: 1080, height: 1920 },
|
|
'16:9': { width: 1920, height: 1080 },
|
|
'1:1': { width: 1080, height: 1080 },
|
|
'4:3': { width: 1440, height: 1080 },
|
|
}
|
|
return map[format] || map['9:16']
|
|
}
|
|
|
|
async function getAudioDurationSec(filePath) {
|
|
try {
|
|
const metadata = await mm.parseFile(filePath)
|
|
const dur = metadata.format.duration
|
|
return dur > 0 ? dur : null
|
|
} catch (_) {
|
|
return null
|
|
}
|
|
}
|
|
|
|
module.exports = { US, getConfig, BASE_URL, api, parseArgs, getResolution, getAudioDurationSec }
|