test-language-e2e.sh 4.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #!/bin/bash
  2. # test-language-e2e.sh — 端到端测试 zh-CMN + en-US 链路
  3. set -e
  4. API=http://127.0.0.1:3100
  5. echo "=== 创建中文书 (zh-CMN) ==="
  6. ZH_RAW=$(curl -sS -X POST $API/api/book-generator/langgraph/books \
  7. -H 'Content-Type: application/json' \
  8. -d '{"title":"语言测试中文","description":"测试中文内容生成和普通话音频","bookScale":"500","language":"zh-CMN","autoGenerateContent":true,"autoGenerateAudio":false,"generateForeword":false,"generateAfterword":false}')
  9. 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"]))'
  10. ZH_ID=$(echo "$ZH_RAW" | python3 -c 'import json,sys; print(json.load(sys.stdin)["data"]["book"]["id"])')
  11. echo "中文书ID: $ZH_ID"
  12. echo
  13. echo "=== 创建英文书 (en-US) ==="
  14. EN_RAW=$(curl -sS -X POST $API/api/book-generator/langgraph/books \
  15. -H 'Content-Type: application/json' \
  16. -d '{"title":"Language Test English","description":"Test English content and audio","bookScale":"500","language":"en-US","autoGenerateContent":true,"autoGenerateAudio":false,"generateForeword":false,"generateAfterword":false}')
  17. 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"]))'
  18. EN_ID=$(echo "$EN_RAW" | python3 -c 'import json,sys; print(json.load(sys.stdin)["data"]["book"]["id"])')
  19. echo "英文书ID: $EN_ID"
  20. echo
  21. echo "=== 等待 60s 让 AI 生成内容 ==="
  22. sleep 60
  23. echo
  24. echo "=== 查章节和内容语言(每本书看前 2 章标题+摘要) ==="
  25. cd /data/ai/audio/server
  26. node -e "
  27. const p = new (require('@prisma/client').PrismaClient());
  28. (async () => {
  29. for (const id of [$ZH_ID, $EN_ID]) {
  30. const b = await p.book.findUnique({ where: { id }, select: { id: true, title: true, targetLanguage: true, genStage: true } });
  31. const chs = await p.bookChapter.findMany({ where: { bookId: id }, orderBy: { number: 'asc' }, take: 3, select: { id: true, title: true, content: true, genStage: true } });
  32. console.log('--- book '+b.id+' (lang='+b.targetLanguage+', stage='+b.genStage+', '+chs.length+' ch) ---');
  33. for (const c of chs) {
  34. const head = (c.content || '').substring(0, 200);
  35. console.log(' ch#'+c.id+' ['+c.genStage+'] '+c.title);
  36. console.log(' '+head.replace(/\\n/g,' / '));
  37. }
  38. }
  39. await p.\$disconnect();
  40. })();
  41. "
  42. echo
  43. echo "=== 触发音频生成(让 2 本书都进 TtsTask 队列) ==="
  44. for ID in $ZH_ID $EN_ID; do
  45. echo "--- book $ID ---"
  46. # 触发 book 的所有叶节点 audio
  47. curl -sS -X POST "$API/api/book-generator/langgraph/books/$ID/audio" \
  48. -H 'Content-Type: application/json' -d '{}' | head -c 200
  49. echo
  50. done
  51. echo
  52. echo "=== 等待 60s 让 TTS 跑完 ==="
  53. sleep 60
  54. echo
  55. echo "=== 查 TtsTask 状态(应该有 targetLanguage 字段) ==="
  56. cd /data/ai/audio/server
  57. node -e "
  58. const p = new (require('@prisma/client').PrismaClient());
  59. (async () => {
  60. 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 });
  61. for (const t of tasks) {
  62. console.log(' ttsTask#'+t.id+' status='+t.status+' voiceId='+t.voiceId+' targetLang='+t.targetLanguage+' prefV='+t.preferredVendor+' prefM='+t.preferredModel);
  63. }
  64. await p.\$disconnect();
  65. })();
  66. "
  67. echo
  68. echo "=== 查生成的音频文件 (DB: BookChapter.audioUrl) ==="
  69. node -e "
  70. const p = new (require('@prisma/client').PrismaClient());
  71. (async () => {
  72. for (const id of [$ZH_ID, $EN_ID]) {
  73. const chs = await p.bookChapter.findMany({ where: { bookId: id, audioUrl: { not: null } }, take: 3, select: { id: true, title: true, audioUrl: true, audioDuration: true } });
  74. console.log('--- book '+id+' 音频 ---');
  75. for (const c of chs) console.log(' ch#'+c.id+' '+c.title+' dur='+c.audioDuration+'s url='+(c.audioUrl||'').slice(-50));
  76. }
  77. await p.\$disconnect();
  78. })();
  79. "