VideoTogether 是一个面向局域网内两人私密观影场景的视频同步应用。
主机端在本机导入视频文件,使用 ffprobe / ffmpeg 处理成 HLS 流,创建私密房间链接,然后把链接发给另一位观看者。观看者不需要安装桌面端,只需要用浏览器打开房间链接即可。
当前主打的是“本机启动、快速分享、两人同步播放”的使用方式。
当前已实现:
- 本地视频导入
ffprobe媒体探测ffmpegHLS 转码与切片.srt、.vtt、.ass字幕导入与转换- 私密房间创建与分享链接
- 浏览器端房间播放
- 两人同步
play / pause / seek - 房间级字幕切换同步
- 参与者在线状态与重连恢复
- Tauri 桌面端主机控制面板
- 一键启动主机流程
apps/
desktop/ Tauri 桌面端主机控制台
server/ Fastify + Socket.IO + SQLite + FFmpeg 服务端
web/ 浏览器端播放与房间页面
packages/
shared-types/
shared-schemas/
shared-utils/
storage/
media/ 上传的原始视频
hls/ 生成的 HLS 清单与分片
subtitles/ 转换后的字幕文件
db/ SQLite 数据库
temp/ 临时处理目录
infra/
docker-compose.yml
scripts/ 启动、停止、打包脚本
你可以直接在 Windows 系统上安装 VideoTogether:
- 请前往 Releases 页面下载最新的 Windows 安装包(
.exe)。 - 双击运行安装程序,按提示完成安装。
- 在
.env.example中配置你的 IP 地址。 - 从开始菜单启动 VideoTogether 即可使用。
打开你常用的终端(例如 powershell),输入以下命令:
> ipconfig你会在输出结果中找到你的 IPv4 地址,看起来像这样:
以太网适配器 以太网:
连接特定的 DNS 后缀 . . . . . . . :
IPv6 地址 . . . . . . . . . . . . : xxxx:xxxx:xxxx:xxxx::xxxx
本地链接 IPv6 地址. . . . . . . . : fe80::xxxx:xxxx:xxxx:xxxx%xx
IPv4 地址 . . . . . . . . . . . . : 10.x.x.x
子网掩码 . . . . . . . . . . . . : 255.255.240.0
默认网关. . . . . . . . . . . . . : fe80::xxxx:xxxx:xxxx:xxxx%xx
10.x.x.x
你需要复制这个 IPv4 地址,并将它粘贴到 输入到应用中 .env.example 文件中LAN IP 输入框内:
...
LAN_IP=10.x.x.x
...完成这些之后就可以了!
正如后文所述,如果你想和不在同一个物理局域网内的人共享视频,你需要用到 ZeroTier。在这种情况下,你需要:
- 下载并安装 ZeroTier
- 和你想共享视频的人加入同一个虚拟局域网
将你在 ZeroTier 面板中分配到的 IP 地址设置为运行应用并配置你的局域网IP.env.example中的LAN_IP。- 和你的朋友一起看电影吧!
成功配置 ZeroTier 后,运行 ipconfig 你应该会看到类似如下的信息:
以太网适配器 ZeroTier One [xxxxxxxxxxxxxxxx]:
连接特定的 DNS 后缀 . . . . . . . :
本地链接 IPv6 地址. . . . . . . . : fe80::xxxx:xxxx:xxxx:xxxx%xx
IPv4 地址 . . . . . . . . . . . . : 10.x.x.x
子网掩码 . . . . . . . . . . . . : 255.255.255.0
默认网关. . . . . . . . . . . . . : 25.x.x.x
这个结果中的 IPv4 地址应该和你自己在 ZeroTier 中的 IP 地址一致。
在主机电脑上需要准备:
- Node.js 22+
- npm 11+
ffmpegffprobe- Rust / Tauri Windows 构建环境
- 开发桌面端或打包桌面安装包时需要
- Docker Desktop
- 仅当
USE_DOCKER=true时需要
- 仅当
推荐从 .env.example 开始。
核心变量如下:
USE_DOCKER- 控制主机启动脚本是否使用 Docker 启动 server
- 默认
false
HOST- server 监听地址
- 如果要让局域网或 ZeroTier 里的 guest 连进来,请使用
0.0.0.0 - 默认
0.0.0.0
PORT- 本地 server 监听端口
- 默认
3000
PUBLIC_PROTOCOL- 生成公开分享链接时使用的协议
- 默认
http
PUBLIC_HOST- 生成公开分享链接时使用的主机名
- 默认
localhost
WEB_DEV_PORTnpm run dev时 Vite 开发服务器使用的端口- 默认
5173
LAN_IP- 桌面端生成局域网房间链接时使用的固定 IPv4
- 请把它设置成你明确要暴露的地址,比如 ZeroTier IPv4
FFMPEG_PATHffmpeg可执行文件路径
FFPROBE_PATHffprobe可执行文件路径
当前 .env.example 的默认思路是:
- 开发模式前端地址:
http://localhost:5173 - 生产式本机 host 流程地址:
http://localhost:3000 - Docker 默认关闭
- 局域网 URL 只使用固定配置的
LAN_IP
在仓库根目录执行:
npm installnpm run host:start这个命令会:
- 构建
web生产产物 - 构建
server生产产物 - 启动本机生产模式 server
- 打开 Tauri 桌面端主机控制面板
默认行为:
- 不使用 Docker
- 分享链接默认指向
http://localhost:3000 - 局域网房间链接只从
LAN_IP生成
停止主机流程:
npm run host:stop这个命令会停止由 host:start 拉起的后台本地 server 进程树。
如果你只想启动本机 server,不打开桌面端:
npm run host:start -- -SkipDesktop桌面端里的推荐流程:
- 选择本地视频文件,或者从已有媒体库中复用视频
- 等待处理完成
- 可选地上传字幕文件
- 选择房间默认字幕
- 设置主机昵称与房间过期时间
- 创建房间
- 复制分享链接并发送给另一位观看者
桌面端还提供:
- 视频处理状态
- 媒体元数据
- 房间状态
- 参与者在线状态
- 字幕更新
- 房间关闭
- 无用媒体删除
- 本机 URL 和局域网 URL 复制
如果你希望桌面端生成局域网 URL,请把 LAN_IP 设置成你想使用的准确 IPv4,例如你的 ZeroTier IPv4。应用不会自动探测局域网 IP。
如果 host 本机能打开房间,但 guest 打不开,先检查 HOST=0.0.0.0,然后把桌面端里的 LAN room URL 发给 guest,而不是 localhost 链接。
观看者不需要桌面端。
只需要:
- 用浏览器打开房间链接
- 输入显示名称
- 加入房间
- 观看同步播放的视频
如果你想让 host:start 通过 Docker 运行 server,请设置:
USE_DOCKER=true然后仍然执行同一个命令:
npm run host:start此时脚本会:
- 使用
infra/docker-compose.yml - 在容器中运行 server
- 挂载本地
storage/*目录 - 保持桌面端仍在宿主机运行
如果你想分别调试 web、server、desktop:
npm run dev:server
npm run dev:web
npm run dev:desktop默认开发地址:
- API:
http://localhost:3000 - Web:
http://localhost:5173 - Desktop dev shell:
npm run dev:desktop
npm run host:start- 构建
web和server的生产产物,启动本地主机 server,并打开 Tauri 桌面端控制面板
- 构建
npm run host:stop- 停止由
host:start拉起的后台 server 进程树
- 停止由
npm run host:start -- -SkipDesktop- 只启动本地主机 server,不打开桌面端
npm run package:desktop- 构建 Tauri 桌面端安装包
npm run dev:server- 以开发 watch 模式运行 Fastify server
npm run dev:web- 以开发模式运行 Vite web 应用
npm run dev:desktop- 以开发模式运行 Tauri 桌面端
npm run build:host- 构建
apps/web和apps/server的生产产物
- 构建
npm run lint- 对所有定义了 lint 脚本的 workspace 执行 ESLint
npm run typecheck- 对所有 workspace 执行 TypeScript 类型检查,并且不产出构建文件
健康检查:
GET /healthGET /api/system/status
房间接口:
POST /api/roomsGET /api/rooms/:tokenPOST /api/rooms/:token/joinPOST /api/rooms/:token/subtitlePOST /api/rooms/:token/close
媒体接口:
GET /api/mediaPOST /api/media/importGET /api/media/:idDELETE /api/media/:idPOST /api/media/:id/processPOST /api/media/:id/subtitlesGET /api/media/:id/subtitles
静态播放资源:
GET /media/:mediaId/*GET /subtitles/:subtitleId.vttGET /GET /room/:token
可以使用 zerotier 来实现不在同一个物理局域网内的视频播放
本项目采用 Apache License 2.0 许可发布,详情请参见 LICENSE 文件。
本项目使用了 FFmpeg(由 GNU Lesser General Public License (LGPL) v2.1 许可授权)。
