当前位置: 首页 > 编程日记 > 正文

不用任何第三方,写一个RTMP直播推流器

2016年是移动直播爆发年,不到半年的时间内无数移动直播App掀起了全民直播的热潮。然而个人觉得直播的门槛相对较高,从推流端到服务端器到播放端,无不需要专业的技术来支撑,仅仅推流端就有不少需要学习的知识。目前大部分直播采用的都是RTMP协议,我这里写一个简单的Demo,帮助大家更好的理解直播推流的过程,主要包括:音视频采集、音视频编码、数据打包、RTMP协议等相关的知识等。项目结构分的很清楚,各个模块也用协议进行了分离,方便大家学习不同的模块。

先阐述下推流的整体流程:

  • 建立tcp连接

  • 建立rtmp连接,以及发送各种控制指令

  • 获取原始视频数据和音频数据

  • 对原始视频数据和音频数据进行压缩编码

  • 编码后的视频数据和音频数据进行打包

  • 发送打包后的音频和视频数据

项目各个类的作用

  • SGSimpleSession 是Api接口层,负责对外提供可直接调用的接口,同时也是一个数据分发中心,获取到的原始音视频数据和编码后的数据都在这里被分发到不同的类进行处理.

  • 视频相关的类

1.SGVideoSource 原始视频数据获取类,底层用的是AVFoundation框架来实现。对外提供原始未经编码的的视频数据,同时提供图像预览功能。如果需要添加美颜,摄像头切换,翻转,闪光灯等操作,也是在这里处理的。

原始视频帧:原始视频数据其实就是一帧一帧的数据,它们没有经过压缩编码,每一帧包含了图像信息和时间信息,我们通过代码提取出图片。

fps:1s中包含的帧数就是帧速(fps),一般fps的范围是15~30帧,帧速越高画面越流畅,带宽消耗量越大。实际直播中,大部分采用15到20就可以了。

分辨率:一帧的图像的大小,iOS原生的有352*288,640*480,1280*720等。一般直播采用640 *480,然后裁剪为640 *360.

码率:也叫比特率,数据传输时单位时间传送的数据位数。可以理解为码率决定一帧图像的显示精细程度。在一定范围内,码率越大,图像越清晰,消耗带宽或者文件体积就越大。超过一定范围后,清晰度不变.一般640 * 480分辨率的,码率512kbps就能够保证清晰度。

2.SGVideoConfig这个视频配置的类,主要包括压缩等级,分辨率,码率等的配置。

3.SGH264Encoder这个类是编码器,主要功能是对原始的视频帧进行编码压缩处理,这里采用的是`硬编码`,编码输出格式为H264格式。

