用网页浏览器在平板上播放电脑上的视频,支持 ASS 字幕渲染、倍速、快进快退、上下集切换。
python3 server.py /path/to/videos [port]默认端口 8080。启动后会打印局域网地址,平板浏览器打开即可。
# 示例
python3 server.py /run/media/walnut/KIOXIA/Kaguya 8080
# 平板访问 http://192.168.x.x:8080- Python 3.7+(标准库,无需 pip install)
- ffmpeg / ffprobe(用于内嵌字幕探测与提取)
- Chromium 内核浏览器(Chrome、Edge 等;Firefox 不支持 HEVC/FLAC 播放)
| 功能 | 说明 |
|---|---|
| 外挂字幕 | 自动匹配同名 .ass / .ssa / .srt / .vtt 文件 |
| 内嵌字幕 | 自动探测 MKV 内嵌字幕轨道,提取到 /tmp 缓存后播放 |
| ASS 渲染 | JASSUB (libass WASM) 客户端渲染,保留样式/定位/特效 |
| VTT/SRT | ArtPlayer 原生字幕,HTML5 TextTrack |
| 字幕切换 | 右上角字幕按钮,弹出菜单选择轨道 |
| 倍速播放 | ArtPlayer 设置面板 |
| 快进快退 | 键盘左右键 / 播放器控件 |
| 上下集 | 同目录视频自动排序,播放器左下角切换 |
| 进度记忆 | 自动记录上次播放位置 |
| 全屏 | 原生全屏 + Web 全屏(兼容 iOS) |
服务端按文件名匹配同目录下的字幕文件,ASS/SSA 走 JASSUB,SRT/VTT 走 ArtPlayer 原生。
- 播放页面生成时,服务端用
ffprobe探测内嵌字幕轨道 - 用
ffmpeg提取到/tmp/kelly_subs/<hash>.ass(首次约 1-2 秒,后续命中缓存) - 提取后的 ASS 文件通过
/tmpsub/路由提供,与外挂字幕流程完全一致
JASSUB 使用 Noto Sans CJK SC(11MB WOFF2)作为 fallback 字体。ASS 文件中指定的字体(如方正准圆_GBK)未安装时,自动回落到此字体。
关键:availableFonts 的键必须匹配字体的内部家族名(noto sans cjk sc),JASSUB/libass 按字体元数据查找,不认注入时的映射键。
kelly/
├── server.py # 主服务器(单文件,标准库)
├── static/
│ ├── artplayer.js # ArtPlayer 播放器
│ ├── artplayer-plugin-jassub.js # JASSUB 插件(内含 libass JS 层)
│ ├── jassub-worker.js # JASSUB Web Worker
│ ├── jassub-worker.wasm # libass WASM
│ ├── jassub-worker-modern.wasm # libass WASM (SIMD)
│ ├── default.woff2 # Liberation Sans(备用拉丁字体)
│ └── NotoSansCJKsc-Regular.woff2 # CJK 字体
└── README.md
平板浏览器
├── ArtPlayer (HTML5 video player)
│ ├── 倍速 / 快进快退 / 全屏 / 上下集
│ └── 原生字幕 (VTT/SRT via TextTrack)
└── JASSUB (libass WASM)
└── ASS 字幕渲染 (Canvas overlay)
电脑服务器 (Python http.server)
├── / → 主页视频列表
├── /play/<file> → 播放器页面
├── /video/<file>→ 视频流 (HTTP Range 请求)
├── /sub/<file> → 外挂字幕文件
├── /tmpsub/<hash>→ 内嵌字幕缓存 (/tmp)
└── /static/ → 播放器静态资源
- Firefox:不支持 HEVC 编码和 FLAC 音频,视频无法播放
- iPad Safari:可能无法播放 MKV 容器(需 Chromium 内核浏览器)
- 内嵌字幕首次加载:需 1-2 秒提取(ffmpeg),后续从
/tmp缓存读取 - 不支持转码:视频原样提供,浏览器不支持编解码则无法播放
如需替换或添加字体:
# 从 OTF 转换为 WOFF2(推荐格式)
python3 -c "
from fontTools.ttLib import TTFont
font = TTFont('YourFont.otf')
font.flavor = 'woff2'
font.save('static/YourFont.woff2')
"然后在 server.py 的 jassubBase.availableFonts 中添加:
'your font family name': '/static/YourFont.woff2'字体名需与 OTF 内部的 nameID=1(Family Name)匹配,小写。