从零部署开源流媒体下载工具 FlowPick:Nuxt 4 项目本地跑起来 + 二次开发实战

一、前言:为什么值得自己部署一套

FlowPick 是一个隐私优先 的流媒体下载工具,同时提供浏览器扩展和在线网页两种形态,支持 HLS(.m3u8)和 DASH(.mpd)协议的视频流、音频、图片的嗅探、下载、合并与转码。它的核心设计是:所有媒体处理都在浏览器内用 FFmpeg WASM 完成,文件不落第三方服务器

正因为开源、本地处理、可改可部署,很多团队会把它改造成内部工具(比如合规的网课归档、素材采集)。本文以FlowPick官方仓库为例,带你把项目在本地跑起来,并给出二次开发和上线的实操要点。


二、环境准备

依赖 版本建议 说明
Node.js 20 LTS 及以上 Nuxt 4 的运行要求
包管理器 pnpm 仓库脚本基于 pnpm;npm/yarn 亦可但需自行对齐 lockfile
Git 任意新版 拉取源码

确认环境:

bash 复制代码
node -v   # 建议 v20.x 或更高
pnpm -v

三、克隆与依赖安装

以官方仓库为例(若你已 fork,替换成自己的地址即可):

bash 复制代码
git clone https://github.com/ezwebtools/flowpick.git
cd flowpick
pnpm install

注意:package.json 里配了 postinstall 自动执行 nuxt prepare,会生成类型声明和路由清单,首次安装稍慢属正常。如果中途中断,可手动补一次 pnpm exec nuxt prepare


四、本地启动与调试

启动开发服务器:

bash 复制代码
pnpm dev

默认监听 http://localhost:3000。几个常用入口:

  • / ------ 落地页
  • /m3u8-downloader ------ HLS 下载器
  • /dash-downloader ------ DASH 下载器
  • /docs ------ 文档站(基于 @nuxt/content)
  • /blog ------ 博客

调试下载逻辑时建议直接开 /m3u8-downloader/dash-downloader 页面,粘贴流地址即可,比扩展更方便。


五、构建与本地预览

生产构建:

bash 复制代码
pnpm build
pnpm preview

pnpm build 产物在 .output/(Nitro 预设为 cloudflare-pages-static,输出的是静态资源)。本地预览用 pnpm preview 验证产物是否符合预期。

要跑类型检查或 lint:

bash 复制代码
pnpm typecheck
pnpm lint

六、项目结构速览

bash 复制代码
app/
├── pages/                # 路由页:index / m3u8-downloader / dash-downloader / docs / blog ...
├── composables/          # 核心逻辑
│   ├── useStreamMerge.ts # 切片下载、解密、合并、写入(下载引擎核心)
│   └── useFFmpeg.ts      # FFmpeg WASM 加载与转码
├── components/           # UI 组件(Nuxt UI)
content/                  # 文档/博客/多语言落地页(yml + md,Zod 校验)
nuxt.config.ts            # 模块、i18n、路由头、runtimeConfig

下载引擎的两个 composable 是二次开发的重点,对外暴露的接口很清晰,例如:

typescript 复制代码
// useStreamMerge.ts 核心入参
export interface StreamMergeOptions {
  segments: ArrayBuffer[] | AsyncGenerator<ArrayBuffer>
  totalSegments: number
  filename: string
  outputFormat?: 'mp4' | 'ts'
  onProgress?: (progress: StreamMergeProgress) => void
  signal?: AbortSignal
}

七、二次开发实战

1. 改文案 / 文档(零代码)

content/ 下是 Markdown 与 YAML,落地页、文档、博客都在这。改完即生效(dev 热更新),且字段受 content.config.ts 里的 Zod schema 约束,写错会在构建时报出来。比如想加一个中文使用场景文档,直接在 content/zh-Hans/1.docs/ 下新建 .md 并在对应 .navigation.yml 登记即可。

2. 调下载引擎参数

打开 app/composables/useStreamMerge.ts

  • 并发数:默认 2,范围 1--8,可按网络调;
  • 重试策略:指数退避,最多 3 次(仅对网络级临时失败重试,4xx 不重试);
  • 三层写入降级:FSA → StreamSaver → Blob,自动按浏览器能力和文件大小选择;
  • AES-128 解密:走 Web Crypto API,密钥不外传。

想换默认输出格式(MP4/TS)或加自定义合并逻辑,改这里最直接。

3. 改配置(nuxt.config.ts)

  • 多语言i18n.locales 已内置 en / zh-Hans / zh-Hant / ja / ko,增减语言在此;
  • 统计/埋点runtimeConfig.publicclarityIdgaId,对应环境变量 NUXT_PUBLIC_CLARITY_IDNUXT_PUBLIC_GA_ID,不想接就留空;
  • 路由头 :下载器路由配了 Cross-Origin-Opener-Policy: same-origin + Cross-Origin-Embedder-Policy: require-corp这是刻意开启 cross-origin isolation 的,目的见下一节。

八、部署上线要点

默认 Nitro 预设是 cloudflare-pages-static,构建出静态产物,可直接推到 Cloudflare Pages,也能放 Vercel / Netlify / 任意静态托管。

如果要自托管 Node 服务 ,把 nuxt.config.tsnitro.preset 改为 node-server 再构建,用 node .output/server/index.mjs 起服务即可。

环境变量示例(部署平台的环境变量面板配置):

bash 复制代码
NUXT_PUBLIC_GA_ID=G-XXXXXXXXXX
NUXT_PUBLIC_CLARITY_ID=xxxxxxxx

九、避坑提示

  1. 千万别删 COOP/COEP 头 。下载器路由的 require-corp 决定了 cross-origin isolation 是否生效------它同时影响两件事:FFmpeg WASM 能否跑多线程(依赖 SharedArrayBuffer),以及大文件能否走 StreamSaver 跨源流式写入。删了头,大文件下载会退化甚至失败。
  2. FFmpeg WASM 首次加载约 8MB,属正常,后续有缓存。
  3. DRM 内容解不了(如 Widevine),这是设计边界,不是 bug。
  4. Node 版本别太低,Nuxt 4 在 Node 18 及以下会直接起不来。

相关推荐
一个人旅程~1 小时前
房子重新被定义为大宗耐用消费品
经验分享·其他·新浪微博
2501_943205055 小时前
【260期】游戏性能优化,大小核CPU调度工具
经验分享
Ztt66666666618 小时前
六方壶不只看棱角,转得温和才耐看
经验分享·笔记·其他·百度·微信公众平台
嵌入式小周18 小时前
【Altium Designer】安装教程
开源软件
sdffdfdfdfd20 小时前
放下繁琐琐事,专心做教学|十克助教,教培机构的数字化经营管家
经验分享
HW-Header1 天前
何为科研之道?我用一整年的时间去回答这个问题
经验分享·年度总结
小+不通文墨1 天前
--no-multibyte-chars 解决OLED_data.c移植后中文乱码问题
c语言·经验分享·笔记·学习
ychqsq1 天前
95.归位
经验分享·职场和发展
这就是佬们吗1 天前
【硬核投资策略】哈利·布朗永久投资组合深度拆解:穿越任何经济季节的极简全天候方案
java·人工智能·经验分享·笔记