基于 Node.js 的 M3U8 解析与下载 API 服务。
支持:
- 解析页面获取 M3U8 地址
- 下载并合并 TS 片段为单一视频文件
- 下载完成后支持多种 存储方式:本地、本地目录、S3、WebDAV、FTP
- 健康检查:
GET /health - 解析页面获取 M3U8:
POST /api/parse - 下载 M3U8 视频(异步):
POST /api/download - 一键流程:解析 + 下载 + 存储(异步):
POST /api/process - 查询任务状态:
GET /api/status/:jobid - 一次性本地下载链接:
GET /files/:id
所有 /api/* 接口默认启用 简单 Token 认证(可通过 .env 控制)。
- Node.js 18+(建议 18 或更新版本,已使用 ES Module 与
node-fetch、puppeteer) - 安装
pnpm或npm
# 安装依赖(任选其一)
pnpm install
# 或
npm install
# 启动服务
node app.js服务默认监听端口:3005,可通过环境变量 PORT 修改。
启动成功后终端会输出类似:
- 健康检查:
http://localhost:3005/health
在项目根目录创建 .env 文件,例如:
PORT=3005
# API 访问 Token(可选,但生产环境强烈推荐配置)
API_TOKEN=your-secret-token
# 本地文件下载链接基础地址(可选)
# 不配置时默认使用当前请求的 protocol + host
DOWNLOAD_BASE_URL=https://your-domain.com- 未配置
API_TOKEN时:认证中间件会 自动跳过认证(方便本地开发)。 - 配置了
API_TOKEN时:调用/api/*需在请求头中携带:x-api-token: your-secret-token
或Authorization: Bearer your-secret-token
- URL:
GET /health - 说明:用于检查服务是否正常运行。
示例响应:
{
"status": "ok",
"message": "Service is running"
}- URL:
POST /api/parse - 认证:需要(取决于
API_TOKEN配置) - 请求体:
{
"url": "https://hsex.men/..."
}当前仅支持
host === 'hsex.men',否则会返回错误。
成功响应示例:
{
"success": true,
"result": [
"https://example.com/path/to/file.m3u8"
],
"title": "页面标题(如果解析到)"
}失败响应示例:
{
"success": false,
"error": "Invalid Host",
"errmsg": "Expected host 'hsex.men', got '...'"
}- URL:
POST /api/download - 认证:需要
- 请求体:
{
"m3u8Url": "https://example.com/file.m3u8",
"outputDir": "data", // 可选,默认 data
"storage": { // 可选,存储配置,见下文
"type": "local"
}
}关键字段说明:
m3u8Url:必填,指向有效的.m3u8文件 URL。outputDir:可选,相对项目根目录的输出目录(默认data)。storage:可选,下载完成后的存储策略:local:仅保留本地文件,并返回可注册的路径local_dir:复制到指定的本地目录s3:上传到 S3 或兼容存储webdav:上传到 WebDAVftp:上传到 FTP
成功响应示例:
{
"success": true,
"jobId": "job-1765890098-abc123",
"message": "Download task started"
}接口会立即返回
jobId,下载任务在后台进行。使用GET /api/status/:jobid查询下载进度和结果。
- URL:
POST /api/process - 认证:需要
- 请求体:
{
"url": "https://hsex.men/...",
"outputDir": "data", // 可选
"storage": { // 可选,存储策略
"type": "local"
}
}处理流程:
- 调用
getM3U8解析页面,获取第一个 M3U8 URL; - 调用
downloadM3U8下载并合并视频; - 调用
handleStorage按配置进行存储(本地、S3、WebDAV、FTP); - 若为本地存储,会生成
downloadUrl供直接下载。
成功响应示例:
{
"success": true,
"jobId": "job-1765890098-abc123",
"message": "Processing task started"
}接口会立即返回
jobId,完整处理流程在后台进行。使用GET /api/status/:jobid查询处理进度和结果。
- URL:
GET /api/status/:jobid - 认证:需要
- 说明:通过
jobId查询异步任务(下载或处理)的执行状态和结果。
成功响应示例:
// 任务进行中(下载状态)
{
"success": true,
"jobId": "job-1765890098-abc123",
"status": "processing",
"progress": 65,
"phase": "downloading",
"downloaded": 65,
"total": 100,
"failed": 0,
"startTime": 1765890098000
}
// 任务完成(本地存储)
{
"success": true,
"jobId": "job-1765890098-abc123",
"status": "completed",
"progress": 100,
"phase": "completed",
"downloaded": 100,
"total": 100,
"failed": 0,
"outputFile": "/abs/path/to/data/xxx.ts",
"storage": {
"success": true,
"type": "local",
"localPath": "/abs/path/to/data/xxx.ts",
"filename": "xxx.ts"
},
"downloadUrl": "http://your-host/files/xxxxxx",
"startTime": 1765890098000,
"endTime": 1765890120000
}
// 任务失败
{
"success": true,
"jobId": "job-1765890098-abc123",
"status": "failed",
"progress": 0,
"phase": "failed",
"error": "Invalid M3U8 URL",
"startTime": 1765890098000,
"endTime": 1765890099000
}关键字段说明:
status:任务状态,可能的值:pending:任务等待中processing:任务处理中completed:任务已完成failed:任务失败
progress:任务进度百分比(0-100)phase:当前执行阶段(parsing, downloading, merging, storing, completed)downloadUrl:仅当任务完成且使用本地存储时返回,指向一次性下载链接
- URL:
GET /files/:id - 说明:通过 ID 下载已经在服务内部注册过的本地文件。
- 用法:无需直接手动调用,一般由
/api/download或/api/process返回的downloadUrl使用。
失败响应示例(ID 无效或过期):
{
"success": false,
"error": "File not found or expired"
}{
"type": "local"
}{
"type": "local_dir",
"path": "/path/to/target/directory"
}- path:必填,目标本地目录的绝对路径。服务会自动创建不存在的目录结构。
{
"type": "s3",
"region": "us-east-1",
"bucket": "your-bucket",
"key": "path/in/bucket/video.ts",
"accessKeyId": "YOUR_ACCESS_KEY",
"secretAccessKey": "YOUR_SECRET_KEY",
"endpoint": "https://s3.your-provider.com", // 可选,自定义 S3 兼容端点
"forcePathStyle": true // 可选,对部分兼容服务必需
}{
"type": "webdav",
"url": "https://webdav.example.com",
"username": "user",
"password": "pass",
"remotePath": "/path/on/server/video.ts"
}{
"type": "webdav",
"url": "https://webdav.example.com",
"username": "user",
"password": "pass",
"path": "/path/on/server"
}配置说明:
url:必填,WebDAV服务器地址username:可选,WebDAV服务器用户名password:可选,WebDAV服务器密码remotePath:可选,完整的远程文件路径(包含文件名)path:可选,远程目录路径(不包含文件名),会自动拼接本地文件名
{
"type": "ftp",
"host": "ftp.example.com",
"port": 21,
"user": "user",
"password": "pass",
"secure": false,
"remotePath": "/path/on/server/video.ts"
}- 配置
API_TOKEN后:- 所有
/api/parse、/api/download、/api/process调用都必须携带有效 Token。
- 所有
- 建议:
- 生产环境务必配置强随机的
API_TOKEN; - 使用 HTTPS 暴露该服务;
- 如需外网开放,再增加额外网关 / 访问控制。
- 生产环境务必配置强随机的
示例调用(curl):
curl -X POST "http://localhost:3005/api/parse" ^
-H "Content-Type: application/json" ^
-H "x-api-token: your-secret-token" ^
-d "{\"url\": \"https://hsex.men/...\"}"- 全局请求日志:打印请求时间、方法、路径及请求体;
- 解析、下载、存储过程均带有详细的
console.log/console.error日志; - 若遇到问题,可直接查看终端输出的 步骤日志 与 错误堆栈。
当前使用 ISC 许可证(见 package.json)。