srs中rtmp接收连接,publish推流源代码解析

srs2.0的rtmp推流处理主要包含在srs_app_conn.cpp,srs_app_source.cpp,srs_app_recv_thread.cpp源文件中。

SrsServer::listen_rtmp()监听client的推流和拉流rtmp请求,接收到推流请求后在SrsServer::accept_client函数中为请求创建一个单独线程的SrsRtmpConn连接,如下图所示。然后在SrsRtmpConn::do_cycle()中处理连接,包括握手以及接收音视频数据等。

经过在SrsRtmpConn::service_cycle()中的rtmp消息交互后,进入SrsRtmpConn::stream_service_cycle()函数,在该函数中通过解析客户端client的type区分是推流还是拉流连接,针对不同的编码器推流分别在rtmp->start_fmle_publish,rtmp->start_haivision_publish,rtmp->start_flash_publish函数中对rtmp的消息交互进行不同处理,并且在SrsSource::fetch_or_create函数中取得直播源,推流创建新的然后返回,拉流直接取存在的源。

在rtmp连接消息交互处理完成后,进入 publishing(source)函数接收实际音视频数据然后处理,在refer->check进行refer鉴权和http_hooks_on_publish函数on_publish请求后,在SrsRtmpConn::acquire_publish函数中对流是否存在以及该节点是否支持推流进行校验,校验通过后如下图单独起一个接收音视频数据的线程,单独的接收线程可以提高服务器性能,do_publishing函数中开始启动线程。


进入到srs_app_recv_thread.cpp文件中,在SrsRecvThread::cycle()函数中接收数据处理,该函数针对推流连接接收实际的音视频数据,针对拉流连接接收客户端client的控制消息。rtmp->recv_message(&msg)接收数据,然后进入handler->handle(msg)处理消息。

在SrsPublishRecvThread::handle(SrsCommonMessage* msg)函数中,下图_conn->handle_publish_message(_source, msg, _is_fmle, _is_edge)函数中处理接收的音视频数据。


在接收线程SrsPublishRecvThread接收数据的同时,SrsRtmpConn::do_publishing()函数中对线程的状态进行检测。

WebSocket 是一种基于 TCP 协议实现的双向通信的协议,而 RTMP 是一种用于音视频流传输的协议,两者并没有直接的联系。 如果需要使用 WebSocket 连接 RTMP 推流,需要借助一些第三方库或工具来实现。以下是一个使用 Socket.IO 和 ffmpeg.js 实现 WebSocket 推流的简单示例: 1. 安装依赖 ``` npm install socket.io-client ffmpeg.js ``` 2. 创建 WebSocket 连接 ```javascript const io = require('socket.io-client'); const socket = io.connect('http://localhost:3000'); // 监听连接成功事件 socket.on('connect', () => { console.log('WebSocket 连接成功'); }); // 监听连接失败事件 socket.on('connect_error', error => { console.error('WebSocket 连接失败', error); }); ``` 3. 使用 ffmpeg.js 将音视频流编码为 FLV 格式并发送到 WebSocket 服务器 ```javascript import { createFFmpeg, fetchFile } from 'ffmpeg.js'; const ffmpeg = createFFmpeg({ log: true }); // 初始化 ffmpeg.js await ffmpeg.load(); // 获取媒体流 const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true }); const audioTrack = mediaStream.getAudioTracks()[0]; const videoTrack = mediaStream.getVideoTracks()[0]; // 创建视频元素并播放媒体流 const videoElement = document.createElement('video'); videoElement.srcObject = mediaStream; videoElement.play(); // 创建视频编码器并设置参数 await ffmpeg.write('input.mp4', await fetchFile(videoElement.src)); // 将视频流写入到 input.mp4 文件 await ffmpeg.write('audio.wav', await fetchFile(audioTrack)); // 将音频流写入到 audio.wav 文件 await ffmpeg.run('-i', 'input.mp4', '-i', 'audio.wav', '-c:v', 'libx264', '-preset', 'ultrafast', '-tune', 'zerolatency', '-c:a', 'aac', '-strict', 'experimental', '-f', 'flv', 'rtmp://localhost/live/stream'); // 对 input.mp4 和 audio.wav 进行编码,并将编码后的 FLV 格式数据通过 RTMP 推流rtmp://localhost/live/stream // 监听编码进度事件 ffmpeg.setProgress(({ ratio }) => { console.log(`编码进度:${(ratio * 100).toFixed(2)}%`); }); // 监听编码完成事件 ffmpeg.setLogger(({ message }) => { console.log(`编码完成:${message}`); }); ``` 需要注意的是,这只是一个简单的示例,实际使用还需要考虑音视频流的编码参数、网络延迟等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值