编码:编码是指将原始的帧数据编码压缩,编码后数据更小,方便在网络上传输。原始数据体积较大,网络传输十分不方便,因此需要将数据压缩,视频压缩算法当前比较主流的是H264,这里我们压缩格式是H264格式。H264有不同的压缩等级,压缩等级不同,压缩比也不同.常见的压缩等级有:baseline ` , `main` 和`high`.

硬编码:硬编码是相对软编码而言的,一般软编码是通过cpu来运算,比较消耗cpu性能,耗时大,但是兼容性好,软编码一般采用ffmpeg或者x264。相对而言,硬编码使用gpu来编码,速度效率很高。这里采用的是iOS自带的硬解码,只支持iOS8以后的系统。

压缩后的视频帧:压缩后的视频有三种帧类型:I ,B ,P帧,I帧也叫关键帧。经过解码后能够独立展示出一幅图像,P帧是前向预测帧,参考前一帧才能解码显示出一幅完整的图像。B 为双向预测帧,必须参考前一帧和后一帧才能解码出图像,因此帧的压缩比最低,大约为0.7,它只能采用帧内压缩,P帧压缩比次之,大概能达到0.5,B帧压缩比则更高,达到了0.3~0.5。B帧和P帧采用的是帧内压缩和帧间压缩技术(也就是运动估计,原理是相邻帧的图像有一部分是一样的,专业术语叫空间冗余)。实际上,视频压缩等级不同,帧种类也不同,比如`baseline等级`压缩后的视频只有I帧 和 P帧。`main等级` 和 `high等级` 则三种帧都包含,它们的整体压缩比要比`baseline`要高。但是因为B帧需要参考前一帧和后一帧才能显示,很容易造成卡顿情况,因为万一后面的帧没有获取到,导致前一帧已也不能显示,所以在实际应用中(直播app),一般压缩等级采用`baseline`.

gop:这个我试着描述一下:因为除了I帧,其它帧都不能独立渲染显示,理论上只需要一个I帧,其它全部是非I帧,,这样压缩比最高,但是因为`(B帧和P帧)参考其他帧`的原因会有一定的误差,当一段时间后,累计误差会原来越大,导致图像失真。解决办法就是以一小段为一个单元,每个单元第一帧都是I帧,这样即使前面某一小段出了问题也不会影响后面的一小段,每一个小段我们称作一个关gop。每个gop的第一帧一定是关键帧,因为你的没得参考;通常我们设置gop的大小为1s到3s,因此关键帧与关键帧之间的间隔就是1s的帧数(对应gop为1s)到3s的帧数(对应gop为3s),根据上面的定义,1s的帧数为fps,因此关键帧间隔为1*fps 到 3*fps。秒开的优化点之一就是减小gop大小,因为gop第一帧是关键帧,能独立渲染出来,用户进入直播间的时间是随机的,为确保用户尽快拿到关键帧,尽快渲染出图像;同时gop越小,关键帧数量就越多,带宽消耗量就越大。

4.SGH264Packager 这个类负责对已经编码好的H264帧数据进行打包处理,打包成符合RTMP协议格式的数据,然后才能发送.

  • 音频相关类

SGAudioSource 这个类主要负责录制音频数据,输出原始音频帧,音频的格式为PCM格式。

SGAudioConfig 这个类是音频配置相关的类,主要包括声道数,码率,采样率的配置。

SGAACEncoder 这个类作用是将原始PCM音频数据进行编码压缩,编码结果为AAC格式的音频数据,这里采用的是硬编码,软编码的库有faac.

SGAACPackager 这个了类作用是将编码后的AAC格式数据大波按成符合RTMP协议的数据。

  • RTMP相关类

`SGStreamSession`这个类主要是用来建立tcp连接,底层数据的读取和发送,以及连接状态的回调,整个连接状态贯穿整个项目,十分重要。

`SGRtmpSession`这个类主要与RTMP相关,主要负责与服务器交互,包括RTMP握手,指令的发送,对数据的进一步封装,封装成消息,然后再发送.指令有很多,说点重要的,比如握手完成以后,要重新协商消息大小(默认128字节),但是128字节太小,影响效率,一般都稍微改大点,比如这里设置为16kb,如果太大也不好,会导致带宽浪费。这个类涉及到rtmp相关的比较多,比较难以理解,网上有开源的实现librtmp这个库,可以用这个来替代。

以上就是整个项目的基本结构,整个过程类似工厂流水线,可以自行对各个模块进行替换和研究。demo中注释也不少,方便理解。是不是感觉信息量有点大?可能有些地方说的不严谨,还望大家多多指正哈。

这个项目在去年7月份左右就写完了,后来加了一些乌七八糟的东西,后来项目挂了,转战新项目(还是直播)。中间写过几篇入门文章,本来打算写成一个系列文章,无奈太忙了,写的不完整。新年伊始,趁着项目不太忙,赶紧整理了一下,纯码字,如果有任何问题可以直接留言。

  • 附上完整的代码:https://github.com/iOSSinger/SGLivingPublisher

  • 附上个人博客:http://www.jianshu.com/u/7246ea6d05dd

  • 附上RTMP中文文档:https://raw.githubusercontent.com/iOSSinger/SGLivingPublisher/master/RTMP.docx

附上学习博客:

  • 雷晓华博士的博客:这个是非常好的视音频开发技术文章,喜欢视音频的可以看看http://blog.csdn.net/leixiaohua1020

  • 硬编码的详细说明:http://www.jianshu.com/p/a6530fa46a88


相关文章:

手机连接服务器数据库文件,手机连接服务器数据库文件夹

手机连接服务器数据库文件夹 内容精选换一换GaussDB(DWS)支持使用gs_dump工具导出某个数据库级的内容,包含数据库的数据和所有对象定义。可根据需要自定义导出如下信息:导出数据库全量信息,包含数据和所有对象定义。使用导出的全量信息可以创…

开源一个上架 App Store 的相机 App

原创 2017-02-21 伯乐专栏/陈浩 iOS大全(点击上方公众号,可快速关注) 来源:伯乐在线 - Hawk0620 如有好文章投稿,请点击 → 这里了解详情 如需转载,发送「转载」二字查看说明 Osho 相机是我独立开发上架的…

WIN7下,联想A30T通过USB连接上网

1.手机连接3G信号 2.手机上在设置里 "设置" |"应用程序" |"USB模式" |勾选"网卡模式" 3.连接上Win7,会出现驱动安装程序,手动安装这里的驱动.(驱动在百度网盘:) 4.在设备管理,网络适配器里查看驱动是否安装成…

在bootstrap ace样式框架上修改的后台管理型模板(Tab页后台管理模板)

后台管理模板开始用frameset布局,但是有时候会遮挡比如上面导航或者左边导航的二级三级弹出菜单,因为宽度被限制了,所以有时候就用easyui或者ext的,但是样式不好看,然后看到了bootstrap ace的后台管理模板,…

文件服务器的内存要多少,文件服务器内存要多大

文件服务器内存要多大 内容精选换一换Windows场景中,当把源端服务器迁移到华为云后,目的端服务器C盘的已用空间比对应源端服务器C盘的已用空间大至少1GB,而不是与源端服务器C盘的已用空间一致,这正常吗?正常现象。您可…

好玩的 RAC

UIControl 监听 control 点击 从此告别 addTarget 和 btnClick 1234[[self.loginBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton *btn) {// btn, 即 self.loginBtn// 这里执行点击之后的操作}];UITextField 监听 textField 的 text 改…

机器学习简单代码示例

机器学习简单代码示例 //在gcc-4.7.2下编译通过。 //命令行&#xff1a;g -Wall -ansi -O2 test.cpp -o test #include <iostream> using namespace std; void input(int &oper,const bool meth) {//meth为true则只判断1&#xff0c;为false则判断1或0while(true){ci…

【2007-5】【素数算式】

Description 在下面的算式中每个“#”都表示一个素数数字。##* #————###请编写程序确定这些数字&#xff0c;输出所有的解。Input Output 依次打印输出每一种解&#xff0c;每行表示一种解&#xff0c;格式为&#xff1a;##*# ###。Sample Input Sample Output HINT Sou…

ubuntu服务器版编辑文件,Ubuntu 服务器版 18.04.4 固定 IP 设置

1、输入命令 su 以root用户权限操作2、找到Ubuntu网络配置文件vim /etc/netplan/50-cloud-init.yaml3、输入 i 让文件变成可编辑状态4、修改内容dhcp4: nodhcp4: noaddresses: [192.168.3.50/24]gateway4: 192.168.3.1nameservers:addresses: [8.8.8.8, 8.8.4.4]如图&#xff…

RACCommand 粗解

前言 学习 RAC 的过程中&#xff0c;RACCommand 是我一直很迷惑的点&#xff0c;感觉一直抓不到它的要点&#xff0c;不明白为何要这样使用。曾经想过用别的方法来替代&#xff0c;只要能找到替代的方法&#xff0c;暂时就没必要死磕&#xff0c;结果发现避免不了&#xff0c;那…

将整数拆分为2的幂次方

任意一个正整数都可以用2的幂次方表示&#xff0c;例如&#xff1a;137&#xff1d;2^72^32^0&#xff0c;同时约定次方用括号来表示&#xff0c;即a^b&#xff1d;a(b)。由此可知&#xff0c;137可表 示&#xff1a;2(7)2(3)2(0)。进一步&#xff1a;72^222^0(2^1用2表示)&…

vbs脚本在服务器上虚拟按键,iisvdir.vbs iis虚拟目录管理脚本使用介绍

IIS管理器也是通过调用iisvdir.vbs来实现虚拟目录的创建和删除的。我们可以通过命令行的方式来执行iisvdir.vbs脚本1)创建虚拟目录&#xff1a;cscript c:\windows\system32\iisvdir.vbs [/s server] [/u username /p password] /create [virtualRoot] Alias PhysicalPath2)删除…

Python字典部分源码分析,字典是无序的

1 def clear(self): # real signature unknown; restored from __doc__ 2 """ D.clear() -> None. Remove all items from D. """ 3 pass 1 #练习1、清空字典&#xff08;置空&#xff09; 2 li {"key1":"v…

【2011-3】【旋转表格】

Description 小敏是个数学迷&#xff0c;特别擅长加法与除法。老师给他一个问题&#xff0c;有一个22表格&#xff0c;表中有正整数A, B, C 和D&#xff0c;表格和表格值的计算如下&#xff1a;小敏的任务是对给出的表格每次顺时针旋转90度&#xff0c;使旋转后的表格值最大&am…

iOS-FXDanmaku弹幕库介绍、相关技术分享

前言 去年, 2016年, 一大波直播平台在移动端涌出, 直播慢慢步入了人们的视角. 网上如今能够看到各式各样的直播, 如秀场直播、游戏直播、体育直播、娱乐直播等等. 在各种类型的直播中, 弹幕在PC、移动端都几乎成为了标配, 今天在这里主要介绍一下个人开源的iOS弹幕, 以及提前为…

【廖雪峰Python学习笔记】字符串与编码

字符串与编码 三种字符编码 ASCII编码 &#xff1a;计算机由美国人发明&#xff0c;最早只有127个字符编码—— 大小写英文字母、数字和符号Unicode&#xff1a;把中文、日文、韩文等所有语言统一到一套编码中&#xff0c;2-4byte&#xff0c;现代OS和大多数语言都支持utf-8&a…

application

说明: 进行应用级操作.比如:设置提醒框,打开其他应用,显示联网状态,控制状态栏 单例对象, UIApplication *app[UIApplication sharedApplication];常用方法 方法1:设置app图标数字提示信息//设置app图标数字提示信息app.applicationIconBadgeNumber10;//ios8以后需要实现以下方…

博客园2013年4月份第2周源码发布详情

Silk Navigation for ASP.NET源码 2013-4-12 [VS2010]功能介绍&#xff1a;Silk Navigation 微软提供&#xff0c;为构建cross-browser 的Web应用程序&#xff0c;是用ASP.NET MVC3和jQuery的。它是非常简单使用ASP.NET Web窗体构建&#xff0c;从而在一个相当小的&#xff0c…

iOS 静态库封装

静态库和动态库 静态库和动态库存在形式 静态库&#xff1a;以.a 和 .framework为文件后缀名。动态库&#xff1a;以.tbd(之前叫.dylib) 和 .framework 为文件后缀名。 静态库和动态库的区别 静态库&#xff1a;链接时会被完整的复制到可执行文件中&#xff0c;被多次使用就有多…

【廖雪峰Python学习笔记】list tuple dict set

列表元组字典集合创建l [1, ‘a’, [1, 3], True]t (1, )d {‘key’ : ‘value’}s set([1, 2, 4, 2, 1])索引l[1]t[0]d.get(‘key’)/插入l.insert(1, ‘3’) / l.append(‘4’)/d[‘k1’] ‘v1’s.add(‘9’)修改l[0] 4/d[‘k1’] v/移除l.pop(0)/d.pop(‘k1’)s.remo…

响应式布局简明示例

响应式布局简明示例&#xff0c;响应式布局最好同时也是自适应布局&#xff0c;然后再配合css3媒体查询&#xff0c;来达到完美的响应式布局。css3的媒体查询ie9一下是不支持的&#xff0c;这太遗憾了&#xff0c;不过幸运的是有大神已经为前端屌丝们写好了用于IE9以下的媒体查…

iOS - APP任意push新页面那些事

大家都知道&#xff0c;UINavigationController对象有一个方法pushViewController&#xff0c;用来做视图跳转&#xff0c;也是在iOS开发中常用的页面转换方法之一。大多数APP的结构一般都是&#xff0c;使用一个UITabBarController&#xff0c;每个tab上都是一个UINavigationC…

主攻ASP.NET.4.5 MVC4.0之重生:Entity Framework生成实体类步骤(十三)

1.新建一个ASP.NET MVC 4.0 项目 2.安装Entity Framework Power Tools 3.Entity Framework- -RepositoryReverse Engineer Code First 4.Install-Package EntityFramework or Update-Package EntityFramework PM -Repository Install-Package EntityFramework 已安装“EntityFr…

【廖雪峰Python学习笔记】高阶函数

Higher-order function高阶函数映射过滤算法排序算法高阶函数 变量可指向函数 >>> abs # 函数 <built-in function abs> >>> abs(-0) # 函数调用 0 >>> func abs # 变量可指向函数 >>> func(-9) # 调用变量 调用函数 9函数名…

丁贵才130702010042第二次作业

第二次作业 2.9 设有如下语句&#xff0c;请用相应的谓词公式分别把它们表示出来&#xff1a; &#xff08;1&#xff09;有的人喜欢梅花&#xff0c;有的人喜欢菊花&#xff0c;有的人既喜欢梅花有喜欢梅花。 解&#xff1a;定义谓词 P&#xff08;x&#xff09;&#xff1a;x…

SpringMVC @RequestBody接收Json对象字符串

以前&#xff0c;一直以为在SpringMVC环境中&#xff0c;RequestBody接收的是一个Json对象&#xff0c;一直在调试代码都没有成功&#xff0c;后来发现&#xff0c;其实 RequestBody接收的是一个Json对象的字符串&#xff0c;而不是一个Json对象。然而在ajax请求往往传的都是Js…

【iOS】自定义日期选择器

自定义了一个日期选择器&#xff0c;与大家分享一下&#xff0c;期待宝贵建议。 github下载地址&#xff1a;https://github.com/huahua0809/XHDatePicker 下面只是说明一下怎么用&#xff0c;具体实现请下载代码看看&#xff1b; 如果大家觉得这个分享有所帮助的话&#xff0c…

【廖雪峰Python学习笔记】函数式编程

Functional Programming高阶函数返回函数匿名函数装饰器偏函数高阶函数 面向过程的程序设计&#xff1a; 把大段代码拆成函数&#xff0c;通过一层层函数调用&#xff0c;可将复杂任务分解成若干简单的任务函数是面向过程的程序设计的基本单位计算机Computer && 计算c…

asp 随机读取ID之Access

我在用ASP连接access 这个桌面数据库的时候&#xff0c;有时候要随机读取ID&#xff0c;传统的办法是&#xff1a; select top 3 * from tablename order by Rnd(ID) 但这样不行&#xff0c;默认还是按ID排序。 解决办法加上timer() 这个函数 select top 3 * from tablenam…

iOS Plist 文件的 增 删 改

一&#xff1a;Plist 文件的创建 Plist 文件作为我们IOS开发的一种数据存储文件&#xff0c;还是经常会用到的。在看《X-code江湖录》的时候&#xff0c;看到了这一点。自己就写了一下&#xff0c;把写的东西分享出来&#xff01;先看看它的创建&#xff0c;它的创建和我们其他…