txagent-y/docs/dev/api/API-02-媒体处理.md

18 KiB
Raw Blame History

API-02 媒体处理MEDIA

共 9 个接口MEDIA-01、MEDIA-02、MEDIA-02A~02E、MEDIA-03、MEDIA-04

存储后端:本项目媒体存储与转码已全量托管给外部 SaaS「老司机媒体库」后端自身不做加密/转码/CDN。

  • 图片:同步上传完成 → 直接返回可用 URL
  • 视频:上传完成后返回 mediaId + processing → 后端后台转发到 SaaS 并轮询转码结果 → 就绪后可播放

状态枚举映射

media.process_status处理状态

DB值 API响应值 说明
1 processing 处理中(视频上传完成,等待转码;图片不会停留在此状态)
2 completed 处理完成
3 failed 处理失败(转码失败/超时/队列繁忙)

图片为同步流程,成功即 completed;视频为异步流程,典型耗时 560 秒。客户端不要把视频上传接口返回视为可播放完成态,必须以 MEDIA-04 的 status=completed 为准。

媒体 URL 说明(重要)

媒体类型 后端返回形态 前端处理
图片类 URL 老司机/CDN 绝对地址。常见为 {img_cn_cdn}/xxx.bnc,也可能是历史兼容绝对地址 后端不会直接返回 /api/media-bnc?url=...。H5 渲染前必须先经过同源代理 helper 转换iOS/Android 按各端现有媒体加载策略处理
视频播放 URL https://{api_host}/client/api/v1/media/:mediaId/main.m3u8?token=... 直接交给 HLS 播放器。后端会再向 LSJ 拉取 m3u8 原文;不需要额外带 Authorization header
视频短预览 URL https://{api_host}/client/api/v1/media/:mediaId/preview.m3u8?token=... <video autoplay muted loop playsinline> 渲染,不是静态图;后端会再向 LSJ 拉取预览 m3u8

后端当前不会把所有图片字段改写成某个前端站点自己的 /api/media-bnc?url=...。 H5 侧应在渲染前,把图片类 URL 通过前端 helper 映射为同源代理地址;不要把接口返回的 LSJ 图片 URL 直接塞进 <img src><video poster>、canvas new Image() 或 CSS background-image。 头像、Banner、帖子封面、评论图片、PPV 图片等都属于“图片类 URL”处理规则一致。 视频类字段不会再直接暴露 movie_cn_cdn / movie_vip_cdn,而是统一返回我方 API 域名下的 m3u8 中转地址;后端为保证签名有效性,视频播放 token 与上游 LSJ 签名都不做落库,每次返回时动态签发。


MEDIA-01 上传图片

项目 说明
接口路径 POST /client/api/v1/media/image
接口用途 上传图片到老司机媒体库
Content-Type multipart/form-data
权限要求 需登录
涉及表 media

接口逻辑:

  1. 校验文件扩展名与 MIMEJPG/PNG/GIF/WEBP和大小上限普通图片 ≤10MB头像/Banner ≤5MB
  2. 流式上传到老司机 /upload/image
  3. 写入 media 表:type=1process_status=2(同步就绪)、storage_path = 老司机返回的 filemetadata = {provider:"lsj", provider_id, file}
  4. 返回 img_cn_cdn + .bnc 的可访问 URL

请求参数FormData

字段 类型 必选 说明
file File 图片文件,支持 JPG/PNG/GIF/WEBP普通图片最大10MB头像/Banner 最大5MB
type string 用途类型avatar/banner/post/ppv/id_card映射 usage_type 2/3/1/4/5

响应数据:

