扫看(scan-watch)
> 扫码即看。把本地一个视频文件,变成一张扫码就能完整观看的二维码。全程 4 步,约 3 分钟。
核心结论(先记住这两条,能省一小时)
- 不要用网盘分享链接做视频分享。 微云/百度网盘对"他人分享的视频"只给 1 分钟试看,看完整版必须登录并转存到自己的网盘——你开会员也解决不了观众侧限制。
- 静态托管(CloudStudio / 各类 Pages)放 MP4 会播不了。 因为服务器不支持 HTTP Range(返回 200 而非 206),iOS Safari 和微信 X5 播 MP4 强制要求字节续传,拿不到就黑屏。必须切 HLS(m3u8 + ts 分片),每片小文件独立下载,不依赖 Range。
环境准备(首次执行一次)
所有依赖装进托管 venv,别污染系统 Python:
VENV="C:/Users/Administrator/.workbuddy/binaries/python/envs/default"
PY="C:/Users/Administrator/.workbuddy/binaries/python/versions/3.13.12/python.exe"
[ -f "$VENV/Scripts/python.exe" ] || "$PY" -m venv "$VENV"
"$VENV/Scripts/python.exe" -m pip install -q -i https://pypi.tuna.tsinghua.edu.cn/simple \
qrcode pillow requests imageio-ffmpeg playwright
- pip 必须用清华源,默认源在本机会卡十几分钟甚至超时。
- ffmpeg 由
imageio-ffmpeg提供,build_site.py会自动发现,无需单独装。 - playwright 不需要下载 chromium:验证脚本优先复用系统 Edge(
channel="msedge"),省 150MB 下载。
工作流
第 1 步:构建 HLS 站点
python scripts/build_site.py "<视频路径>" "<输出目录>" --title "扫码观看视频"
产出目录:index.html、index.m3u8、seg_*.ts、video.mp4(下载兜底)、poster.jpg、hls.min.js。
常用参数:
| 参数 | 说明 |
|------|------|
| --segment 5 | 分片秒数,默认 5。长视频(>10 分钟)可设 10 减少文件数 |
| --skip-copy | 不复制原始 MP4,省一半体积,但会失去"下载视频"兜底 |
| --title | 页面 H1 与二维码共用标题 |
第 2 步:部署到公网
用 workbuddy_cloudstudio_deploy(deferred 工具,先 ToolSearch 加载):
action=deploy directory=<站点目录绝对路径> entry=index.html
返回 shareLink 即公网地址。同一目录再次 deploy 会原地更新,链接不变——所以改完页面不用重做二维码。
第 3 步:先验证,再出码(别跳过)
# 资源可达性(注意:Git Bash 下 -o /dev/null 会让 size_download 恒为 0,务必落到真实文件)
curl -s -o /tmp/m3u8 "<URL>/index.m3u8" -w "%{http_code} %{size_download}\n"
# 真机仿真:能不能播
python scripts/verify_play.py "<URL>" --shot <截图路径>
判定标准:VERDICT: PLAYABLE ✅ —— 即 readyState≥3、videoWidth>0、播放 3 秒后 currentTime 推进。
--ua android 可再跑一遍安卓 UA(走 hls.js 分支,与 iOS 原生分支不同路径)。
第 4 步:生成二维码
python scripts/make_qr.py "<URL>" "<输出PNG路径>" --title "扫码观看视频"
输出 760px 宽的浅色卡片:标题 + 副标题 + 二维码 + 链接文字 + 底部提示。
默认纠错等级 H(30%),扫码容错最好。
交付前最后一步
自己用微信扫一次验证。若有问题,见下方排查表。
排查表
| 现象 | 原因 | 解法 |
|---|---|---|
| 扫码黑屏、转圈不出画面 | 直接放了 MP4,服务器不支持 Range(返回 200 非 206) | 切 HLS:build_site.py 重跑 |
| 页面打不开 / 很慢 | 沙箱冷启动 | 等 10 秒刷新;链接本身不会失效 |
| 微信内提示"已停止访问"或空白 | 外部域名被微信拦截 | 页面已内置提示:右上角「···」→ 用浏览器打开 |
| iOS 有声无画 / 安卓正常 | 编码兼容性 | 重编码:ffmpeg -i in.mp4 -c:v libx264 -profile:v main -pix_fmt yuv420p -c:a aac out.mp4 后重切片 |
| 只有声音没画面 | 分辨率/编码过高 | 压到 720p:-vf scale=1280:-2 -crf 26 |
| 想要更好国内速度 | CloudStudio 网关在境外 | 换 EdgeOne Pages / 腾讯云 COS(支持 Range,可直接用 MP4) |
| 视频太大加载慢 | 码率过高 | 短视频建议 ≤3Mbps;或 --skip-copy 减半体积 |
坑位备忘录
- HLS 切片用
-c copy不重编码,17MB 视频几百毫秒切完,画质零损失。 - hls.js 从 npmmirror 下载并随站部署(415KB),不要引用 CDN——国内访问 jsdelivr 经常失败,一旦 JS 加载不到,安卓端直接没画面。
- 后台跑 pip/下载类任务时,别在前台同步等待;用
run_in_background,完成会自动通知。 - Git Bash 的
curl -o /dev/null会导致%{size_download}为 0 且 exit 23,验证时一定要-o到真实临时文件。 - Windows 下 Python 输出中文:命令前加
PYTHONIOENCODING=utf-8。 - 部署后 先 curl 确认资源大小与本地一致,再出二维码,避免白跑一轮。
一次成功的长什么样(2026-09-05 双 UA 实测)
16.8MB / 720p / 1:24 的视频:
- 切成 9 个 ts 分片 → 部署 → 仿真验证 VERDICT: PLAYABLE ✅
- iPhone UA:readyState=4, duration=84.33, currentSrc=index.m3u8, currentTime 推进到 2.26s
- Android UA:同样 PLAYABLE ✅(走 hls.js 分支)
- 二维码 760×804 PNG(纠错等级 H),微信扫码 2 秒内起播
- 三份脚本均已在本机端到端跑通(build_site / make_qr / verify_play)
文件清单
| 文件 | 作用 |
|---|---|
scripts/build_site.py |
一键构建 HLS 站点(探测信息 / 封面 / 切片 / hls.js / 生成页面) |
scripts/make_qr.py |
生成二维码卡片 PNG |
scripts/verify_play.py |
移动端仿真验证是否真能播 |
assets/player.html |
播放器页面模板(三分支:原生 HLS → hls.js → MP4 兜底) |