Flask 部分视频流无法在 Ipad 和 Iphone 上运行

问题描述 投票:0回答:1

我正在尝试编写一个 Flask 网页,将特定范围的字节流传输到客户端,这样您就可以从网络驱动器观看大型视频文件(mp4),而无需加载整个视频。它已经可以在我的笔记本电脑和托管网页的电脑上运行,但当我尝试在苹果移动设备上使用该网页时,我不断遇到问题。视频只是无法加载。视频播放器保持空白,不显示视频持续时间,并且无法启动和观看视频。

我已经尝试过使用其他浏览器。我尝试了 Safari、Google 和 Firefox,但没有任何效果。

这是流媒体页面的 HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{title}}</title>
</head>
<body>
    <video controls="true" width="650" playsinline autoplay muted loop>
        <source src="{{url_for('stream.getMovie',id=id, ver=version)}}" type="video/mp4">
    </video>
</body>
</html>

这是相关的烧瓶文件:

import mimetypes
from flask import Response, render_template, request, Blueprint
import os

from helper import getMovieById, getMovieList


stream = Blueprint("stream", __name__)


 
def removeNonDigit(str):
    final = ""
    for i in str:
        if i  in "0123456789":
            final += i
    return final






@stream.route("/movie/<id>/<ver>", methods=['GET'])
def getMovie(id, ver):
    range = request.headers.get("range")
    if not range:
        return Response("Requires Range header",status=400)
    
    videoPath: str = getMovieById(id).get("versions")[int(ver)][1]

    videoSize: bytes = os.stat(videoPath).st_size

    # parse Range
    # "bytes=3323-"
    CHUNK_SIZE = (10 ** 6)*1 # about 1 MB
    x = range[:range.find("-")]
    start = int(removeNonDigit(x))
    end = min(start + CHUNK_SIZE, videoSize-1)

    # read the data
    with open(videoPath, "rb") as v:
        v.seek(start)
        data = v.read(CHUNK_SIZE) 

    content_length = end - start + 1
    headers = {
        "Content-Range": f'bytes {start}-{end}/{videoSize}',
        "Accept-Ranges": "bytes",
        "Content-Length": content_length,
        "Content-Type": "video/mp4",
    }
    return Response(data, status=206, headers=headers, mimetype=mimetypes.guess_type(videoPath)[0],direct_passthrough=True)








@stream.route("/watch/<id>/<version>")
def player(id, version):
    return render_template("movie.html", title=getMovieById(id).get("name"), version=version, id=id)

@stream.route("/banner/<id>")
def banner(id):
    img = getMovieById(id).get("img")
    with open(img, "rb") as f:
        data = f.read()
    return Response(data, status=202)

这可能有点混乱,我已经尝试了很长时间了

这是当我从 PC 连接而不启动视频时从 Flask 控制台获得的输出:

127.0.0.1 - - [13/Nov/2023 20:14:02] "GET /watch/1/1 HTTP/1.1" 200 -
127.0.0.1 - - [13/Nov/2023 20:14:04] "GET /movie/1/1 HTTP/1.1" 206 -
127.0.0.1 - - [13/Nov/2023 20:14:04] "GET /movie/1/1 HTTP/1.1" 206 -

但是从我的 iPad 连接时我只得到这个输出:

192.xxx.xxx.xxx - - [13/Nov/2023 20:15:36] "GET /watch/1/0 HTTP/1.1" 200 -
192.xxx.xxx.xxx - - [13/Nov/2023 20:15:38] "GET /movie/1/0 HTTP/1.1" 206 -

我还发现来自 iPad 的请求中的标头的字节范围为“bytes=0-1”,来自 PC 的字节范围为“bytes=0-”

我不是请求方面的专家,但这也许有帮助......

如果您需要更多详细信息或代码片段,请告诉我。

提前谢谢您:3

python ios flask httprequest http-live-streaming
1个回答
0
投票

因此,经过一番尝试后,我发现手机上的浏览器会发送一个测试请求,在接受更大的范围之前仅请求一口。 我通过检查范围标头是否为“bytes=0-1”来修复此问题,如果是,我只返回浏览器请求的视频的一部分,而不是发回 1MB 块。

© www.soinside.com 2019 - 2024. All rights reserved.