You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI单接口同时返回带音频的MP4视频与JSON/文本数据的实现方案咨询

FastAPI单接口同时返回带音频的MP4视频与JSON/文本数据的实现方案咨询

兄弟,我明白你想在一个接口里同时返回带音频的MP4和文本/JSON数据的需求,但这里有个核心问题——HTTP响应只能有一种媒体类型,没法同时把二进制视频流和JSON格式的文本塞进同一个响应里,所以你原来的代码直接返回字典肯定会报错。给你两个可行的方案,看哪种更适合你的场景:


方案一:拆分接口(推荐,简单易维护)

这是最符合HTTP规范的做法:一个接口负责返回带音频的视频流,另一个接口返回文本/JSON数据,前端页面同时请求这两个接口即可。

1. 修改后端代码

保留原有的视频流接口,新增一个返回文本数据的接口:

from http import HTTPStatus
from pathlib import Path
import uvicorn
from fastapi import FastAPI, Header, Request, Response
from fastapi.templating import Jinja2Templates

app = FastAPI()
templates = Jinja2Templates(directory="templates")

CHUNK_SIZE = 1024*1024
video_path = Path("dataclasses_part2.mp4")

@app.get("/")
async def read_root(request: Request):
    return templates.TemplateResponse("index.htm", context={"request": request})

# 视频流接口(修复原有逻辑,确保带音频的视频正常播放)
@app.get("/video")
async def video_endpoint(range: str = Header(None)):
    start, end = range.replace("bytes=", "").split("-")
    start = int(start)
    end = int(end) if end else start + CHUNK_SIZE
    # 防止end超出文件大小
    end = min(end, video_path.stat().st_size - 1)
    
    with open(video_path, "rb") as video:
        video.seek(start)
        video_data = video.read(end - start + 1)  # 修正字节读取范围
    
    filesize = str(video_path.stat().st_size)
    headers = {
        'Content-Range': f'bytes {start}-{end}/{filesize}',
        'Accept-Ranges': 'bytes',
        'Content-Length': str(end - start + 1),
    }
    
    return Response(
        video_data,
        status_code=HTTPStatus.PARTIAL_CONTENT,
        headers=headers,
        media_type="video/mp4"
    )

# 新增:返回文本/JSON数据的接口
@app.get("/video-info")
async def get_video_info():
    data_oper = "Some info"  # 这里可以替换成你的业务逻辑生成的文本
    return {"text_data": data_oper}

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

2. 修改前端HTML模板

用JavaScript请求新增的接口,把文本数据渲染到页面上:

<!DOCTYPE html>
<html>
<head>
    <title>FastAPI video streaming</title>
</head>
<body>
    <video width="1200" controls muted="muted">
        <source src="http://localhost:8000/video" type="video/mp4"/>
    </video>
    <h1 id="video-info">Loading info...</h1>

    <script>
        // 异步请求视频文本信息
        fetch('/video-info')
            .then(response => response.json())
            .then(data => {
                document.getElementById('video-info').textContent = data.text_data;
            })
            .catch(error => {
                console.error('加载视频信息失败:', error);
                document.getElementById('video-info').textContent = '加载信息失败';
            });
    </script>
</body>
</html>

方案二:单接口返回Multipart混合数据(不推荐,前端处理复杂)

如果一定要用单个接口返回两种数据,只能用multipart/form-data格式打包视频流和JSON,但浏览器的<video>标签无法直接解析这种格式,需要前端手动拆分数据并转换,复杂度很高。

后端示例代码

from http import HTTPStatus
from pathlib import Path
import json
import uvicorn
from fastapi import FastAPI, Header, Response
from multipart.multipart import MultipartEncoder

app = FastAPI()

CHUNK_SIZE = 1024*1024
video_path = Path("dataclasses_part2.mp4")

@app.get("/combined")
async def combined_endpoint(range: str = Header(None)):
    # 1. 获取视频流数据(和方案一的视频接口逻辑一致)
    start, end = range.replace("bytes=", "").split("-")
    start = int(start)
    end = int(end) if end else start + CHUNK_SIZE
    end = min(end, video_path.stat().st_size - 1)
    
    with open(video_path, "rb") as video:
        video.seek(start)
        video_data = video.read(end - start + 1)
    
    # 2. 准备文本数据
    text_data = {"text_data": "Some info"}
    
    # 3. 打包成Multipart格式
    encoder = MultipartEncoder(
        fields={
            "video": ("video.mp4", video_data, "video/mp4"),
            "info": ("info.json", json.dumps(text_data), "application/json")
        }
    )
    
    return Response(
        encoder,
        media_type=encoder.content_type,
        status_code=HTTPStatus.PARTIAL_CONTENT
    )

前端处理说明

前端需要手动解析Multipart响应,提取视频流并转换成Blob,再生成URL给<video>标签,这部分代码繁琐且容易出问题,除非有特殊业务需求,否则不建议使用。


备注:内容来源于stack exchange,提问作者Motixa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 11:37:33