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

FastAPI流式传输S3存储桶视频至Vue.js时绑定播放器出错,求解决

解决FastAPI流式S3视频到Vue.js video-player的绑定问题

问题场景

我需要从FastAPI向Vue.js的video-player流式传输S3存储桶中的视频,但遇到了问题:FastAPI返回的流式响应无法绑定到video-player(该组件需要通过src属性加载视频)。我尝试的Vue代码如下:

async videoDownload() {
  var url = '/api/v1/docs/1955/video'
  const resp = await this.axios.get(url);
  console.log("Video is streaming live !!")
  this.videoOptions.sources[0].src = resp;
  this.showvideo = true
},

问题根源

video-player的src属性需要的是可直接访问的资源URL,而不是axios返回的响应对象。浏览器会自动向该URL发起请求,并处理视频流式传输所需的范围请求(断点续传),当前写法完全绕开了浏览器的原生处理逻辑。

修复步骤

1. 调整FastAPI端实现(支持范围请求)

FastAPI必须返回支持范围请求的流式响应,否则视频无法正常播放(比如拖动进度条)。以下是完整的实现代码:

from fastapi import FastAPI, Request, Response, status
from fastapi.responses import StreamingResponse
import boto3
from botocore.exceptions import ClientError

app = FastAPI()

# 初始化S3客户端(建议用环境变量存储密钥,避免硬编码)
s3_client = boto3.client(
    's3',
    aws_access_key_id="你的AWS访问密钥",
    aws_secret_access_key="你的AWS私有密钥"
)

@app.get("/api/v1/docs/{doc_id}/video")
async def stream_video(doc_id: str, request: Request):
    bucket_name = "你的S3存储桶名称"
    # 替换成你的视频文件在S3中的路径规则
    object_key = f"videos/{doc_id}.mp4"
    
    try:
        # 获取视频文件的元数据
        obj_metadata = s3_client.head_object(Bucket=bucket_name, Key=object_key)
        total_length = obj_metadata['ContentLength']
        content_type = obj_metadata.get('ContentType', 'video/mp4')
        
        # 处理浏览器的范围请求(实现断点续传)
        range_header = request.headers.get('range')
        if range_header:
            start, end = range_header.replace('bytes=', '').split('-')
            start = int(start)
            end = int(end) if end else total_length - 1
            # 从S3获取指定范围的字节流
            s3_stream = s3_client.get_object(
                Bucket=bucket_name,
                Key=object_key,
                Range=f'bytes={start}-{end}'
            )['Body']
            
            response = StreamingResponse(
                s3_stream,
                status_code=status.HTTP_206_PARTIAL_CONTENT,
                media_type=content_type
            )
            response.headers['Content-Range'] = f'bytes {start}-{end}/{total_length}'
            response.headers['Content-Length'] = str(end - start + 1)
        else:
            # 返回完整视频流
            s3_stream = s3_client.get_object(Bucket=bucket_name, Key=object_key)['Body']
            response = StreamingResponse(s3_stream, media_type=content_type)
            response.headers['Content-Length'] = str(total_length)
        
        # 告诉浏览器支持范围请求
        response.headers['Accept-Ranges'] = 'bytes'
        return response
    except ClientError:
        return Response(status_code=status.HTTP_404_NOT_FOUND)

2. 简化Vue端代码

直接将API的URL赋值给video-player的src,不需要用axios请求:

async videoDownload() {
  this.videoOptions.sources[0].src = '/api/v1/docs/1955/video';
  this.showvideo = true;
}

原理说明

浏览器的video元素会自动向指定的src URL发起请求,当需要流式播放时,会发送Range请求头。FastAPI端处理该请求后,返回对应范围的视频字节流,从而实现流畅的视频播放体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 01:07:02