通过Flask+FFmpeg的方式,将视频流对外发布为HLS流(windows)

FFmpeg介绍

FFmpeg 是一个用于处理视频、音频等多媒体文件的开源工具包。它支持几乎所有的多媒体格式转换、剪辑和编辑,是开发者和多媒体工作者必备的工具。

 

FFmpeg安装教程(参考:FFmpeg 超级详细安装与配置教程(Windows 系统)_windows安装ffmpeg-CSDN博客

1. 打开 Dpwnload FFmpeg 官网

 2.下滑找到release bulids部分,选择ffmpeg-essentials_build.zip

 3. 配置环境变量

进入 bin 目录,可以看到 FFmpeg 的三个核心可执行文件:ffmpeg.exeffplay.exeffprobe.exe

找到“系统变量”中的 Path 条目并点击“编辑”,输入 FFmpeg 的 bin 文件夹路径

 4. 测试安装是否成功

 在cmd命令行中输入以下命令查看 FFmpeg 版本,ffmpeg -version

 

通过opencv读取视频流

import cv2

video_path = r"./pedestrian.mp4"

# 初始化视频捕获对象
cap = cv2.VideoCapture(video_path)

# 检查视频是否成功打开
if not cap.isOpened():
    print(f"Error: 无法打开视频文件 {video_path}")
    exit()

# 获取视频属性
fps = cap.get(cv2.CAP_PROP_FPS)
delay = int(1000 / fps) if fps > 0 else 1  # 计算每帧显示延迟时间

try:
    while True:
        # 读取视频帧
        ret, frame = cap.read()
        if not ret:  # 视频读取结束或发生错误
            break

        # 显示当前帧
        cv2.imshow("frame", frame)

        # 按键检测与退出逻辑
        if cv2.waitKey(delay) & 0xFF == ord('q'):
            break
finally:
    # 确保资源正确释放
    cap.release()
    cv2.destroyAllWindows()

 

通过flask+ffmpeg将视频流发布为hls流

import cv2
import os
import subprocess
import threading
from flask import Flask, send_from_directory
from flask_cors import CORS
import time

# ================== 配置参数 ==================
VIDEO_PATH = "./pedestrian.mp4"
# VIDEO_PATH = "rtsp://admin:zdhb2323@192.1.181.191:554/h264/ch1/main/av_stream"

HLS_DIR = "hls"
FLASK_PORT = 9090

ffmpeg_path = "C:/Software/FFmpeg/ffmpeg-7.0.2-essentials_build/bin/ffmpeg.exe"
os.environ["PATH"] += os.pathsep + os.path.dirname(ffmpeg_path)

# ================== Flask 静态文件服务 ==================
def run_flask_static_server():
    app = Flask(__name__)
    CORS(app)

    @app.route('/hls/<path:filename>')
    def serve_hls(filename):
        if filename.endswith('.m3u8'):
            return send_from_directory(HLS_DIR, filename, mimetype='application/vnd.apple.mpegurl')
        elif filename.endswith('.ts'):
            return send_from_directory(HLS_DIR, filename, mimetype='video/mp2t')
        else:
            return send_from_directory(HLS_DIR, filename)

    @app.route('/')
    def index():
        return 'HLS Streaming Server is Running...'

    app.run(host='0.0.0.0', port=FLASK_PORT)

# ================== 主程序 ==================
def main():
    os.makedirs(HLS_DIR, exist_ok=True)

    cap = cv2.VideoCapture(VIDEO_PATH)
    if not cap.isOpened():
        print(f"[错误] 无法打开视频文件: {VIDEO_PATH}")
        return

    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    fps = str(int(cap.get(cv2.CAP_PROP_FPS) or 25))

    # 启动 Flask 静态服务器
    threading.Thread(target=run_flask_static_server, daemon=True).start()
    time.sleep(1)

    # 启动 FFmpeg 推流进程
    hls_output = os.path.join(HLS_DIR, "stream.m3u8")
    ffmpeg_cmd = [
        ffmpeg_path,
        "-y",
        "-f", "rawvideo", "-pixel_format", "bgr24",
        "-video_size", f"{width}x{height}",
        "-framerate", fps,
        "-i", "-",
        "-c:v", "libx264", "-preset", "veryfast",
        "-f", "hls", "-hls_time", "1", "-hls_list_size", "5",
        "-hls_flags", "delete_segments",
        hls_output
    ]
    ffmpeg_process = subprocess.Popen(ffmpeg_cmd, stdin=subprocess.PIPE)

    try:
        while True:
            ret, frame = cap.read()
            if not ret:
                print("[警告] 视频读取失败,尝试重新打开视频")
                cap = cv2.VideoCapture(VIDEO_PATH)
                continue

            # 将帧数据写入 FFmpeg 进程的标准输入
            ffmpeg_process.stdin.write(frame.tobytes())

    except Exception as e:
        print(f"[错误]: {e}")
    finally:
        print("[清理] 正在关闭资源...")
        cap.release()
        cv2.destroyAllWindows()
        ffmpeg_process.stdin.close()
        ffmpeg_process.wait()

if __name__ == "__main__":
    main()

 

发布的HLS流地址为:http://192.168.31.164:9090/hls/stream.m3u8(通过PotPlayer打开)

 

posted @ 2025-07-11 11:15  马铃薯1  阅读(175)  评论(0)    收藏  举报