#!/usr/bin/env node const fs = require("node:fs"); const Module = require("node:module"); const path = require("node:path"); const rootDir = path.resolve(__dirname, ".."); function loadEnvFile(filePath, override = false) { if (!fs.existsSync(filePath)) return; const lines = fs.readFileSync(filePath, "utf8").split(/\r?\n/); for (const line of lines) { const trimmed = line.trim(); if (!trimmed || trimmed.startsWith("#")) continue; const normalized = trimmed.startsWith("export ") ? trimmed.slice("export ".length).trim() : trimmed; const match = normalized.match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/); if (!match) continue; const key = match[1]; let value = match[2].trim(); if ( (value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'")) ) { value = value.slice(1, -1); } value = value.replace(/\\n/g, "\n"); if (override || process.env[key] === undefined) { process.env[key] = value; } } } function registerTypeScriptRuntime() { const ts = require("typescript"); const originalResolveFilename = Module._resolveFilename; Module._resolveFilename = function resolveFilename( request, parent, isMain, options, ) { if (request.startsWith("@/")) { return originalResolveFilename.call( this, path.join(rootDir, request.slice(2)), parent, isMain, options, ); } return originalResolveFilename.call(this, request, parent, isMain, options); }; const compile = (module, filename) => { const source = fs.readFileSync(filename, "utf8"); const output = ts.transpileModule(source, { fileName: filename, compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022, esModuleInterop: true, resolveJsonModule: true, jsx: ts.JsxEmit.ReactJSX, moduleResolution: ts.ModuleResolutionKind.Node10, }, }).outputText; module._compile(output, filename); }; require.extensions[".ts"] = compile; require.extensions[".tsx"] = compile; require.extensions[".md"] = (module, filename) => { module.exports = fs.readFileSync(filename, "utf8"); }; } function getAwemeId() { const args = process.argv.slice(2); const fromFlag = args.find((arg) => arg.startsWith("--aweme-id=")); if (fromFlag) return fromFlag.slice("--aweme-id=".length).trim(); const flagIndex = args.findIndex( (arg) => arg === "--aweme-id" || arg === "-a", ); if (flagIndex >= 0) return (args[flagIndex + 1] || "").trim(); return (args.find((arg) => !arg.startsWith("-")) || "").trim(); } function usage() { console.log("用法: npm run asr -- "); console.log("或: node scripts/asr-cli.cjs --aweme-id "); } function logStep(message) { const now = new Date().toISOString(); console.log(`[asr ${now}] ${message}`); } async function main() { loadEnvFile(path.join(rootDir, ".env")); loadEnvFile(path.join(rootDir, ".env.local"), true); registerTypeScriptRuntime(); const awemeId = getAwemeId(); if (!awemeId) { usage(); process.exitCode = 1; return; } logStep(`开始执行 aweme_id=${awemeId}`); const { transcriptAweme } = require(path.join(rootDir, "app/api/asr")); const { prisma } = require(path.join(rootDir, "lib/prisma")); try { const result = await transcriptAweme(awemeId, { log: logStep }); logStep("最终结果:"); console.log(JSON.stringify(result, null, 2)); } finally { await prisma.$disconnect(); } } main().catch((error) => { console.error("[asr] 执行失败:", error); process.exitCode = 1; });