(aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器

这篇具有很好参考价值的文章主要介绍了(aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 背景介绍

在先前的博客文章中,我们已经搭建了一个基于SRS的流媒体服务器。现在,我们希望通过Web接口来控制这个服务器的行为,特别是对于正在进行的 RTSP 转码任务的管理。这将使我们能够在不停止整个服务器的情况下,动态地启动或停止摄像头的转码过程。

Docker部署 SRS rtmp/flv流媒体服务器-CSDN博客文章浏览阅读360次,点赞7次,收藏5次。SRS(Simple Realtime Server)是一款开源的流媒体服务器,具有高性能、高可靠性、高灵活性的特点,能够支持直播、点播、转码等多种流媒体应用场景。SRS 不仅提供了流媒体服务器,还提供了适用于多种平台的客户端 SDK 和在线转码等辅助服务,是一款十分强大的流媒体解决方案。https://blog.csdn.net/m0_56659620/article/details/135400510?spm=1001.2014.3001.5501

2. 技术选择

在选择技术方案时,考虑到构建视频流转码服务的需求,我们将采用Python编程语言,并结合asyncio和aiohttp库。这一选择基于异步框架的优势,以下是对异步框架和同步框架在视频流转码场景中的优缺点的明确总结:

异步框架的优势:

  • 高并发处理: 异步框架通过非阻塞方式处理请求,能够高效处理大量并发请求,确保系统在高负载下保持稳定性。
  • 异步I/O: 支持异步I/O操作,允许在等待I/O操作完成的同时继续处理其他请求,提高整体效率。
  • 资源利用率高: 能够更有效地利用系统资源,同时处理多个请求,提高视频转码效率。
  • 事件驱动: 采用事件驱动模型,适应实时性要求高的视频流处理,能够立即响应新的转码请求。

同步框架的缺点:

  • 阻塞: 阻塞调用可能导致整个程序停滞,尤其在处理大文件或网络请求时可能引发性能问题,特别是在高并发场景下。
  • 低并发: 每个请求需要独立的线程或进程,可能导致系统资源耗尽,降低并发处理能力,对于需要同时处理多个视频流的情况可能不够高效。

考虑到处理大量并发请求、提高系统性能和响应性的需求,采用异步框架是更为合适的选择。异步框架的高并发处理能力、异步I/O支持、高资源利用率以及事件驱动的特性使其更适用于实时性要求较高的视频流转码服务。

3. 代码实现(必须在linux系统运行,4步骤为部署攻略)

3.1 导入必要的库

首先,我们导入所需的库,包括asyncio、aiohttp、aiohttp_cors和logging。

import asyncio
from aiohttp import web
import aiohttp_cors
import logging

3.2 设置日志

logging.basicConfig(level=logging.INFO)

3.3 配置并发控制和任务跟踪

设置最大同时运行的ffmpeg子进程数量,并使用Semaphore限制并发进程数量。同时,使用字典跟踪正在进行的转码任务。

MAX_CONCURRENT_PROCESSES = 5
semaphore = asyncio.Semaphore(MAX_CONCURRENT_PROCESSES)
transcoding_tasks = {}

3.4 定义启动和停止转码任务的方法

定义启动和停止 RTSP 转码任务的方法

# 开始转码方法
async def perform_transcoding(ip, camera_id, rtmp_server):
    # 检查相同RTSP是否已有子进程在处理
    if camera_id in transcoding_tasks:
        return transcoding_tasks[camera_id]

    # 使用Semaphore限制并发进程数量
    async with semaphore:
        # 实际的转码操作,这里需要调用ffmpeg或其他工具
        ffmpeg_command = [
            'ffmpeg',
            '-rtsp_transport', 'tcp',
            '-i', ip,
            '-c:v', 'libx264',
            '-c:a', 'aac',
            '-f', 'flv',
            f'{rtmp_server}/live/livestream{camera_id}'
        ]

        # 创建异步子进程
        process = await asyncio.create_subprocess_exec(*ffmpeg_command)

        # 将任务添加到字典中
        transcoding_tasks[camera_id] = process

        # 等待子进程完成
        await process.communicate()

        # 从字典中移除已完成的任务
        transcoding_tasks.pop(camera_id, None)

# 停止转码方法
async def stop_transcoding(camera_id):
    # 停止转码任务
    if camera_id in transcoding_tasks:
        process = transcoding_tasks[camera_id]
        process.terminate()  # 发送终止信号
        await process.wait()  # 等待进程结束

        # 从字典中移除已停止的任务
        transcoding_tasks.pop(camera_id, None)

3.5 定义Web接口路由

定义Web接口路由,包括启动摄像头转码、停止摄像头转码和停止所有摄像头转码的路由。

# 开始转码任务
async def play_camera(request):
    data = await request.post()

    # 从表单数据中获取摄像头的ID和rtsp流
    camera_id = data.get('id')
    rtsp = data.get('ip')

    # 这里设置你的 RTMP 服务器地址
    rtmp_server = 'rtmp://192.168.14.93:1935'

    # 执行实际的转码操作
    task = await perform_transcoding(rtsp, camera_id, rtmp_server)

    # 返回包含转码后的RTMP URL的JSON响应
    rtmp_url = f'http://192.168.14.93:8080/live/livestream{camera_id}.flv'
    return web.json_response({'message': '转码启动成功', 'flv_data': rtmp_url})


# 停止转码任务
async def stop_camera(request):
    data = await request.post()
    camera_id = data.get('id')

    # 停止指定摄像头的转码任务
    await stop_transcoding(camera_id)

    return web.json_response({'code':200,'message': '转码停止成功'})


# 如果页面进行刷新或者关闭停止全部转码任务
async def stop_all_camera(request):

    # 获取所有正在运行的任务的列表
    tasks = [stop_transcoding(camera_id) for camera_id in transcoding_tasks.keys()]

    # 并发停止所有任务
    await asyncio.gather(*tasks)

    # 清空字典,表示所有任务都已停止
    transcoding_tasks.clear()

    return web.json_response({'code':200,'message': '转码停止成功'})

3.6 创建Web应用和配置CORS

创建Web应用,配置CORS(跨域资源共享)中间件,以确保接口可以被跨域访问。

app = web.Application()

# CORS配置
cors = aiohttp_cors.setup(app, defaults={
    "*": aiohttp_cors.ResourceOptions(
        allow_credentials=True,
        expose_headers="*",
        allow_headers="*",
    )
})

3.7 添加Web接口路由

添加Web接口路由,包括启动摄像头转码、停止摄像头转码和停止所有摄像头转码的路由。

app.router.add_route('POST', '/play_camera', play_camera)  # 开始转码任务路由
app.router.add_route('POST', '/stop_camera', stop_camera)  # 停止转码任务路由
app.router.add_route('POST', '/stop_all_camera', stop_all_camera)  # 停止全部转码任务路由

3.8 添加CORS中间件

添加CORS中间件,确保接口可以被跨域访问。

# 添加 CORS 中间件
for route in list(app.router.routes()):
    cors.add(route)

3.9 运行Web应用

运行Web应用,监听指定的主机和端口。

if __name__ == '__main__':
    web.run_app(app, host='0.0.0.0', port=7000,access_log=logging.getLogger())

 3.10 完整代码

import asyncio
from aiohttp import web
import aiohttp_cors
import logging

# 设置日志级别
logging.basicConfig(level=logging.INFO)

# 最大同时运行的ffmpeg子进程数量
MAX_CONCURRENT_PROCESSES = 5

# 使用Semaphore限制并发进程数量
semaphore = asyncio.Semaphore(MAX_CONCURRENT_PROCESSES)

# 字典用于跟踪正在进行的转码任务
transcoding_tasks = {}

# 开始转码方法
async def perform_transcoding(ip, camera_id, rtmp_server):
    # 检查相同RTSP是否已有子进程在处理
    if camera_id in transcoding_tasks:
        return transcoding_tasks[camera_id]

    # 使用Semaphore限制并发进程数量
    async with semaphore:
        # 实际的转码操作,这里需要调用ffmpeg或其他工具
        ffmpeg_command = [
            'ffmpeg',
            '-rtsp_transport', 'tcp',
            '-i', ip,
            '-c:v', 'libx264',
            '-c:a', 'aac',
            '-f', 'flv',
            f'{rtmp_server}/live/livestream{camera_id}'
        ]

        # 创建异步子进程
        process = await asyncio.create_subprocess_exec(*ffmpeg_command)

        # 将任务添加到字典中
        transcoding_tasks[camera_id] = process

        # 等待子进程完成
        await process.communicate()

        # 从字典中移除已完成的任务
        transcoding_tasks.pop(camera_id, None)

# 停止转码方法
async def stop_transcoding(camera_id):
    # 停止转码任务
    if camera_id in transcoding_tasks:
        process = transcoding_tasks[camera_id]
        process.terminate()  # 发送终止信号
        await process.wait()  # 等待进程结束

        # 从字典中移除已停止的任务
        transcoding_tasks.pop(camera_id, None)


# 开始转码任务
async def play_camera(request):
    data = await request.post()

    # 从表单数据中获取摄像头的ID和rtsp流
    camera_id = data.get('id')
    rtsp = data.get('ip')

    # 这里设置你的 RTMP 服务器地址
    rtmp_server = 'rtmp://192.168.14.93:1935'

    # 执行实际的转码操作
    task = await perform_transcoding(rtsp, camera_id, rtmp_server)

    # 返回包含转码后的RTMP URL的JSON响应
    rtmp_url = f'http://192.168.14.93:8080/live/livestream{camera_id}.flv'
    return web.json_response({'message': '转码启动成功', 'flv_data': rtmp_url})


# 停止转码任务
async def stop_camera(request):
    data = await request.post()
    camera_id = data.get('id')

    # 停止指定摄像头的转码任务
    await stop_transcoding(camera_id)

    return web.json_response({'code':200,'message': '转码停止成功'})


# 如果页面进行刷新或者关闭停止全部转码任务
async def stop_all_camera(request):

    # 获取所有正在运行的任务的列表
    tasks = [stop_transcoding(camera_id) for camera_id in transcoding_tasks.keys()]

    # 并发停止所有任务
    await asyncio.gather(*tasks)

    # 清空字典,表示所有任务都已停止
    transcoding_tasks.clear()

    return web.json_response({'code':200,'message': '转码停止成功'})


app = web.Application()

# CORS配置
cors = aiohttp_cors.setup(app, defaults={
    "*": aiohttp_cors.ResourceOptions(
        allow_credentials=True,
        expose_headers="*",
        allow_headers="*",
    )
})

app.router.add_route('POST', '/play_camera', play_camera)  # 开始转码任务路由
app.router.add_route('POST', '/stop_camera', stop_camera)  # 停止转码任务路由
app.router.add_route('POST', '/stop_all_camera', stop_all_camera)  # 停止全部转码任务路由

# 添加 CORS 中间件
for route in list(app.router.routes()):
    cors.add(route)


if __name__ == '__main__':
    web.run_app(app, host='0.0.0.0', port=7000,access_log=logging.getLogger())

4. 部署(Docker环境)

部署所需Dockerfile文件代码如下

FROM python:3.7-slim

WORKDIR /app

COPY requirements.txt .

RUN apt-get update \
    && apt-get install -y ffmpeg \
    && rm -rf /var/lib/apt/lists/* \
    && pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["python", "async_io_io.py"]

部署所需requirements.txt如下

aiohttp
aiohttp-cors
ffmpeg

根目录进行打包及启动

(aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器,服务器,运维

请求接口实现转码

(aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器,服务器,运维

5. 总结

通过以上的步骤,我们成功构建了一个流媒体服务器控制接口,可以通过Web接口实现对摄像头的 RTSP 转码任务的动态管理。这个接口可以集成到现有的流媒体服务器中,提供更多控制和管理的可能性。文章来源地址https://www.toymoban.com/news/detail-781833.html

到了这里,关于(aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Windows-docker集成SRS服务器的部署和使用

    一、Windows Docker安装 Docker Desktop 官方下载地址: https://docs.docker.com/desktop/install/windows-install/ 下载windows版本的就可以了。 注意:此方法仅适用于 Windows 10 操作系统专业版、企业版、教育版和部分家庭版! 安装 Hyper-V 我们开启Hyper-V。 我们安装好Docker for Windows后,可以在CMD中执

    2024年02月10日
    浏览(43)
  • docker部署SRS实时视频服务器,rtmp推流,用WebRTC播放

    SRS是一个简单高效的实时视频服务器,支持RTMP/WebRTC/HLS/HTTP-FLV/SRT/GB28181 大家可以先去gitub上面看使用说明,地址是:v4_CN_Home · ossrs/srs Wiki · GitHub 然后我们通过docker去启动SRS,这些文档里面都有,就不用多说了,然后我们可以用rtmp推流 用WebRTC播放,首先要支持WebRTC我们需要

    2023年04月11日
    浏览(63)
  • SRS视频媒体服务器-docker启动:更换默认端口时的错误

    在使用srs视频服务器时,一直都是使用默认的端口配置。但是,这些默认端口在某些时候可能已经被占用了,就需要更改端口了。 注意注意注意:使用docker启动srs,在更换端口一定要下面的内容。 网络拓扑图:   启动命令:外部端口1936映射内部1935  和 外部端口8001映射内部

    2024年02月13日
    浏览(48)
  • 9步实现 Docker部署 SRS rtmp/flv流媒体服务器

    这是基于centos7.6系统部署的 运行容器会直接停留在容器运行界面,通过Ctrl+P+Q可后台形式退出容器 这时候其实已经运行成功!可以通过以下命令查看SRS控制台 进入/home/docker/srs3 可查看配置文件是否复制成功 这是可能会报错: 因为步骤四我们意见运行一个容器,已经使用过

    2024年02月15日
    浏览(61)
  • 在服务器上使用Docker运行SRS Stack,推拉直播流、多平台转播、本地录制、虚拟直播、直播转码、AI字幕、其他

    SRS Stack | SRS (ossrs.net) Docker​ 推荐使用Docker运行SRS Stack: 服务器防火墙开启端口:  TCP/1935 复制 请打开页面http://localhost:2022开始使用SRS Stack。 关于使用说明,请参考 SRS Stack Docker。

    2024年01月16日
    浏览(58)
  • Python异步编程探究:深入理解asyncio的使用和原理【第130篇—asyncio】

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 随着计算机应用程序的复杂性不断增加,对于高效处理I/O密集型任务的需求也越来越迫切。在Python中,asyncio模块提供了一种强大的异步编程

    2024年04月12日
    浏览(44)
  • Asyncio 协程异步笔记

    协程不是计算机提供,而是程序员人为创造。 协程(coroutine),也可以被称为微线程,是一种用户态内的上下文切换技术。简而言之,其实就是通过一个线程实现代码块互相切换运行。例如: 实现协程有这么几种方法: greenlet ,早期模块。 yield 。 asyncio 装饰器(py

    2024年02月08日
    浏览(49)
  • 高并发 发送请求(asyncio)

    在接手这个项目之前,关于数据存储的代码逻辑如上图,看起来按部就班,也很合理。(本人觉得这就像个玩具车) 在最后一步发送HTTP request响应足够快的话,其实速度说不上快但稳定,可以接受。但偏偏第三季度了,数据量上来了,最后一步得到response的时间达到了2秒多(

    2024年02月07日
    浏览(40)
  • aiohttp 异步爬虫实战

    之前介绍的 asyncio 模块内部 实现了对 TCP、UDP、SSL 协议的异步操作,但是对于 HTTP 请求的异步操作来说,我们就需要用到 aiohttp 来实现了 。aiohttp 是 一个基于 asyncio 的异步 HTTP 网络模块,它既提供了服务端,又提供了客户端 。其中我们用服务端可以搭建一个支持异步处理的

    2023年04月22日
    浏览(37)
  • Sanic、uvloop及Asyncio的局限

    sanic使用基于libuv的uvloop事件循环替代python asnycio自带的事件循环替代,以此提高异步性能。 Flask和Django是同步框架,Tornado、FastApi和Sanic均为异步框架,Sanic的性能最好。 Sanic入门教程:Sanic:一款号称 Python 中性能最高的异步 web 框架,全方位介绍 Sanic Sanic支持通过workers设置并

    2024年02月12日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包