基于fastapi和ffmpeg的流媒体服务器简单实现

一、背景

打算做一个点播系统,主要功能是播放视频,但是视频流如何传到web端是一个主要问题。如果是以MP4整个文件传输会导致如下问题:一是文件过大,加载过慢,二是流量消耗过多,中途可能直接关闭视频。
解决这个问题采用m3u8格式,将MP4视频进行切片,一次一次的加载。

二、准备

我准备了一个MP4视频huahai.mp4,没错就是周董的《花海》。
使用python3,最好是3.7及以上版本支持asyncio模块,其他需要fastapi、ffmpy3模块
先看整个目录结构和内容,理论的内容大家自行百度,我也说不明白,直接上代码。
在这里插入图片描述
其中html文件是前端,播放的界面,py就是服务端,huahai是存放媒体的目录,MP4是我们视频文件。
整个流程就是先将MP4生成m3u8文件,然后开启api服务器,久可以在前端访问了。

三、代码

1、前端代码,很简单涉及videojs

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>文档标题</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/video.js/7.3.0/video-js.min.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/video.js/7.3.0/video.min.js"></script>
    
</head>

<body>
    <div>
        <video id="example_video" class="video-js vjs-default-skin" controls preload="none"
            poster="https://i1.hdslb.com/bfs/archive/3123c64f3be9669ae2d2b3ef82549b1b2bd035e5.jpg@480w_270h_1c">
            <source src="http://127.0.0.1:5000/video/huahai.m3u8" type="application/x-mpegURL">
            <!-- <source src="C:/Users/WYC/Desktop/fastapitest/testffm/huahai2/huahai.m3u8" type="application/x-mpegURL"> -->
        </video>
    </div>
</body>
<script>
    var player = videojs('example_video', {
        muted: true,//静音
        controls: true,//控制组件
        width: 1000,
        loop: true,//循环播放
        playbackRates: [0.5, 1, 1.5, 2]//控制速度
    });
</script>

</html>

2、后端代码,很简单涉及fastapi和ffmpeg的操作

import uvicorn
from fastapi import FastAPI,Response
from starlette.responses import FileResponse
from fastapi.middleware.cors import CORSMiddleware
from ffmpy3 import FFmpeg
import os

inputs={'./huahai/huahai.mp4': None}
# 配置生成指令
outputs={None:'-c:v libx264 -c:a aac -strict -2 -f segment -segment_time 10 -segment_list_entry_prefix http://127.0.0.1:5000/video/ -segment_list ./huahai/huahai.m3u8 ./huahai/huahai-%4d.ts'}
app = FastAPI()
origins = [
    "*"
]
# 配置允许跨域
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.get("/video/{fileName}")
async def video(response: Response,fileName:str):
    response.headers["Content-Type"] = "application/x-mpegURL"
    return FileResponse('./huahai/'+fileName, filename=fileName) 

# 处理视频文件 生成 m3u8
def chuliVideo(path):
    # 判断文件是否存在
    if not os.path.exists('./huahai/'+path):
        return False#文件不存在
    # 提取文件名
    ff = FFmpeg(inputs=inputs, outputs=outputs)
    ff.run()

if __name__ == '__main__':
    chuliVideo('huahai.mp4')
    uvicorn.run("apifastMain:app", host="127.0.0.1", port=5000, log_level="info", reload=True, debug=True)

3、结果说明

处理之后生成的文件
在这里插入图片描述
前端播放效果,可以看到支持慢加载
在这里插入图片描述

服务器路由请求路径,可以看出一个一个加载
在这里插入图片描述

四、说明

1、关于m3u8文件的生成和处理

我们看一下m3u8文件内容,每个ts都进行了处理,补充了完整的路由,这是因为videojs在自动加载的时候是根据m3u8的内容进行的,不断读取ts路径,关于这个文件我们也可以动态的生成和修改,因为路由在开发过程中是不确定的。
在这里插入图片描述

2、关于ffmpeg命令补充

outputs={None:'-c:v libx264 -c:a aac -strict -2 -f segment -segment_time 10 -segment_list_entry_prefix http://127.0.0.1:5000/video/ -segment_list ./huahai/huahai.m3u8 ./huahai/huahai-%4d.ts'}

对于上面的代码,主要考虑如下参数:
-segment_time + 多少秒分割
-segment_list_entry_prefix + 每个ts文件前加的字符串,组成绝对路径
-segment_list + 输出的文件位置,包括文件名
这个%4d是后缀,意思四位数字,不够补零
具体效果可以思考 huhai目录以及里面的文件

3、关于fastapi跨域

需要注意,没有解决跨域问题,前端videojs会报错的,打开浏览器调式窗口可以看到。

五、总结

我在写本篇博客之前百度了很多内容,但是大多是理论的东西,告诉你可以用HLS实现,但是没有具体实现方法,又或者是爬虫之类的得到m3u8的路径直接放进前端videojs处理,现在将所做分享给大家,希望和大家一起学习进步,当然后面还有很多的工作需要完善。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江湖人称王某人的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值