字段 类型 说明
mediaId string 媒体ID
url url 图片 URL后端返回老司机/CDN 绝对地址H5 渲染前需先转同源代理)
thumbnailUrl url 缩略图 / 小图 URL若上游未返回则可能为空H5 渲染规则同 url
blurUrl url 模糊图 / 小图 URL若上游未返回则可能为空H5 渲染规则同 url
mimeType string 文件MIME类型
size number 文件大小(字节)
width number 图片宽度(像素,目前为 0老司机不回传
height number 图片高度(像素,目前为 0
status string 固定为 completed

MEDIA-02 上传视频

项目 说明
接口路径 POST /client/api/v1/media/video
接口用途 上传视频到老司机媒体库
Content-Type multipart/form-data
权限要求 需登录
涉及表 media

接口逻辑:

  1. 校验扩展名、MIMEMP4/MOV/WebM包含 iOS QuickTime/MOV、大小≤1GB
  2. 后端按服务端配置分片调老司机 /upload/byte,最后一片拿到 file/id。当前默认 1MB上限 8MB此前测试环境 4MB 灰度已回退
  3. 写入 media 表:type=2process_status=1storage_path = 老司机返回的 file (原始 mp4 路径)metadata = {provider:"lsj", provider_id}
  4. 推入后台转码轮询队列(内存 channel4 worker、3s 间隔、10 分钟超时);入队阻塞最多 5 秒,仍失败则直接写 process_status=3 并返回 50001 视频处理队列繁忙,请稍后重试
  5. 立即返回 status=processing + mediaId

转码回写:后台 worker 调老司机 /upload/query 拿到 file_status=2 后,把 storage_path 更新为 file_m3u8(真正可播放路径),thumbnail_url 写入 file_preview_m3u8(短预览 m3u8 原始路径),并回填 width/height/duration

请求参数FormData

字段 类型 必选 说明
file File 视频文件,支持 MP4/MOV/WebM包含 iOS QuickTime/MOV最大1GB
type string 用途类型post/ppv映射 usage_type 1/4。视频不支持 id_card

响应数据:

字段 类型 说明
mediaId string 媒体ID
mimeType string 文件MIME类型
size number 文件大小(字节)
status string 固定为 processing(异步转码中)

上传响应仍只返回 mediaId + processingcoverUrl/blurPreviewUrl/signedUrl/width/height/duration 这类完成态字段,需要在转码完成后通过 MEDIA-04 或 MEDIA-03 获取。


MEDIA-02A 初始化客户端分片上传

项目 说明
接口路径 POST /client/api/v1/media/upload/init
接口用途 初始化一次客户端分片上传会话,返回 uploadId
Content-Type application/json
权限要求 需登录
涉及表 无(会话保存在服务端内存态 ChunkedUploadStore

适用场景:

  • 大视频走客户端分片上传,不再使用 multipart/form-data 直接调 MEDIA-02
  • 图片也可走这套协议,但当前 H5 常规图片仍主要使用 MEDIA-01

接口逻辑:

  1. 校验 kindfilenamesizechunkSize
  2. 服务端创建一次分片上传会话,生成 uploadId
  3. 返回服务端确认后的 chunkSizetotalChunks

请求参数JSON

字段 类型 必选 说明
filename string 原始文件名
size number 文件总大小(字节)
chunkSize number 每片大小(字节)
kind string image / video
type string 用途类型:post / ppv / avatar / banner / id_card
mimeType string MIME 类型;未传时由后端按文件名和后续处理兜底识别

响应数据:

字段 类型 说明
uploadId string 分片上传会话 ID
chunkSize number 服务端接受的分片大小
totalChunks number 总分片数
received number[] 已接收的分片索引,初始化时通常为空

服务端对分片上传会话数量有限流;同一用户同时进行中的会话过多时会返回业务错误。


MEDIA-02B 上传单个分片

项目 说明
接口路径 PUT /client/api/v1/media/upload/:uploadId/chunk/:idx
接口用途 上传指定索引的单个分片
Content-Type application/octet-stream
权限要求 需登录
涉及表

接口逻辑:

  1. uploadId 找到服务端分片会话,并校验归属用户
  2. 校验 idx 是否越界
  3. 校验当前分片大小:
    • 非最后一片必须等于 chunkSize
    • 最后一片必须等于剩余大小
  4. 把分片写入服务端临时目录;已上传过的相同分片按幂等成功返回
  5. 返回当前已接收分片数

路径参数:

字段 类型 必选 说明
uploadId string 分片上传会话 ID
idx number 当前分片索引,从 0 开始

请求体:

字段 类型 必选 说明
body binary 当前分片的二进制内容

请求头:

字段 必选 说明
Content-Type 固定 application/octet-stream
Content-Length 建议 当前分片大小;服务端会据此和期望分片大小进行校验
Content-MD5 可选;传入时服务端会校验分片 MD5

响应数据:

字段 类型 说明
uploadId string 分片上传会话 ID
index number 当前分片索引
received number 当前已接收分片数
total number 总分片数
allChunked boolean 是否已收齐全部分片

若某个分片请求没有到达应用层,status/complete 阶段会表现为对应索引仍在 missing 列表中。


MEDIA-02C 查询分片上传状态

项目 说明
接口路径 GET /client/api/v1/media/upload/:uploadId
接口用途 查询某次分片上传会话已收到/缺失的分片
权限要求 需登录
涉及表

路径参数:

字段 类型 必选 说明
uploadId string 分片上传会话 ID

响应数据:

字段 类型 说明
uploadId string 分片上传会话 ID
totalChunks number 总分片数
received number[] 已成功接收的分片索引
missing number[] 当前仍缺失的分片索引

典型用途:

  • 断点续传
  • complete 失败后排查缺失分片
  • 客户端决定是否重传 missing 中的分片

MEDIA-02D 完成客户端分片上传

项目 说明
接口路径 POST /client/api/v1/media/upload/:uploadId/complete
接口用途 在全部分片到齐后合并文件并生成媒体记录
权限要求 需登录
涉及表 media

接口逻辑:

  1. 校验上传会话存在且归属当前用户
  2. 若仍有缺失分片,返回 40901,并拒绝进入合并流程
  3. 合并所有分片为完整文件,并根据真实文件内容嗅探 MIME
  4. 根据 kind 调用后续处理:
    • image:同步上传到老司机图片接口并返回完成态
    • video:先写 media 记录并返回 processing,后台继续执行 上传老司机 -> 转码轮询 -> 更新 completed
  5. 成功或失败后清理上传会话

视频分片完成语义:

  • complete 在服务端确认分片完整、合并成功并生成 mediaId 后即可返回,不再同步等待老司机上传和转码。
  • 视频初始写入 media.process_status=processingstorage_path 为后端占位路径;后台 LSJ 上传成功后会更新为老司机原始视频路径,转码完成后再更新为可播放 m3u8。
  • 后台任务使用内存队列;服务重启期间未完成任务不会自动恢复,相关媒体可能停留在 processing,需后续持久化任务表版本解决。
  • LSJ 上传失败、后台队列失败或转码失败时,media.process_status 会更新为 failed,失败原因通过 MEDIA-04 的 errorMessage 返回。
  • 仅分片视频异步链路在失败终态时会写一条系统站内通知:category=systemtype=systemrelatedType=mediarelatedId=mediaId,标题为“视频上传失败”。
  • 视频真正可播放并进入待审核状态后,后端会写一条系统站内通知:category=systemtype=publish_successrelatedType=mediarelatedId=mediaId,标题为“视频等待审核”。

路径参数:

字段 类型 必选 说明
uploadId string 分片上传会话 ID

响应数据:

字段 类型 说明
mediaId string 媒体ID
mimeType string 文件MIME类型
size number 文件大小(字节)
width number 图片/视频宽度;视频通常在转码完成后才完整回填
height number 图片/视频高度
status string 图片为 completed,视频通常为 processing

40901 的含义是:当前 uploadId 仍有未上传成功的分片,最常见表现是 missing=[0] 或其他缺失索引。

视频场景下,complete 返回 mediaId 只代表“客户端分片已被服务端完整接收并进入后台处理”,不代表视频已经可播放。前端仍需轮询 MEDIA-04通知中心里的“视频等待审核 / 视频上传失败”系统通知只能作为辅助提醒,不能代替状态查询。


MEDIA-02E 取消客户端分片上传

项目 说明
接口路径 DELETE /client/api/v1/media/upload/:uploadId
接口用途 主动终止一次分片上传会话并清理临时文件
权限要求 需登录
涉及表

路径参数:

字段 类型 必选 说明
uploadId string 分片上传会话 ID

接口逻辑:

  1. 校验上传会话存在且归属当前用户
  2. 删除服务端临时分片文件
  3. 清理会话

当前服务端会话是内存态,超时也会被后台 GC 清理;客户端在用户取消上传时仍建议主动调用本接口。


MEDIA-03 获取签名URL

项目 说明
接口路径 GET /client/api/v1/media/:mediaId/signed-url
接口用途 获取媒体文件的对外访问地址
权限要求 需登录;是否返回真实地址由媒体所属内容的访问权限决定
涉及表 media, post_media, post, user_subscription, ppv_unlock, content_unlock

接口逻辑:

  1. 查询 media 获取 storage_pathtypeprocess_status
  2. process_status != 2 → 返回 40901 media 仍在处理中
  3. 判定当前用户是否有访问权限:
    • 自己上传的媒体,直接允许
    • 命中 IM 侧 ppv_unlock,允许
    • 媒体关联到内容时:
      • free:允许
      • subscriber:校验有效订阅且 tier_level >= requiredTierLevel
      • ppv:校验 content_unlock
  4. 根据 type 生成 URL
    • 图片:img_cn_cdn + replaceExt(storage_path, ".bnc")
    • 视频:生成我方 API 域名下的 m3u8 中转地址:
      • 主播放流:/client/api/v1/media/:mediaId/main.m3u8?token=...
      • 预览播放流:/client/api/v1/media/:mediaId/preview.m3u8?token=...
      • 后端收到请求后,再用 movie_cn_cdn + m3u8Path + sign/time/rand/uid 向 LSJ 拉取 m3u8 原文并转发
  5. 返回结果;无权限时不返回 signedUrl,仅返回 hasAccess=false 及预览字段

路径参数:

字段 类型 必选 说明
mediaId string 媒体ID

响应数据:

字段 类型 说明
mediaId string 媒体ID
signedUrl url 图片 .bnc URL / 视频主播放 m3u8 中转地址
coverUrl url 视频预览 m3u8 中转地址(视频时返回;图片为空)
blurPreviewUrl url coverUrl 含义一致,兼容客户端视频预览字段命名
mimeType string 文件MIME类型
size number 文件大小(字节)
expiresAt timestamp 视频播放 token 过期时间戳;图片字段为 0
hasAccess boolean 当前用户是否有访问权限
width number 媒体宽度(像素)
height number 媒体高度(像素)
duration number 视频时长(秒,图片为 0

MEDIA-04 查询媒体处理状态

项目 说明
接口路径 GET /client/api/v1/media/:mediaId/status
接口用途 查询视频上传后的转码进度
权限要求 需登录(只能查自己上传的)
涉及表 media

接口逻辑:

  1. 查询 media,校验 user_id == 当前用户,否则 40301
  2. 返回 process_status 枚举名
  3. process_status=3,返回 process_error

路径参数:

字段 类型 必选 说明
mediaId string 媒体ID

响应数据:

字段 类型 说明
mediaId string 媒体ID
status string 处理状态:processing / completed / failed
progress number 仅有 0(处理中/失败)或 100(完成)两态。老司机 /upload/query 不返回百分比,暂不支持真实进度
signedUrl url 转码完成后返回视频主播放 m3u8 中转地址
coverUrl url 转码完成后返回视频预览 m3u8 中转地址
blurPreviewUrl url coverUrl 含义一致,兼容客户端视频预览字段命名
mimeType string 文件MIME类型
size number 文件大小(字节)
width number 视频宽度(像素)
height number 视频高度(像素)
duration number 视频时长(秒)
errorMessage string 失败原因status=failed时返回

前端建议:视频上传后以 35 秒间隔轮询本接口;拿到 status=completed 后,可直接使用本接口返回的 signedUrl/coverUrl 做回显,或再调用 MEDIA-03 取新的播放地址。不要依赖 progress 做进度条。分片视频在完成转码或进入失败终态后还会进入通知中心系统分类,客户端可用该通知触发刷新,但不应只依赖通知完成业务闭环。