Emby-Transcoder 是一个轻量级 Go 反向代理,为 Emby 和 Jellyfin 客户端补充本地 FFmpeg HLS 转码能力。
它的目标很窄:普通 API 请求继续透明转发到上游服务;命中配置规则的客户端请求 PlaybackInfo 时,会收到由代理提供的 HLS TranscodingUrl。
Emby / Jellyfin 客户端
|
v
Emby-Transcoder
- 普通请求透明转发
- 按客户端配置匹配 PlaybackInfo
- 将命中的 PlaybackInfo 改写到本地 HLS
- 在本机维护 FFmpeg 转码会话
|
v
上游 Emby / Jellyfin
- 原生 Go 二进制,适合 Linux 部署。
- 普通 Emby/Jellyfin 请求透明反向代理。
- 按
User-Agent、X-Emby-Authorization和X-MediaBrowser-Token匹配客户端配置。 - 对命中的客户端重写 PlaybackInfo。
- 本地 FFmpeg HLS 会话路径为
/streambridge/transcode/。 - 支持通过 Emby
AudioStreamIndex选择音轨,切换音轨时会重启本地转码。 - 通过 Emby
/Sessions/Playing*check-in 和 HLS 访问跟踪播放生命周期。 - 输出目标保守固定为 H.264 视频、AAC 音频、HLS MPEG-TS 分片。
- 软件转码会把视频输出限制到 1920x1080,并保持原始宽高比;VAAPI 模式不做缩放。
- PlaybackInfo 重写时会预热转码会话,减少首次 playlist 请求等待。
- FFmpeg 使用低延迟启动和 GOP 参数,降低首分片延迟。
不包含:虚拟媒体库、RSS、封面生成、刮削、数据库存储或管理 UI。
go run ./cmd/emby-transcoder -config config.example.json然后让客户端连接代理地址,例如 http://linux-host:8097。
使用 Docker Hub 公共镜像 tces1/emby_transcoder:latest。docker/ 目录里的 compose 文件已经指向这个发布好的 linux/amd64 镜像,不会在本地 build。
最小 compose 服务示例:
services:
emby-transcoder:
image: tces1/emby_transcoder:latest
container_name: emby-transcoder
restart: unless-stopped
privileged: true
ports:
- "8097:8097"
devices:
- /dev/dri:/dev/dri
volumes:
- ./config/config.json:/app/config/config.json:ro
- ./data/transcode:/var/lib/emby-transcoder/transcode使用仓库内的 compose 模板:
cd docker
mkdir -p data/transcode
cp config/config.json config/config.local.json启动前修改 docker/config/config.local.json:
- 将
upstream.url改成你的 Emby 或 Jellyfin 地址。 - 如果客户端通过另一层反向代理访问本服务,设置
server.public_url。 server.debug默认保持false,日志更简洁;需要诊断时改成true。transcode.hardware_decode保持""表示不使用硬件加速,走 CPU 转码。- Linux 主机有 Intel 或 AMD
/dev/driVAAPI 支持时,可将transcode.hardware_decode设置为vaapi。 - 当前 VAAPI 模式使用硬件解码加
h264_vaapi硬件编码,不再插入缩放过滤器。 - 启动时会探测 VAAPI 可用性,包括设备初始化和
h264_vaapi;设备、驱动或 ffmpeg 支持缺失时会启动失败。
如果使用 config.local.json,需要把 docker/docker-compose.yml 的挂载改成本地配置文件:
volumes:
- ./config/config.local.json:/app/config/config.json:ro
- ./data/transcode:/var/lib/emby-transcoder/transcode启动或更新服务:
docker compose pull
docker compose up -d
docker compose logs -f停止服务:
docker compose downgo build ./cmd/emby-transcoder复制 config.example.json,然后修改上游地址:
{
"server": {
"listen": ":8097",
"public_url": "",
"debug": false
},
"upstream": {
"url": "http://127.0.0.1:8096"
},
"transcode": {
"enabled": true,
"ffmpeg_path": "/usr/bin/ffmpeg",
"temp_dir": "/var/lib/emby-transcoder/transcode",
"hardware_decode": "",
"hardware_device": "/dev/dri/renderD128",
"max_sessions": 2,
"buffer_pause_seconds": 300,
"buffer_resume_seconds": 120,
"segment_seconds": 2,
"segment_retention_seconds": 300,
"idle_timeout_seconds": 60
}
}客户端直接连接 Emby-Transcoder 时,public_url 留空。服务在另一层反向代理后面时,再设置它。
debug 保持 false 时只输出动作级日志;需要 TRACE_SWITCH 和请求级诊断时设置为 true。
hardware_decode 保持 "" 表示不使用硬件加速,走 CPU 转码。设置为 vaapi 可启用 VAAPI 硬件转码,默认设备是 /dev/dri/renderD128。
当前 VAAPI 模式使用硬件解码加 h264_vaapi 硬件编码,不再插入缩放过滤器。如果设备、驱动或 h264_vaapi 探测失败,服务会停止启动。
Emby-Transcoder 会把本地 FFmpeg 会话绑定到 Emby 播放 check-in:
POST /Sessions/Playing和/Sessions/Playing/Progress更新本地播放状态。POST /Sessions/Playing/Stopped会立即停止匹配的本地 FFmpeg 会话。- HLS playlist 和 segment 请求会刷新媒体访问时间。
segment_seconds控制 HLS 分片时长;默认2秒,兼顾启动延迟和分片数量。设为1启动最快,更高值会减少文件数量和磁盘抖动。- 已转码内容超过播放位置
buffer_pause_seconds时,暂停 FFmpeg。 - 缓冲回落到
buffer_resume_seconds以下时,恢复 FFmpeg。 - 落后当前播放位置超过
segment_retention_seconds的旧分片会从本地缓存删除。 - 如果超过
idle_timeout_seconds没有播放活动或 HLS 访问,idle reaper 会停止会话。 - 新的
master.m3u8请求如果带来不同的上游 stream URL,例如 seek 后StartTimeTicks变化,会重启本地会话。
本仓库代码以 Apache License 2.0 发布,Copyright 2026 tces1。
Docker 镜像中包含的 Debian、FFmpeg 和 VAAPI 相关用户态组件遵循各自上游许可证。