FastAPI 是一个快速、现代的 Web 框架,以支持异步 REST API 和易于使用而闻名。
在本文中,我们将了解如何使用 FastAPI 在前端流式传输视频。
流式响应
1. 流式传输本地视频
FastAPI 提供了一个专门用于流式传输的 StreamingResponse 类。StreamingResponse 类接收一个生成器或迭代器,并对响应进行流式处理。
下面是一个将本地视频流传输到浏览器的简单示例。
# localvid.py
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
app = FastAPI()
# Video path
vid_path = 'sample_video.mp4'
# Function to stream local video
def stream_local_video():
with open(vid_path, 'rb') as vid_file:
yield from vid_file
# Path to stream video
@app.get("/")
def video_stream():
return StreamingResponse(stream_local_video(), media_type='video/mp4')
我们从 fastapi.responses
模块中导入了 StreamingResponse
类。
在 video_stream()
路径操作函数中,我们使用 StreamingResponse
返回了响应。我们将生成器函数 stream_local_video()
和 media_type
作为参数传递给 StreamingResponse
类。
生成器函数 stream_local_video()
会读取视频的字节,然后对字节进行迭代,迭代后的每一部分都会被生成。
以下命令将在 http://127.0.0.1:8000/ 上运行服务器并流式传输视频。
> fastapi dev localvid.py
╭────────── FastAPI CLI - Development mode ───────────╮
│ │
│ Serving at: http://127.0.0.1:8000 │
│ │
│ API docs: http://127.0.0.1:8000/docs │
│ │
│ Running in development mode, for production use: │
│ │
│ fastapi run │
│ │
╰─────────────────────────────────────────────────────╯
2. 流式传输在线视频
# onlinevid.py
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import requests
app = FastAPI()
# Video URL
vid_url = 'https://cdn.pixabay.com/video/2023/07/28/173530-849610807_large.mp4'
# Function to stream online video
def stream_online_video(url):
response = requests.get(url, stream=True)
for portion in response.iter_content(chunk_size=1024*1024):
yield portion
# Path to stream video
@app.get("/")
def video_stream():
return StreamingResponse(stream_online_video(vid_url), media_type='video/mp4')
在本例中,我们使用 requests
库从 URL 抓取视频内容,并设置了 stream=True(避免一次性将视频读入内存)。然后,我们迭代并分块生成视频内容(每次 1024 字节)。
当我们运行服务器时,它将从 URL 提供视频。
我们可以在端点中指定 URL,而不是硬编码 URL。
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import requests
app = FastAPI()
# Function to stream online video
def stream_online_video(url):
response = requests.get(url, stream=True)
for portion in response.iter_content(chunk_size=1024*1024):
yield portion
# Path to stream video
@app.get("/")
def video_stream(url):
return StreamingResponse(stream_online_video(url), media_type='video/mp4')
在本例中,我们修改了路径操作函数 video_stream()
以接受 URL。
现在,我们可以在端点中以以下格式指定视频的 URL。
http://127.0.0.1:8000/?url=https://cdn.pixabay.com/video/2023/07/28/173530-849610807_large.mp4
我们还可以使用 async 使路径操作函数异步。
文件响应
1. 流式传输本地视频
类FileResponse
仅获取一个文件并流式传输响应。
from fastapi import FastAPI
from fastapi.responses import FileResponse
app = FastAPI()
# Video path
vid_path = 'video.mp4'
# Path to stream video
@app.get("/")
def video_stream():
return FileResponse(vid_path, media_type='video/mp4')
在上面的示例中,我们只是在 FileResponse
类中传递了一个视频文件并返回了响应。
我们并没有像在 StreamingResponse
中那样读取和遍历视频的字节来对其进行流式处理。
FileResponse 类非常适合相对较小或中等大小的文件,因为它会在内存中加载文件。大文件将消耗更多内存。
2. 流式传输在线视频
使用 FileResponse
从 URL 流式传输视频与流式传输本地视频不同。我们知道,FileResponse
类接收文件并将其流式传输。
from fastapi import FastAPI
from fastapi.responses import FileResponse
import requests
import os
app = FastAPI()
# Video URL
vid_url = 'https://cdn.pixabay.com/video/2023/07/28/173530-849610807_large.mp4'
local_vid = 'sample_video.mp4'
# Function to save video from URL
def save_as_file(url, path):
if not os.path.exists(path):
response = requests.get(url)
with open('sample_video.mp4', 'wb') as vid:
vid.write(response.content)
save_as_file(vid_url, local_vid)
# Path to stream video
@app.get("/")
def video_stream():
return FileResponse(local_vid, media_type='video/mp4')
在本例中,我们使用 FileResponse 从 URL 流式传输视频,而不是流式传输本地视频。
这并不是最好的做法,因为我们首先将 URL 中的视频保存在本地机器中,然后才串流视频。
FileResponse 类最好用于本地文件,而不是网络内容。
这就是将视频直接流式传输到浏览器的全部过程,但我们并不想每次都这样做,相反,我们希望在网站的登陆页面上流式传输视频。
在前端流式传输视频
那么,如何使用 FastAPI 在前端流式传输视频呢?我们需要使用 HTML 创建一个前端,然后流式传输视频。
首先,创建一个名为 serve_video 或其他任何你想命名的目录,并创建以下文件和子目录。
serve_video/
- templates/
- display_video.html
- app.py
app.py
文件将包含我们的后端代码,该display_video.html
文件将包含前端代码。
app.py
from fastapi import FastAPI, Request
from fastapi.responses import StreamingResponse, HTMLResponse
from fastapi.templating import Jinja2Templates
import requests
app = FastAPI()
templates = Jinja2Templates(directory="templates")
vid_urls = [
"https://cdn.pixabay.com/video/2023/07/28/173530-849610807_large.mp4",
'https://cdn.pixabay.com/video/2024/03/31/206294_large.mp4',
'https://cdn.pixabay.com/video/2023/10/11/184510-873463500_large.mp4',
'https://cdn.pixabay.com/video/2023/06/17/167569-837244635_large.mp4'
]
# Stream the video from the URL
def stream_video(url):
response = requests.get(url, stream=True)
for portion in response.iter_content(chunk_size=1024*1024):
yield portion
# Endpoint to render the HTML template with the video player
@app.get("/", response_class=HTMLResponse)
async def video_template(request: Request):
return templates.TemplateResponse("display_video.html", {"request": request})
# Endpoint to stream the video
@app.get("/video/{video_id}")
async def video_stream(vid_id: int):
if 0 <= vid_id < len(vid_urls):
return StreamingResponse(stream_video(vid_urls[vid_id]), media_type="video/mp4")
else:
return HTMLResponse("Video not found", status_code=404)
display_video.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stooooockzz</title>
</head>
<body>
<h1>What we do?</h1>
<p>We create awesome stock videos for free usage</p>
<h3>Video Samples</h3>
<div style="display: flex; justify-content: space-evenly;">
<video width='20%' height='30%' style="border-radius: 10px;" controls autoplay>
<source src="/video/0" type="video/mp4">
</video>
<video width='20%' height='30%' style="border-radius: 10px;" controls autoplay>
<source src="/video/1" type="video/mp4">
</video>
<video width='20%' height='30%' style="border-radius: 10px;" controls autoplay>
<source src="/video/2" type="video/mp4">
</video>
<video width='20%' height='30%' style="border-radius: 10px;" controls autoplay>
<source src="/video/3" type="video/mp4">
</video>
</div>
</body>
</html>
该 HTML 文件包含多个<video>
标签,其中源指向基于/video/{video_id}
端点,该端点根据 ID 流式传输视频。
> fastapi dev app.py
使用上述命令运行服务器后,我们在前端可以看到:
结论
我们已经使用 StreaminResponse
和 FileResponse
类在浏览器上直接流式传输本地和网络视频,此外,我们还使用 StreamingResponse
在浏览器上流式传输使用 HTML 文件渲染的多个视频。
在本文中,我们使用了互联网上的视频 URL,但您也可以从数据库、本地文件、磁盘等获取 URL。
作者:Sachin Pal
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。