選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 

9 行
3.8 KiB

  1. import fs from 'node:fs';
  2. const dir='reports/bridge-introduction-narration-20260924';
  3. const load=(name,fallback)=>fs.existsSync(dir+'/'+name)?JSON.parse(fs.readFileSync(dir+'/'+name,'utf8')):fallback;
  4. const {profile,clips}=load('generation.json'),quality=load('quality.json',[]),activation=load('activation.json',{}),live=load('live.json',{});
  5. const e=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
  6. const file=url=>'../../../unreal_tran_web/public'+url;
  7. fs.writeFileSync(dir+'/index.html',`<!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>005–008 背景与讲解数字教员</title><style>body{font:16px/1.7 system-ui;margin:0;background:#eef4f1;color:#193c35}main{max-width:1180px;margin:auto;padding:32px}h1{font-size:28px}a{color:#087b63}nav{display:flex;gap:12px;flex-wrap:wrap}article{background:white;border:1px solid #c9dcd5;border-radius:12px;padding:24px;margin:24px 0;display:grid;grid-template-columns:240px 1fr;gap:28px}video{width:100%;aspect-ratio:3/4;background:#eff3f2;border-radius:8px}h2{font-size:21px;margin-top:0}.body{white-space:pre-wrap}.meta{font-size:14px;color:#566d64}img{width:100%;border-radius:10px}details{margin-top:14px}.warn{color:#9b5710}@media(max-width:650px){main{padding:16px}article{grid-template-columns:1fr}video{max-width:240px}}</style><main><h1>005–008 背景与讲解数字教员</h1><p>${e(profile.avatar)} v2 · ${e(profile.voice)} · ${e(profile.engine)} · 480 × 640 / 25 fps</p><p>共 ${clips.length} 段,视频静态引用。画面口型驱动与最终音轨使用同一份处理后的 WAV;只压缩异常长静音,不改变正文。旧步骤讲解保留。</p><p>自动校验核对音轨时差、音频相关性及独立 ASR 文本。ASR 含技术词语同音误识别;这些检查不等于人工听感或逐帧口型验收,请结合视频试听。</p><p>资源接入:${activation.pass?'已接入,原四个任务及操作快照不变':'待资源验收'}。页面验收:${live.pass?'已通过四任务、翻页停播、小屏、异常重试和编排关联':'待完成'}。</p><nav>${['005','006','007','008'].map(x=>`<a href="#TASK-VIRTUAL-${x}">${x} 讲解</a>`).join('')}<a href="quality.json">音频校验记录</a><a href="generation.json">生成与文本记录</a></nav>${clips.map((clip,i)=>{const q=quality.find(q=>q.key===clip.key);return `<article id="${e(clip.key.endsWith('00')?clip.code:clip.key)}"><div><video controls playsinline preload="metadata" poster="${e(file(clip.posterUrl))}" src="${e(file(clip.videoUrl))}"></video><a href="${e(file(clip.audioUrl))}" download>下载 WAV</a> · <a href="${e(file(clip.videoUrl))}" download>下载 MP4</a></div><div><div class="meta">${e(clip.code)} · ${i+1}/${clips.length} · ${clip.duration.toFixed(1)} 秒</div><h2>${e(clip.title)}</h2><div class="body">${e(clip.body)}</div><details><summary>校验记录</summary><p class="${q?.needsTranscriptReview?'warn':'meta'}">${q?.technicalPass?'音轨检查通过':'待音轨检查'} · ASR相似度 ${q?Math.round(q.asrSimilarity*100)+'%':'—'} · 音轨偏移 ${q?.audioLagMs??'—'} ms · ${q?.needsTranscriptReview?'需复核文本':'未发现长段漏读或额外插话'}</p><p>${e(q?.asrText)}</p></details></div></article>`;}).join('')}${live.pass?'<h2>页面与编排</h2><img src="86-page-0.png" alt="1366 像素笔记本页面"><p><a href="desktop.png">桌面</a> · <a href="theme-dark.png">深色</a> · <a href="authoring-438.png">训练编排</a> · <a href="live.json">页面验收记录</a></p>':''}<p>回滚:构建环境设 VITE_BRIDGE_INTRO_NARRATION_RELEASE=none,现有任务恢复仅图文。训练编排的新增视频可清空后保存、发布;原编排完整备份在 before-project-*.json。</p></main></html>`);
  8. console.log(dir+'/index.html');