No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

31 líneas
4.8 KiB

  1. import json
  2. from retrain_instructors_v2 import ROOT, REPORT
  3. jobs = json.loads((REPORT / 'jobs.json').read_text('utf-8'))
  4. audio = (ROOT / 'unreal_tran/ute2e/reports/bridge-lipsync-diagnosis-20260914/sample.wav').read_bytes()
  5. (REPORT / 'sample.wav').write_bytes(audio)
  6. cards = []
  7. for row in jobs:
  8. n, ident = row['number'], row['stable_id']
  9. source = (ROOT / '数字人素材' / row['source']).as_uri()
  10. cards.append(f'''<article><h2>教员{n} <span>v2{' · 默认形象' if n == 2 else ''}</span></h2>
  11. <img src="stable-{n}-speaking.png" alt="教员{n}的实时语音驱动截图">
  12. <button onclick="openViewer({n},'{ident}')">打开实时形象预览</button>
  13. <p><a href="{source}">原始 v2 素材</a> · <a href="generated/{ident}/assets/01.mp4">新形象底片(无声)</a></p>
  14. <p class="detail">720 × 960 · 25 FPS · 502 帧<br>原编号:{ident}</p></article>''')
  15. html = '''<!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
  16. <title>三位教员 v2 资源更新与预览</title><style>
  17. *{box-sizing:border-box}body{margin:0;background:#f1f7f5;color:#153e36;font:15px/1.65 system-ui,"Microsoft YaHei",sans-serif}main{max-width:1340px;margin:32px auto;padding:0 24px}h1{font-size:28px;margin-bottom:8px}h2{font-size:20px;margin:0 0 12px}p{margin:10px 0}a{color:#07866d}header,article,.note{background:white;border:1px solid #cfe2dd;border-radius:12px;padding:22px}.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px;margin:20px 0}article img{width:100%;max-height:430px;object-fit:contain;background:#f3f8f7}span{font-size:13px;color:#087b61}button{border:1px solid #148872;background:#148872;color:white;border-radius:7px;padding:10px 16px;font:inherit;cursor:pointer}button:disabled{opacity:.5;cursor:wait}article button{width:100%;margin-top:12px}.detail{font-size:12px;word-break:break-all;color:#56796f}.note{border-left:4px solid #be8d36}dialog{width:min(650px,95vw);max-height:95vh;border:1px solid #bdd7cf;border-radius:12px;padding:18px}dialog::backdrop{background:#102722aa}.viewer-head{display:flex;align-items:center;justify-content:space-between;gap:16px}iframe{display:block;width:100%;height:min(65vh,640px);border:0;background:#eaf1ef;margin:12px 0}.viewer-controls{display:flex;gap:14px;align-items:center}.viewer-controls span{flex:1} @media(max-width:800px){.grid{grid-template-columns:1fr}main{margin:16px auto}}</style>
  18. <main><header><h1>三位教员已更新为 v2 素材</h1><p>2026-09-15 · 已替换共享生成服务、镜像、源码资源包与封面。原有三条形象记录、默认教员2、声音配置保持不变。</p><p><a href="http://127.0.0.1:8003/assets/avatars">打开数字人系统</a> · <a href="catalog-v2.png">查看列表截图</a> · <a href="final-validation.json">核验记录</a> · <a href="ROLLBACK.md">旧版备份位置</a></p></header>
  19. <section class="grid">CARDS</section><section class="note"><strong>本次核验范围</strong><p>三位原编号均已完成实时加载、语音开始/结束、嘴部驱动与资源哈希核验,未出现运行错误。本次检查不代表“嘴型与每个音节完全吻合”已验收。</p><p>约10秒的原始视频会生成正放/倒放循环底片,时长20.08秒。本报告中的实时形象预览展示无声底片;语音驱动测试的截图及记录已保留。之前生成的讲解 MP4 和 WAV 均保留,没有自动重新生成。</p><p>本次用于驱动验证的讲解音频(单独试听,不联动上方预览):</p><audio controls src="sample.wav"></audio></section></main>
  20. <dialog id="preview"><div class="viewer-head"><strong id="viewer-title"></strong><button onclick="closeViewer()">关闭</button></div><iframe id="viewer" title="数字人实时预览" allow="autoplay"></iframe><div class="viewer-controls"><span id="status">加载中</span><a href="http://127.0.0.1:8003/assets/avatars" target="_blank">进入数字人系统</a></div></dialog>
  21. <script>
  22. const origin='http://127.0.0.1:8003';const frame=document.getElementById('viewer'),dialog=document.getElementById('preview'),status=document.getElementById('status');
  23. function openViewer(n,id){status.textContent='正在加载新形象…';document.getElementById('viewer-title').textContent='教员'+n+' · v2 实时预览';dialog.showModal();frame.src=origin+'/human/viewer/'+id;}
  24. function closeViewer(){frame.src='about:blank';dialog.close();}
  25. dialog.addEventListener('cancel',e=>{e.preventDefault();closeViewer()});
  26. addEventListener('message',e=>{if(e.source!==frame.contentWindow||e.origin!==origin)return;if(e.data?.type==='digital-human.ready')status.textContent='v2 形象已就绪(无声预览)';});
  27. </script></html>'''.replace('CARDS', ''.join(cards))
  28. (REPORT / 'index.html').write_text(html, encoding='utf-8')
  29. print('Report written:', REPORT / 'index.html')