|
@@ -0,0 +1,88 @@
|
|
|
|
|
+#!/bin/bash
|
|
|
|
|
+# test-language-e2e.sh — 端到端测试 zh-CMN + en-US 链路
|
|
|
|
|
+set -e
|
|
|
|
|
+
|
|
|
|
|
+API=http://127.0.0.1:3100
|
|
|
|
|
+
|
|
|
|
|
+echo "=== 创建中文书 (zh-CMN) ==="
|
|
|
|
|
+ZH_RAW=$(curl -sS -X POST $API/api/book-generator/langgraph/books \
|
|
|
|
|
+ -H 'Content-Type: application/json' \
|
|
|
|
|
+ -d '{"title":"语言测试中文","description":"测试中文内容生成和普通话音频","bookScale":"500","language":"zh-CMN","autoGenerateContent":true,"autoGenerateAudio":false,"generateForeword":false,"generateAfterword":false}')
|
|
|
|
|
+echo "$ZH_RAW" | python3 -c 'import json,sys; d=json.load(sys.stdin); b=d["data"]["book"]; print("id="+str(b["id"])+" targetLanguage="+str(b.get("targetLanguage","未设"))+" genStage="+str(b["genStage"]))'
|
|
|
|
|
+ZH_ID=$(echo "$ZH_RAW" | python3 -c 'import json,sys; print(json.load(sys.stdin)["data"]["book"]["id"])')
|
|
|
|
|
+echo "中文书ID: $ZH_ID"
|
|
|
|
|
+
|
|
|
|
|
+echo
|
|
|
|
|
+echo "=== 创建英文书 (en-US) ==="
|
|
|
|
|
+EN_RAW=$(curl -sS -X POST $API/api/book-generator/langgraph/books \
|
|
|
|
|
+ -H 'Content-Type: application/json' \
|
|
|
|
|
+ -d '{"title":"Language Test English","description":"Test English content and audio","bookScale":"500","language":"en-US","autoGenerateContent":true,"autoGenerateAudio":false,"generateForeword":false,"generateAfterword":false}')
|
|
|
|
|
+echo "$EN_RAW" | python3 -c 'import json,sys; d=json.load(sys.stdin); b=d["data"]["book"]; print("id="+str(b["id"])+" targetLanguage="+str(b.get("targetLanguage","未设"))+" genStage="+str(b["genStage"]))'
|
|
|
|
|
+EN_ID=$(echo "$EN_RAW" | python3 -c 'import json,sys; print(json.load(sys.stdin)["data"]["book"]["id"])')
|
|
|
|
|
+echo "英文书ID: $EN_ID"
|
|
|
|
|
+
|
|
|
|
|
+echo
|
|
|
|
|
+echo "=== 等待 60s 让 AI 生成内容 ==="
|
|
|
|
|
+sleep 60
|
|
|
|
|
+
|
|
|
|
|
+echo
|
|
|
|
|
+echo "=== 查章节和内容语言(每本书看前 2 章标题+摘要) ==="
|
|
|
|
|
+cd /data/ai/audio/server
|
|
|
|
|
+node -e "
|
|
|
|
|
+const p = new (require('@prisma/client').PrismaClient());
|
|
|
|
|
+(async () => {
|
|
|
|
|
+ for (const id of [$ZH_ID, $EN_ID]) {
|
|
|
|
|
+ const b = await p.book.findUnique({ where: { id }, select: { id: true, title: true, targetLanguage: true, genStage: true } });
|
|
|
|
|
+ const chs = await p.bookChapter.findMany({ where: { bookId: id }, orderBy: { number: 'asc' }, take: 3, select: { id: true, title: true, content: true, genStage: true } });
|
|
|
|
|
+ console.log('--- book '+b.id+' (lang='+b.targetLanguage+', stage='+b.genStage+', '+chs.length+' ch) ---');
|
|
|
|
|
+ for (const c of chs) {
|
|
|
|
|
+ const head = (c.content || '').substring(0, 200);
|
|
|
|
|
+ console.log(' ch#'+c.id+' ['+c.genStage+'] '+c.title);
|
|
|
|
|
+ console.log(' '+head.replace(/\\n/g,' / '));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ await p.\$disconnect();
|
|
|
|
|
+})();
|
|
|
|
|
+"
|
|
|
|
|
+
|
|
|
|
|
+echo
|
|
|
|
|
+echo "=== 触发音频生成(让 2 本书都进 TtsTask 队列) ==="
|
|
|
|
|
+for ID in $ZH_ID $EN_ID; do
|
|
|
|
|
+ echo "--- book $ID ---"
|
|
|
|
|
+ # 触发 book 的所有叶节点 audio
|
|
|
|
|
+ curl -sS -X POST "$API/api/book-generator/langgraph/books/$ID/audio" \
|
|
|
|
|
+ -H 'Content-Type: application/json' -d '{}' | head -c 200
|
|
|
|
|
+ echo
|
|
|
|
|
+done
|
|
|
|
|
+
|
|
|
|
|
+echo
|
|
|
|
|
+echo "=== 等待 60s 让 TTS 跑完 ==="
|
|
|
|
|
+sleep 60
|
|
|
|
|
+
|
|
|
|
|
+echo
|
|
|
|
|
+echo "=== 查 TtsTask 状态(应该有 targetLanguage 字段) ==="
|
|
|
|
|
+cd /data/ai/audio/server
|
|
|
|
|
+node -e "
|
|
|
|
|
+const p = new (require('@prisma/client').PrismaClient());
|
|
|
|
|
+(async () => {
|
|
|
|
|
+ const tasks = await p.ttsTask.findMany({ where: { chapterId: { in: (await p.bookChapter.findMany({ where: { bookId: { in: [$ZH_ID, $EN_ID] } }, select: { id: true } })).map(c => c.id) } }, orderBy: { id: 'desc' }, take: 5 });
|
|
|
|
|
+ for (const t of tasks) {
|
|
|
|
|
+ console.log(' ttsTask#'+t.id+' status='+t.status+' voiceId='+t.voiceId+' targetLang='+t.targetLanguage+' prefV='+t.preferredVendor+' prefM='+t.preferredModel);
|
|
|
|
|
+ }
|
|
|
|
|
+ await p.\$disconnect();
|
|
|
|
|
+})();
|
|
|
|
|
+"
|
|
|
|
|
+
|
|
|
|
|
+echo
|
|
|
|
|
+echo "=== 查生成的音频文件 (DB: BookChapter.audioUrl) ==="
|
|
|
|
|
+node -e "
|
|
|
|
|
+const p = new (require('@prisma/client').PrismaClient());
|
|
|
|
|
+(async () => {
|
|
|
|
|
+ for (const id of [$ZH_ID, $EN_ID]) {
|
|
|
|
|
+ const chs = await p.bookChapter.findMany({ where: { bookId: id, audioUrl: { not: null } }, take: 3, select: { id: true, title: true, audioUrl: true, audioDuration: true } });
|
|
|
|
|
+ console.log('--- book '+id+' 音频 ---');
|
|
|
|
|
+ for (const c of chs) console.log(' ch#'+c.id+' '+c.title+' dur='+c.audioDuration+'s url='+(c.audioUrl||'').slice(-50));
|
|
|
|
|
+ }
|
|
|
|
|
+ await p.\$disconnect();
|
|
|
|
|
+})();
|
|
|
|
|
+"
|