该工程使用 FastAPI + 原生前端 + 后台任务队列,支持视频批量转 PDF,且任务不依赖网页连接。
- 目录映射:在网页中输入或使用容器挂载目录作为根目录。
- 文件夹全列出:文件夹列表完整展示,可递归处理。
- 视频不全量展示:通过正则搜索返回结果,支持多个正则(逗号/分号/换行分隔)。
- 算法开关:
FrameDiff可单独使用;也可作为MOG2/KNN的可控二次确认开关。 - 方向开关:可自动检测竖屏素材;若为竖屏,PDF 按横向每页拼接 3 张(不足 3 张用最后一张补齐)。
- 强制竖屏:可开启
强制 9:16,即使原视频是横屏,也会把抽帧图统一转换为竖屏并按竖屏三联排版生成 PDF。 - 后台任务:提交后由后台 Worker 执行,关闭浏览器不影响任务运行。
- 进度可见:网页可查看 Job 列表和 Job 详情(每个视频状态/进度/输出路径)。
- 任务归档:主页仅展示进行中任务(支持停止);已完成任务归档到
/history页面。 - 参数持久化:页面参数和搜索条件会自动保存到
STATE_DIR/settings.json。 - 输出规则:PDF 输出到视频同级目录
pdf/子目录,文件名与视频同名。- 例如
/data/course/a.mp4->/data/course/pdf/a.pdf
- 例如
- 移动端可用:响应式页面,支持手机操作。
engine.py:抽帧、去重、PDF 核心逻辑。job_manager.py:任务队列、后台执行、状态持久化。api_app.py:FastAPI 后端。web/:前端静态页面(HTML/CSS/JS)。Dockerfile/docker-compose.yml:容器化部署。
使用docker-compose.yml
version: "3.9"
services:
video2pdf:
image: ghcr.io/yzmninglang/video2pdf:latest
container_name: video2pdf-batch
user: "0:0"
ports:
- "7862:7862"
volumes:
# 格式为 [宿主机路径]:[容器内路径]
- /vol1/1000/课程:/data
- ./state_data:/state
restart: always
command:
- "--server-name"
- "0.0.0.0"
- "--server-port"
- "7862"
- "--mapped-dir"
- "/data"
- "--state-dir"
- "/state"直接运行
docker run -d \
--name video2pdf-batch \
--user "0:0" \
-p 7862:7862 \
-v /vol1/1000/课程:/data \
-v $(pwd)/state_data:/state \
--restart always \
ghcr.io/yzmninglang/video2pdf:latest \
--server-name 0.0.0.0 \
--server-port 7862 \
--mapped-dir /data \
--state-dir /statecd ~/video2pdf
mkdir -p state_data
STATE_DIR=./state_data HOST_PORT=7861 \
HTTP_PROXY=xxx \
HTTPS_PROXY=xxx \
docker-compose up -d --build访问:
http://127.0.0.1:7861
默认映射:
./example -> /data(视频目录)./state_data -> /state(任务状态与参数持久化)
说明:当前镜像默认以 root 运行,优先保证挂载目录在各种场景下可写。
docker-compose down --remove-orphans
docker rm -f $(docker ps -aq --filter "name=video2pdf-batch") 2>/dev/null || true然后重试 docker-compose up -d --build。
新增了 docker-compose.image.yml,用于直接拉取镜像。
cd ~P/video2pdf
mkdir -p state_data
VIDEO2PDF_IMAGE=video2pdf-batch:latest \
HOST_PORT=7861 STATE_DIR=./state_data \
docker compose -f docker-compose.image.yml pull
VIDEO2PDF_IMAGE=video2pdf-batch:latest \
HOST_PORT=7861 STATE_DIR=./state_data \
docker compose -f docker-compose.image.yml up -d如果你的镜像在远端仓库,例如:
VIDEO2PDF_IMAGE=ghcr.io/your-org/video2pdf-batch:latest \
docker compose -f docker-compose.image.yml up -dGET /health:健康检查。GET /api/defaults:默认映射目录与用户保存的参数。POST /api/settings:保存用户参数(自动调用)。POST /api/scan:扫描目录,仅返回文件夹列表和总视频计数。POST /api/videos/search:按正则搜索视频(支持多模式)。POST /api/jobs:提交后台任务。POST /api/jobs/{job_id}/stop:停止任务,并自动清理该任务当前视频的中间缓存(如生成图片)。GET /api/jobs:任务列表。GET /api/jobs/{job_id}:任务详情。
pip install -r requirements.txt
python api_app.py --mapped-dir ./example --state-dir ./state_data --server-name 0.0.0.0 --server-port 7860浏览器访问:
http://127.0.0.1:7860
该项目离不开如下项目的支持
- binh234/video2slides: Video to Slides Converter
- 本项目也在LINUX DO 社区 进行分享与交流,感谢社区的支持与反馈
