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

FastAPI后端向HTML5 video流式传输内存图像失败求助

问题原因

核心问题是用错了HTML元素:<video>标签不支持multipart/x-mixed-replace格式。这个格式是专门用来实现逐帧刷新的图片流(比如MJPEG),应该用<img>标签加载,而非视频标签。浏览器的视频解码器只识别标准视频格式(MP4、WebM等),对这种多部分图片流完全不兼容,所以才会报“无对应解码器”的错误。

解决方案

1. 修改前端HTML(替换为img标签)

把原来的<video>标签换成<img>,不需要autoplay属性,因为multipart/x-mixed-replace流会自动推送新图片并替换旧内容:

<!DOCTYPE html>
<html>
<head>
    <title>Streaming JPEG</title>
</head>
<body>
    <h1>Streaming JPEG</h1>
    <p>Your IP address is {{ request.client.host }}.</p>
    <img src="http://127.0.0.1:8000/video-stream" width="256" height="256" />
    <p>End stream</p>
</body>
</html>

2. 后端代码微调(优化格式严谨性)

你的后端逻辑本身没问题,微调边界符输出顺序后更符合标准multipart格式:

import io
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, StreamingResponse
from fastapi.templating import Jinja2Templates
from PIL import Image
import asyncio

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

@app.get("/", response_class=HTMLResponse)
async def read_item(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})

@app.get("/video-stream")
async def video_stream():
    # 创建红蓝两张图片
    imgs = [
        Image.new('RGB', (256, 256), color='red'),
        Image.new('RGB', (256, 256), color='blue')
    ]
    img_bytes = []
    for img in imgs:
        with io.BytesIO() as output:
            img.save(output, format="JPEG")
            img_bytes.append(output.getvalue())

    async def generate_frames():
        boundary = b"frame"
        # 输出初始边界
        yield b"--%s\r\n" % boundary
        while True:
            for img_data in img_bytes:
                # 输出当前帧的类型头和图片数据
                yield b"Content-Type: image/jpeg\r\n\r\n" + img_data + b"\r\n"
                # 输出下一帧的边界
                yield b"--%s\r\n" % boundary
                await asyncio.sleep(1)

    return StreamingResponse(
        generate_frames(),
        media_type=f"multipart/x-mixed-replace;boundary=frame"
    )

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

3. 测试验证

启动服务后访问http://127.0.0.1:8000/,就能看到img标签每秒交替显示红色和蓝色图片了。

额外说明:如果一定要用video标签

如果必须用video元素(比如需要视频控件、全屏功能),需要把图片序列编码成标准视频格式(如WebM、MP4)再流式传输。这种方式复杂度更高,需要用ffmpeg等工具实时编码,对于简单逐帧显示场景,用img加载multipart流是更轻量的选择。

内容的提问来源于stack exchange,提问作者NumesSanguis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 03:25:07