如何用 Docker 和 FastAPI 快速交付一个可用的“万能视频下载工厂”服务|AI辅助编程案例

视频服务容器数据库
为什么要做“万能视频下载工厂”?

最近在工作上有大量的自媒体内容分析的任务,包括AI 爆款分析、AI 内容质检等。但是,所有分析的前期,是批量下载 B 站、YouTube、抖音、快手等平台的视频或音频。

可是,每个平台的架构不同,在进行不同平台音视频下载,都要找不同的脚本、插件,甚至还要手动切换环境、改参数。

基本上,每次换个平台,都是一场“折腾之旅”。

脚本东拼西凑,环境一乱就报错,想自动化更是难上加难。于是打算通过 Cursor 辅助,要做一个“万能视频下载工厂”——我只需要提供一个链接和平台名,剩下的交给 API 自动搞定。

API 化能让团队、AI 工具(比如 Dify)都能一键调用。

这不仅仅是“省事”,更是一次工程化思维的升级。经过 2 天时间的折腾,把整个过程完整的走通了,特地开一篇文章做记录。

一、需求分析与方案设计

和 AI 协作,做项目,最怕“想到哪做到哪”。第一步,先把需求梳理清楚。

  • 支持多平台:B 站、YouTube、抖音、快手,甚至本地文件。
  • API 化:不是写死在脚本里,而是做成标准接口,方便对接各种系统。
  • 可扩展:以后想加新平台,不能推倒重来。
  • 易部署:最好一条命令就能跑起来,别再为环境折腾。

方案选型时,选择了 Python(生态好,爬虫和音视频处理强),FastAPI(写 API 超快),Docker(环境一致,部署无忧),再加上自动化测试兜底。

目标很明确:让“下载”变成一项标准服务,像自来水一样随取随用。

技术选型代码片段:

  
from fastapi import FastAPIapp = FastAPI()
二、代码重构:从脚本到工程化

一开始,我的代码就是一堆“能用就行”的脚本。

picture.image

每个平台一个 py 文件,参数全靠手动改,想测哪个就注释哪个。但很快我发现,这样下去根本没法维护,更别说扩展和自动化了。于是我决定重构:

  • 抽象出一个 Downloader 基类,把通用逻辑提取出来。

Downloader 基类(base.py)

  
from abc import ABC, abstractmethodclass Downloader(ABC):    @abstractmethod    def download(self, url: str):        pass
  • 每个平台写一个子类,实现自己的下载细节。

Bilibili 下载器示例(bilibili_downloader.py)

  
from base import Downloaderclass BilibiliDownloader(Downloader):    def download(self, url: str):        # 伪代码:实际用 bilibili-api 或 you-get/youtube-dl        video\_path = ...        audio\_path = ...        return {"video\_path": video\_path, "audio\_path": audio\_path}
  • 用工厂模式统一管理,想加新平台只需加一个类。

工厂模式(downloader_factory.py)

  
def get\_downloader(platform: str):    if platform == "bilibili":        return BilibiliDownloader()    # 其他平台...

重构后的代码像搭积木一样清晰,每个下载器都能独立测试、独立维护。

从“脚本乱麻”到“模块积木”,这一步让我体会到了工程化的力量。

三、自动化测试:让每个下载器都靠谱

有了模块化的代码,下一步就是让它们“靠谱”——写自动化测试。

我让 AI写了一个测试脚本,可以一键测试所有下载器,也能指定只测某个平台。

每次改完代码,跑一遍测试,心里就有底了。测试过程中也遇到不少坑,比如依赖库缺失、Cookie 配置、环境变量加载等。

picture.image

但正是这些“红叉叉”,让我及时发现并修复了问题,避免了“上线即翻车”。测试不是负担,而是让你大胆重构的底气。现在每次加新功能,我都敢放心大胆地动手,因为有测试兜底。

测试脚本(test_downloaders.py)

  
import argparsefrom downloader\_factory import get\_downloaderdef test\_downloader(platform, url):    downloader = get\_downloader(platform)    result = downloader.download(url)    assert result["video\_path"] and result["audio\_path"]if \_\_name\_\_ == "\_\_main\_\_":    parser = argparse.ArgumentParser()    parser.add\_argument("--downloader", type=str, help="指定下载器")    args = parser.parse\_args()    # 示例:python test\_downloaders.py --downloader bilibili    test\_downloader(args.downloader, "https://www.bilibili.com/video/BV1xxxxxxx")

.env 文件配置(用于抖音/快手 Cookie)

  
DOUYIN\_COOKIE="your\_douyin\_cookie\_here"KUAISHOU\_COOKIE="your\_kuaishou\_cookie\_here"
四、API 封装:让下载能力变成服务

