feat: add real-time caption CLI prototype with Qwen3-ASR
Add a C++/Qt6/CMake CLI prototype that captures the default sink monitor through libpulse and transcribes it in-process with Qwen3-ASR via libllama/libmtmd. Add phase 0/1 verification docs. 新增实时字幕命令行原型:libpulse 采集默认输出 monitor,进程内用 libllama/libmtmd 跑 Qwen3-ASR 推理。附阶段 0/1 验证文档。
This commit is contained in:
commit
18dbc9c8d3
18 files changed
+1682
No files matched your search
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python3
|
||||
"""只抓 GGUF 头部(HTTP Range)读元数据,不下载整个文件。
|
||||
用法: gguf_head.py <url> [<url> ...]"""
|
||||
import sys, struct, urllib.request
|
||||
|
||||
TYPES = {0:1,1:1,2:2,3:2,4:4,5:4,6:4,7:1,8:None,9:None,10:8,11:8,12:8}
|
||||
NAMES = {0:"u8",1:"i8",2:"u16",3:"i16",4:"u32",5:"i32",6:"f32",7:"bool",8:"str",9:"arr",10:"u64",11:"i64",12:"f64"}
|
||||
|
||||
def readstr(b,o):
|
||||
n,=struct.unpack_from("<Q",b,o); o+=8
|
||||
return b[o:o+n].decode("utf-8","replace"), o+n
|
||||
|
||||
def peek(url, limit=4_000_000):
|
||||
req=urllib.request.Request(url, headers={"Range":f"bytes=0-{limit}"})
|
||||
b=urllib.request.urlopen(req, timeout=60).read()
|
||||
assert b[:4]==b"GGUF", "not a GGUF"
|
||||
n_kv,=struct.unpack_from("<Q",b,16); o=24
|
||||
out={}
|
||||
for _ in range(n_kv):
|
||||
k,o=readstr(b,o)
|
||||
t,=struct.unpack_from("<I",b,o); o+=4
|
||||
if t==8:
|
||||
v,o=readstr(b,o)
|
||||
elif t==9:
|
||||
et,=struct.unpack_from("<I",b,o); o+=4
|
||||
n,=struct.unpack_from("<Q",b,o); o+=8
|
||||
if et==8:
|
||||
v=[readstr(b,o)[0] for _ in range(min(n,4))]
|
||||
for _ in range(n): _,o=readstr(b,o)
|
||||
else:
|
||||
o+=n*TYPES[et]; v=f"<{n}x{NAMES[et]}>"
|
||||
else:
|
||||
sz=TYPES[t]; v=int.from_bytes(b[o:o+sz],"little",signed=t in (1,3,5,11)); o+=sz
|
||||
out[k]=v
|
||||
if k=="general.architecture":
|
||||
break
|
||||
return out
|
||||
|
||||
for url in sys.argv[1:]:
|
||||
print(f"=== {url.split('/resolve/')[0].split('/')[-2] + '/' + url.split('/')[-1]} ===")
|
||||
try:
|
||||
m=peek(url)
|
||||
print(" architecture =", m.get("general.architecture"), "| name =", m.get("general.name"))
|
||||
for k,v in m.items():
|
||||
if "clip" in k or "projector" in k or "audio" in k:
|
||||
print(f" {k} = {str(v)[:70]}")
|
||||
except Exception as e:
|
||||
print(" ERR", e)
|
||||
Reference in new issue
Block a user