ToothpasteLake commited on
Commit
ecc5ae3
·
verified ·
1 Parent(s): 2247396

add demo video + corrected RTF table (5-round medians)

Browse files
Files changed (5) hide show
  1. .gitattributes +1 -0
  2. README.md +16 -2
  3. demo.mp4 +3 -0
  4. demo.mp4.json +75 -0
  5. index.html +21 -8
.gitattributes CHANGED
@@ -46,3 +46,4 @@ static/videos/shiba.mp4 filter=lfs diff=lfs merge=lfs -text
46
  static/videos/steve.mp4 filter=lfs diff=lfs merge=lfs -text
47
  static/videos/teaser.mp4 filter=lfs diff=lfs merge=lfs -text
48
  static/videos/toby.mp4 filter=lfs diff=lfs merge=lfs -text
 
 
46
  static/videos/steve.mp4 filter=lfs diff=lfs merge=lfs -text
47
  static/videos/teaser.mp4 filter=lfs diff=lfs merge=lfs -text
48
  static/videos/toby.mp4 filter=lfs diff=lfs merge=lfs -text
49
+ demo.mp4 filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -13,7 +13,7 @@ short_description: 100% offline ASR for meetings — local, no upload
13
 
14
  100% 离线的会议 / 课堂转写。没有账号,没有云端,拔掉网线它还在写。
15
 
16
- 这个 Space 是**静态证据页**:五个语种的实测输出、RTF 数字、演示视频位。
17
  不放可交互 demo 的原因很实际——转写要在服务端跑 229 MiB 的模型,
18
  而 Hugging Face 免费账号不能运行 CPU 上的 Gradio 容器(`cpu-basic` 返回配额错误,
19
  `zero-a10g` 返回 402,官方文档写明 Gradio/Docker Space 需要付费计划)。
@@ -23,10 +23,24 @@ short_description: 100% offline ASR for meetings — local, no upload
23
  | 文件 | 用途 |
24
  |---|---|
25
  | `index.html` | 实际展示的页面 |
 
 
26
  | `README.md` | 本文件,Space 卡片元数据 |
27
  | `app.py`、`requirements.txt` | **Gradio 版**,本地已跑通;当前 `sdk: static` 不执行它。升级 PRO 后把 frontmatter 改回 `sdk: gradio` 即可切换 |
28
 
29
- ## 模型
 
 
 
 
 
 
 
 
 
 
30
 