脚本再好,也只能自己用。

要让“下载”变成一个服务,让任何人、任何系统都能一键调用。接下来,用 FastAPI 封装了 RESTful 接口,只需 POST 一个链接和平台名,就能返回音视频的下载地址。

更妙的是,AI 还用 FastAPI 的静态文件服务,把下载好的文件直接映射成可访问的 URL。

这样,外部系统(比如 Dify、前端页面)只需拿到链接就能直接下载,无需关心文件存储细节。

API 是能力的放大器,让工具变成别人的服务。这一步,让万能下载工厂”真正具备了“对外赋能”的能力。

FastAPI 主接口(api.py)

  
from fastapi import FastAPI, HTTPExceptionfrom fastapi.responses import FileResponsefrom downloader\_factory import get\_downloaderapp = FastAPI()@app.post("/download")def download\_video(data: dict):    url = data["url"]    platform = data["platform"]    downloader = get\_downloader(platform)    result = downloader.download(url)    return {        "video\_path": f"/files/{result['video\_path']}",        "audio\_path": f"/files/{result['audio\_path']}"    }# 静态文件服务from fastapi.staticfiles import StaticFilesapp.mount("/files", StaticFiles(directory="downloaded\_files"), name="files")

请求示例(curl)

  
curl -X POST http://127.0.0.1:8000/download \  -H "Content-Type: application/json" \  -d '{"url": "https://www.bilibili.com/video/BV1xxxxxxx", "platform": "bilibili"}'

picture.image

五、Docker 打包:一键部署的魔法

开发环境能跑,不代表生产环境就没问题。依赖、版本、系统环境,分分钟让你“崩溃”。

为了解决“环境地狱”,我用 Docker 把整个项目打包成镜像。

只需一条命令,就能在任何地方一键启动服务。我还用 .dockerignore 排除了不必要的文件,让镜像更小更快。为了方便本地调试和文件管理,我用 -v 参数把容器里的下载目录挂载到本地,所有下载的音视频都能实时同步到电脑上。

Docker 让部署变得像复制粘贴一样简单。这一步,让我的服务从“能用”变成了“随时可用”。

Dockerfile

  
FROM python:3.10-slimWORKDIR /appRUN apt-get update && apt-get install -y --no-install-recommends ffmpeg && rm -rf /var/lib/apt/lists/*COPY requirements.txt .RUN pip install --no-cache-dir -r requirements.txtCOPY . .EXPOSE 8000CMD ["uvicorn", "api:app", "--host", "0.0.0.0", "--port", "8000"]

.dockerignore

  
\_\_pycache\_\_/*.pyc.envtest\_downloaders.logdata/temp\_test\_data/downloaded\_files/

Docker 部署完成后,可以在 Docker 容器内看到 video-downloader 服务已经起来了。

picture.image

点开 prots 看一下,看到网页响应的 message 是 "API is running!"代表这项服务已经通过 Docker 启用了!

picture.image

六、多容器网络互通:Dify 对接实战

当我把下载服务和 Dify 都用 Docker 跑起来后,发现 Dify 的 HTTP 节点死活访问不到 127.0.0.1:8000。

原来,Docker 容器里的 127.0.0.1 只代表自己,地址需要映射成:

http://host.docker.internal:8000/download

立刻就通了!网络互通,是微服务世界的“最后一公里”。这一步,让我的服务真正实现了“系统级联动”,为后续更多自动化场景打下了基础。

picture.image

完成 Dify 工作流搭建后,直接请求 API 服务,完成了音频和视频的下载。这里的地址其实是我本地可访问的地址。

picture.image

看一下效果:音频访问 ☑️

picture.image

视频访问☑️

picture.image

七、AI 助手陪跑:开发效率飞跃

这次项目还有一个最大亮点:AI 助手Cursor全程陪跑。

从需求分析、代码重构、测试调试、Docker 打包,到文档撰写、网络排障,AI 都能给出专业建议和详细操作步骤。遇到报错时,AI 能帮我快速定位问题、给出修复建议;

picture.image

有了 AI 的陪跑,开发过程无比丝滑。AI 不是替代者,而是最强的开发搭子。2 天时间完成一个稳定应用 API 服务发布,这在以前,是根本不敢想的!

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
火山引擎大规模机器学习平台架构设计与应用实践
围绕数据加速、模型分布式训练框架建设、大规模异构集群调度、模型开发过程标准化等AI工程化实践,全面分享如何以开发者的极致体验为核心,进行机器学习平台的设计与实现。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论