如何修复 Flask 应用中 m3u8 流的 CORS 问题?

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

我正在构建一个 Flask 应用程序,它使用 m3u8 和请求来提供 m3u8 流视频文件。但是,当我尝试从外部 URL 获取 m3u8 文件时遇到 CORS 问题。 CORS 标头设置不正确,我需要确保视频播放器可以从我的服务器获取播放列表和 TS 文件,而不会遇到 CORS 错误。

这是我当前的设置:

from flask import Flask, request, jsonify, render_template
import m3u8
import requests
from flask_cors import CORS, cross_origin

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/extract', methods=['POST'])
def extract_quality():
    m3u8_url = request.json.get('url')
    
    if not m3u8_url:
        return jsonify({"error": "No URL provided"}), 400
    
    try:
        playlist = m3u8.load(m3u8_url)
        
        qualities = []
        for playlist_variant in playlist.playlists:
            resolution = playlist_variant.stream_info.resolution
            bandwidth = playlist_variant.stream_info.bandwidth
            uri = playlist_variant.uri
            
            qualities.append({
                "resolution": resolution,
                "bandwidth": bandwidth,
                "uri": uri
            })
        
        return jsonify(qualities)
    
    except Exception as e:
        return jsonify({"error": f"An error occurred: {str(e)}"}), 500

CORS(app, resources={r"/*": {"origins": "*"}})

@app.route('/proxy', methods=['GET'])
@cross_origin()
def proxy():
    url = request.args.get('url')
    if not url:
        return jsonify({"error": "No URL provided"}), 400

    try:
        response = requests.get(url)
        if response.status_code == 200:
            return response.content, response.status_code, {
                'Access-Control-Allow-Origin': '*',
                'Content-Type': response.headers.get('Content-Type', 'application/octet-stream')
            }
        else:
            return jsonify({"error": f"Failed to fetch URL, status code: {response.status_code}"}), 500
    except requests.exceptions.RequestException as e:
        return jsonify({"error": f"An error occurred: {str(e)}"}), 500

@app.route('/tsproxy', methods=['GET'])
@cross_origin()
def ts_proxy():
    ts_url = request.args.get('url')
    if not ts_url:
        return jsonify({"error": "No URL provided"}), 400

    try:
        response = requests.get(ts_url)
        if response.status_code == 200:
            return response.content, response.status_code, {
                'Access-Control-Allow-Origin': '*',
                'Content-Type': 'video/MP2T'
            }
        else:
            return jsonify({"error": f"Failed to fetch TS file, status code: {response.status_code}"}), 500
    except requests.exceptions.RequestException as e:
        return jsonify({"error": f"An error occurred: {str(e)}"}), 500

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5500)

我在前端使用 Hls.js 和 Plyr 来播放视频。这是播放器的 JavaScript 代码:

// JavaScript to handle fetching and playing the video
function getQualities() {
  const url = document.getElementById("m3u8_url").value;
  if (!url) {
    alert("Please enter a URL!");
    return;
  }

  fetch("/extract", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ url: url }),
  })
    .then((response) => response.json())
    .then((data) => {
      if (data.error) {
        alert(data.error);
      } else {
        const selector = document.getElementById("quality_selector");
        selector.innerHTML = ""; // Clear previous results

        data.forEach((item) => {
          const option = document.createElement("option");
          option.value = item.uri;
          option.textContent = `${item.resolution ? item.resolution.join("x") : "N/A"} - ${item.bandwidth} bps`;
          selector.appendChild(option);
        });

        document.getElementById("quality_options").classList.remove("hidden");
      }
    })
    .catch((error) => {
      console.error("Error:", error);
      alert("An error occurred while fetching the data");
    });
}

function playVideo() {
  const video = document.getElementById("video");
  const url = document.getElementById("quality_selector").value;

  if (!url) {
    alert("Please select a quality!");
    return;
  }

  const proxyUrl = `http://192.168.1.15:5500/proxy?url=${encodeURIComponent(url)}`;

  if (Hls.isSupported()) {
    const hls = new Hls({
      loader: function (config) {
        const originalLoader = new Hls.DefaultConfig.loader(config);
        const originalLoad = originalLoader.load.bind(originalLoader);

        // Update the TS segment URL to use the '/tsproxy' route
        originalLoader.load = function (context, config, callbacks) {
          if (context.type === "fragment") {
            context.url = `http://192.168.1.15:5500/tsproxy?url=${encodeURIComponent(context.url)}`;
          }
          return originalLoad(context, config, callbacks);
        };

        return originalLoader;
      },
    });

    hls.loadSource(proxyUrl);
    hls.attachMedia(video);

    new Plyr(video);
  } else if (video.canPlayType("application/vnd.apple.mpegurl")) {
    video.src = proxyUrl;
    new Plyr(video);
  } else {
    alert("Your browser does not support HLS!");
  }
}

} 问题: 当我尝试从外部源获取 m3u8 和 TS 文件时,尽管在 Flask 中使用了 CORS 库,但我还是遇到了 CORS 错误。 我使用 /proxy 和 /tsproxy 路由通过 Flask 应用程序代理请求,但似乎 CORS 标头设置不正确或者浏览器仍然阻止请求。

我在代理响应中手动添加了 CORS 标头。 我尝试在代理路由上使用 @cross_origin() 。 我检查了浏览器的开发人员工具,在尝试获取视频片段时,它显示了与 CORS 相关的错误。 如何解决 CORS 问题并在 Flask 应用程序中成功从外部 URL 传输 m3u8 视频?

flask cors http-live-streaming m3u8
1个回答
0
投票

您可以创建一个服务器端 PHP 代理,通过所选的引荐来源网址获取视频并将其提供给您的 HTML 页面。

代理.php

<?php
$url = $_GET['url'];

// Set to your desired referrer
$referrer = 'http://www.example.com/';

// Set the referrer header
$opts = [
    'http' => [
        'header' => 'Referer: ' . $referrer
    ]
];

// Create stream context with referrer header
$context = stream_context_create($opts);

// Fetch video with the specified referrer
$videoContent = file_get_contents($url, false, $context);

// Set the Content-Type header
header('Content-Type: application/x-mpegURL');

echo $videoContent;
?>

将 HTML 指向服务器端脚本的 URL。

<body>
    <video id="video" style="width: 100%; height: 100%;" controls="">
        <source src="proxy.php?url=https://yoursite.com/video/720p/playlist.m3u8" type="application/x-mpegURL">
    </video>
        <script src="player.js"></script>
</body>
© www.soinside.com 2019 - 2024. All rights reserved.