31
  权重在 [ToothpasteLake/offlisten-models](https://huggingface.co/ToothpasteLake/offlisten-models),
32
  6 个文件 229.07 MiB,逐文件 sha256 对应发行清单。
 
 
 
13
 
14
  100% 离线的会议 / 课堂转写。没有账号,没有云端,拔掉网线它还在写。
15
 
16
+ 这个 Space 是**静态证据页**:五个语种的实测输出、RTF 分布、演示视频。
17
  不放可交互 demo 的原因很实际——转写要在服务端跑 229 MiB 的模型,
18
  而 Hugging Face 免费账号不能运行 CPU 上的 Gradio 容器(`cpu-basic` 返回配额错误,
19
  `zero-a10g` 返回 402,官方文档写明 Gradio/Docker Space 需要付费计划)。
 
23
  | 文件 | 用途 |
24
  |---|---|
25
  | `index.html` | 实际展示的页面 |
26
+ | `demo.mp4` | 42 秒演示:五段音频真跑,听完才落字;`tools/record-demo.py` 生成 |
27
+ | `demo.mp4.json` | 那次录制的实测记录:每段文本、耗时、音频 sha256 |
28
  | `README.md` | 本文件,Space 卡片元数据 |
29
  | `app.py`、`requirements.txt` | **Gradio 版**,本地已跑通;当前 `sdk: static` 不执行它。升级 PRO 后把 frontmatter 改回 `sdk: gradio` 即可切换 |
30
 
31
+ ## 演示是怎么录的
32
+
33
+ 不是手工录屏。`tools/record-demo.py` 做三件事,所以视频和上表不可能对不上:
34
+
35
+ 1. 用同一份权重、同样 2 线程,真跑五段 `test_wavs`,拿到文本与耗时
36
+ 2. 起本地 `web_live` 服务与无头 Edge,把每段结果按真实时钟推给页面,逐帧截图
37
+ 3. 按同一时钟把五段音频混成音轨,ffmpeg 合成 H.264 + AAC
38
+
39
+ 因此视频里“字幕出现的时刻”就是产品里“一段话说完的时刻”,音画不会漂。
40
+
41
+ ## 模型与音频
42
 
43
  权重在 [ToothpasteLake/offlisten-models](https://huggingface.co/ToothpasteLake/offlisten-models),
44
  6 个文件 229.07 MiB,逐文件 sha256 对应发行清单。
45
+ 表里那五段音频在同一个仓库的 `test_wavs/` 下,点语种名可以直接听,也可以下载后自己复跑。
46
+
demo.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f6a598fae1ae7550cbf7aece507cac5ce8a0457634f3e4456c7e9e8038f16ac6
3
+ size 801685
demo.mp4.json ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "generated_at": "2026-11-12T23:15:38",
3
+ "model": "SenseVoice int8, use_itn=True, threads=2",
4
+ "video": "demo.mp4",
5
+ "video_bytes": 801685,
6
+ "video_seconds": 41.85,
7
+ "frames": 189,
8
+ "rows": [
9
+ {
10
+ "lang": "zh",
11
+ "label": "中",
12
+ "wav": "zh.wav",
13
+ "duration": 5.59,
14
+ "elapsed": 0.45,
15
+ "rtf": 0.081,
16
+ "rtf_min": 0.081,
17
+ "rtf_max": 0.081,
18
+ "rounds": 1,
19
+ "text": "开饭时间早上9点至下午5点。",
20
+ "sha256": "b77f1794fe374a0ba1ee1dc458bfaf9349496cbbfc32780c50ba3c5a7ad8e373"
21
+ },
22
+ {
23
+ "lang": "en",
24
+ "label": "英",
25
+ "wav": "en.wav",
26
+ "duration": 7.15,
27
+ "elapsed": 0.805,
28
+ "rtf": 0.113,
29
+ "rtf_min": 0.113,
30
+ "rtf_max": 0.113,
31
+ "rounds": 1,
32
+ "text": "The tribal chieftain called for the boy and presented him with 50 pieces of code.",
33
+ "sha256": "eb1eb008904465b74c304aad8342e8c7d3c6e61ffe9f66adcaca9cf0f76a93f4"
34
+ },
35
+ {
36
+ "lang": "ja",
37
+ "label": "日",
38
+ "wav": "ja.wav",
39
+ "duration": 7.2,
40
+ "elapsed": 0.623,
41
+ "rtf": 0.087,
42
+ "rtf_min": 0.087,
43
+ "rtf_max": 0.087,
44
+ "rounds": 1,
45
+ "text": "うちの中学は弁当制で持っていきない場合は、50円の学校販売のパンを買う。",
46
+ "sha256": "460bd8dccb0d2a5f4e29c628f837be4082d13defc64c3fc21dd1b6bb0e119095"
47
+ },
48
+ {
49
+ "lang": "ko",
50
+ "label": "韩",
51
+ "wav": "ko.wav",
52
+ "duration": 4.61,
53
+ "elapsed": 0.352,
54
+ "rtf": 0.076,
55
+ "rtf_min": 0.076,
56
+ "rtf_max": 0.076,
57
+ "rounds": 1,
58
+ "text": "조금만 생각을 하면서 살면 훨씬 편할 거야.",
59
+ "sha256": "0dc797a5c81ed30fc339d91f3da718ab02854e17ffa37cb93c4c039ac5c6bb9c"
60
+ },
61
+ {
62
+ "lang": "yue",
63
+ "label": "粤",
64
+ "wav": "yue.wav",
65
+ "duration": 5.15,
66
+ "elapsed": 0.402,
67
+ "rtf": 0.078,
68
+ "rtf_min": 0.078,
69
+ "rtf_max": 0.078,
70
+ "rounds": 1,
71
+ "text": "呢几个字都表达唔到我想讲嘅意思。",
72
+ "sha256": "0960b2db54ae202071d250e6462fbf74a3c863f0e3e7f01273e4939c996875a0"
73
+ }
74
+ ]
75
+ }
index.html CHANGED
@@ -39,6 +39,8 @@
39
  tr:last-child td { border-bottom: 0; }
40
  td.num { font-variant-numeric: tabular-nums; white-space: nowrap; }
41
  td.out { font-size: 13px; color: #d4d9de; }
 
 
42
  video { width: 100%; border: 1px solid var(--line); border-radius: 8px; background: #000; display: block; }
43
  .videohint {
44
  border: 1px dashed var(--line); border-radius: 8px; padding: 28px 20px;
@@ -73,20 +75,25 @@
73
  <div class="tablewrap">
74
  <table>
75
  <thead>
76
- <tr><th>音频</th><th>时长</th><th>耗时</th><th>RTF</th><th>输出</th></tr>
77
  </thead>
78
  <tbody>
79
- <tr><td>中</td><td class="num">5.6 s</td><td class="num">0.45 s</td><td class="num">0.080</td><td class="out">开饭时间早上9点至下午5点。</td></tr>
80
- <tr><td>英</td><td class="num">7.2 s</td><td class="num">0.81 s</td><td class="num">0.114</td><td class="out">The tribal chieftain called for the boy and presented him with 50 pieces of code.</td></tr>
81
- <tr><td>日</td><td class="num">7.2 s</td><td class="num">0.61 s</td><td class="num">0.085</td><td class="out">うちの中学は弁当制で持っていきない場合は50円の学校販売のパンを買う。</td></tr>
82
- <tr><td>韩</td><td class="num">4.6 s</td><td class="num">0.39 s</td><td class="num">0.084</td><td class="out">조금만 생각을 하면서 살면 훨씬 편할 거야.</td></tr>
83
- <tr><td>粤</td><td class="num">5.1 s</td><td class="num">0.45 s</td><td class="num">0.088</td><td class="out">呢几个字都表达唔到我想讲嘅意思。</td></tr>
84
  </tbody>
85
  </table>
86
  </div>
87
 
88
  <p class="note" style="margin-top:12px">
89
- RTF = 转写耗时 ÷ 音频时长,小于 1 表示比实时快。上表是 Windows 本机 2 线程的成绩,换机器会有出入。
 
 
 
 
 
90
  <br>
91
  一处如实标注:同一段中文,官方示例作「<b>开放</b>时间」,int8 量化下这里是「<b>开饭</b>时间」——
92
  我们把它留在表里,而不是挑一条好看的。
@@ -95,7 +102,13 @@ RTF = 转写耗时 ÷ 音频时长,小于 1 表示比实时快。上表是 Win
95
  <h2>演示</h2>
96
 
97
  <video id="demo" controls preload="metadata" src="./demo.mp4" hidden></video>
98
- <p class="videohint" id="demo-hint">演示视频待上传。</p>
 
 
 
 
 
 
99
 
100
  <h2>它和云端转写的区别</h2>
101
  <ul>
 
39
  tr:last-child td { border-bottom: 0; }
40
  td.num { font-variant-numeric: tabular-nums; white-space: nowrap; }
41
  td.out { font-size: 13px; color: #d4d9de; }
42
+ th .thsub { font-weight: 400; font-size: 11px; color: var(--dim); }
43
+ td .rng { font-size: 11px; color: var(--dim); font-weight: 400; }
44
  video { width: 100%; border: 1px solid var(--line); border-radius: 8px; background: #000; display: block; }
45
  .videohint {
46
  border: 1px dashed var(--line); border-radius: 8px; padding: 28px 20px;
 
75
  <div class="tablewrap">
76
  <table>
77
  <thead>
78
+ <tr><th>音频</th><th>时长</th><th>耗时</th><th>RTF<br><span class="thsub">5 轮中位数</span></th><th>输出</th></tr>
79
  </thead>
80
  <tbody>
81
+ <tr><td><a href="https://huggingface.co/ToothpasteLake/offlisten-models/resolve/main/test_wavs/zh.wav">中</a></td><td class="num">5.6 s</td><td class="num">0.56 s</td><td class="num">0.100<br><span class="rng">0.087–0.117</span></td><td class="out">开饭时间早上9点至下午5点。</td></tr>
82
+ <tr><td><a href="https://huggingface.co/ToothpasteLake/offlisten-models/resolve/main/test_wavs/en.wav">英</a></td><td class="num">7.2 s</td><td class="num">0.59 s</td><td class="num">0.083<br><span class="rng">0.077–0.090</span></td><td class="out">The tribal chieftain called for the boy and presented him with 50 pieces of code.</td></tr>
83
+ <tr><td><a href="https://huggingface.co/ToothpasteLake/offlisten-models/resolve/main/test_wavs/ja.wav">日</a></td><td class="num">7.2 s</td><td class="num">0.65 s</td><td class="num">0.090<br><span class="rng">0.080–0.108</span></td><td class="out">うちの中学は弁当制で持っていきない場合は、50円の学校販売のパンを買う。</td></tr>
84
+ <tr><td><a href="https://huggingface.co/ToothpasteLake/offlisten-models/resolve/main/test_wavs/ko.wav">韩</a></td><td class="num">4.6 s</td><td class="num">0.38 s</td><td class="num">0.082<br><span class="rng">0.080–0.087</span></td><td class="out">조금만 생각을 하면서 살면 훨씬 편할 거야.</td></tr>
85
+ <tr><td><a href="https://huggingface.co/ToothpasteLake/offlisten-models/resolve/main/test_wavs/yue.wav">粤</a></td><td class="num">5.1 s</td><td class="num">0.42 s</td><td class="num">0.081<br><span class="rng">0.078–0.099</span></td><td class="out">呢几个字都表达唔到我想讲嘅意思。</td></tr>
86
  </tbody>
87
  </table>
88
  </div>
89
 
90
  <p class="note" style="margin-top:12px">
91
+ 点语种名可以直接听那段音频——五段都在
92
+ <a href="https://huggingface.co/ToothpasteLake/offlisten-models/tree/main/test_wavs">模型仓库的 test_wavs/</a>,
93
+ 和模型一样可下载。转写耗时是 2 个 CPU 线程的中位数,括号里是五轮的极值。
94
+ <br>
95
+ <b>一行精确到三位小数的 RTF 是噪声,不是一个值得炫耀的指标。</b>同一段音频连跑五次能落在 0.077–0.117 之间,
96
+ 所以上表只能读出一件事:处理速度大约是实时的十倍。要当真 benchmark 用,得固定机器、关掉后台、多轮取分布。
97
  <br>
98
  一处如实标注:同一段中文,官方示例作「<b>开放</b>时间」,int8 量化下这里是「<b>开饭</b>时间」——
99
  我们把它留在表里,而不是挑一条好看的。
 
102
  <h2>演示</h2>
103
 
104
  <video id="demo" controls preload="metadata" src="./demo.mp4" hidden></video>
105
+ <p class="videohint" id="demo-hint">演示视频加载中;若浏览器不支持 mp4,可直接<a href="./demo.mp4">下载观看</a>。</p>
106
+
107
+ <p class="note">
108
+ 这 42 秒里没有写好的台词:五段音频先被模型听,听完才落字,和产品里一样按停顿切段。
109
+ 界面是产品的本地文本页,以纯回放模式启动,所以控制区显示「只读文本页」——正常桌面运行时那里是开始/暂停。
110
+ 视频里出现的每个字节都只走过 <code>127.0.0.1</code>。
111
+ </p>
112
 
113
  <h2>它和云端转写的区别</h2>
114
  <ul>