我正在使用FastAPI从googlevideo.com
返回视频响应。这是我正在使用的代码:
@app.get(params.api_video_route)
async def get_api_video(url=None):
def iter():
req = urllib.request.Request(url)
with urllib.request.urlopen(req) as resp:
yield from io.BytesIO(resp.read())
return StreamingResponse(iter(), media_type="video/mp4")
但这不管用
我希望这个Nodejs
被转换成PythonFastAPI:
app.get("/download-video", function(req, res) {
http.get(decodeURIComponent(req.query.url), function(response) {
res.setHeader("Content-Length", response.headers["content-length"]);
if (response.statusCode >= 400)
res.status(500).send("Error");
response.on("data", function(chunk) { res.write(chunk); });
response.on("end", function() { res.end(); }); }); });
我遇到了类似的问题,但解决了所有问题。主要思想是使用request. Session()创建一个会话,并一个接一个地生成一个块,而不是获取所有内容并一次生成它。这非常好,根本不会产生任何内存问题。
@app.get(params.api_video_route)
async def get_api_video(url=None):
def iter():
session = requests.Session()
r = session.get(url, stream=True)
r.raise_for_status()
for chunk in r.iter_content(1024*1024):
yield chunk
return StreamingResponse(iter(), media_type="video/mp4")
快速解决方案是用下面的替换io. BytesIO(resp.read())的收益(有关更多详细信息,请参阅FastAPI留档-
StreamingResponse
)。
yield from resp
然而,我建议使用HTTPX库,而不是使用urllib. request和resp.read()
(这会将整个文件内容读取到内存中,因此需要太长时间才能响应),它与urllib和请求
库相比,还提供了async
支持,这更适合于FastAPI等async
环境。此外,它还支持流式响应(也请参阅async
流式响应),因此,您可以避免一次将整个响应体加载到内存中(尤其是在处理大文件时)。下面提供了同步和异步方式的示例,说明如何从给定URL流式传输视频。
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import httpx
app = FastAPI()
@app.get('/video')
def get_video(url: str):
def iterfile():
with httpx.stream("GET", url) as r:
for chunk in r.iter_bytes():
yield chunk
return StreamingResponse(iterfile(), media_type="video/mp4")
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import httpx
app = FastAPI()
@app.get('/video')
async def get_video(url: str):
async def iterfile():
async with httpx.AsyncClient() as client:
async with client.stream("GET", url) as r:
async for chunk in r.aiter_bytes():
yield chunk
return StreamingResponse(iterfile(), media_type="video/mp4")
您可以使用此处提供的公共视频来测试上述内容。示例:
http://127.0.0.1:8000/video?url=http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4
如果您想返回一个自定义的Response
或FileResponse
-如果您正在处理大型视频文件,我真的不建议这样做,因为您应该将整个内容读取到内存中,或者将内容保存到磁盘上的临时文件中,您以后必须再次读取到内存中,以便将其发送回客户端-请查看此答案和此答案。