前言
直播流程模型如下图
1.采集
采集是整个直播过程中的第一个环节,负责从采集设备中采集原始数据传递到下一个环节,采集设备可以是手机也可以是摄像机等设备,原始数据的采集涉及两方面数据的采集:音频采集和图像采集。
音频数据采集
数字化的声音数据就是音频数据。数字化声音的过程实际上就是以一定的频率对来自microphone 等设备的连续的模拟音频信号进行模数转换(ADC)得到音频数据的过程;数字化声音的播放就是将音频数据进行数模转换(DAC)变成模拟音频信号输出。在数字化声音时有两个重要的指标,即采样频率(Sampling Rate)和采样大小(SamplingSize)。
采样
声音是由物体振动产生的声波。而波是无限光滑的,采样的过程就是从波中抽取某些点的值。
数码音频系统是通过将声波波形转换成一连串的二进制数据来再现原始声音的,实现这个步骤使用的设备是模/数转换器(A/D)它以每秒上万次的速率对声波进行采样,每一次采样都记录下了原始模拟声波在某一时刻的状态,称之为样本。将一串的样本连接起来,就可以描述一段声波了,把每一秒钟所采样的数目称为采样频率或采率,单位为HZ(赫兹)。采样频率越高所能描述的声波频率就越高。
采样频率
音频的采样频率是指一秒钟内对声音信号的采样次数,单位为Hz,采样频率越高声音的还原就越真实越自然。
常用的采样频率:8,000 Hz - 电话所用采样率, 对于人的说话已经足够,11,025 Hz-AM调幅广播所用采样率,44,100 Hz- 音频 CD所用采样率,48000Hz则更加精确一些。
采样位数
每个采样点能够表示的数据范围。采样位数通常有8bits或16bits两种,采样位数越大,所能记录声音的变化度就越细腻,相应的数据量就越大。8位字长量化(低品质)和16位字长量化(高品质),16 bit 是最常见的采样精度。
声道
是指声音在录制或播放时在不同空间位置采集或回放的相互独立的音频信号,所以声道数也就是声音录制时的音源数量或回放时相应的扬声器数量。
PCM数据
PCM(Pulse Code Modulation,脉冲编码调制)音频数据是未经压缩的音频采样数据裸流,它是由模拟信号经过采样、量化、编码转换成的标准数字音频数据。PCM数据是经过采样后最原始的数据,未经过压缩,完全无损,但体积比较大,为了解决这个问题先后诞生了一系列的音频格式,这些音频格式运用不同的方法对音频数据进行压缩,其中有无损压缩(ALAC、APE、FLAC)和有损压缩(MP3、AAC、OGG、WMA)两种。
图像数据采集
将图像采集到的图片一帧帧组成连续播放的动画即构成视频中可视的部分。数字图像是连续的光信号经过传感器的采样在空间域上的表达。一张图像是由一个包含若干个像素点的矩形框组成的.
把图片放大可以看到图像是由很多个小格子组成的,每个小格子都只有一种颜色,这是构成图像的最小单元——像素(pixel)。不同的像素值代表了不同的颜色,像素值的值域一般在0到255(包括)之间,也就是256个整数。但0-255并不能映射到像上图所示的彩色,而只是对应黑色到白色之间的灰度值
颜色
颜色或色彩是通过眼、脑和我们的生活经验所产生的一种对光的视觉效应。简单点说,颜色就是人对光的一种感觉,由大脑产生的一种感觉
人的视网膜上布满了感光细胞,当有光线传入人眼时,这些细胞就会将刺激转化为视神经的电信号,最终在大脑得到解释。视网膜上有两类感光细胞:视锥细胞和视杆细胞。
视锥细胞大都集中在视网膜的中央,每个视网膜大概有700万个左右。每个视锥细胞包含有一种感光色素,分别对红、绿、蓝三种光敏感。这类细胞能在较明亮的环境中提供辨别颜色和形成精细视觉的功能。
视杆细胞分散分布在视网膜上,每个视网膜大概有1亿个以上。这类细胞对光线更为敏感(敏感程度是视锥细胞的100多倍),一个光子就足以激发它的活动。视杆细胞不能感受颜色、分辨精细的空间,但在较弱的光线下可以提供对环境的分辨能力(比如夜里看到物体的黑白轮廓)。
当一束光线进入人眼后,视细胞会产生4个不同强度的信号:三种视锥细胞的信号(红绿蓝)和视感细胞的信号。这其中,只有视锥细胞产生的信号能转化为颜色的感觉。三种视锥细胞(S、M和L类型)对波长长度不同的光线会有不同的反应,每种细胞对某一段波长的光会更加敏感,如下图。这些信号的组合就是人眼能分辨的颜色总和。
三种视锥细胞(S、M和L类型)对单色光谱刺激的反应( 横坐标为光的波长,纵坐标为产生信号的强度)
能够引起视锥细胞活动的光波长范围 :312.3nm至745.4mn(可见光)
这里有一个重要的理论:我们可以用3种精心选择的单色光来刺激视锥细胞,模拟出人眼所能感知的几乎所有的颜色(例如红绿光的混合光,和单色黄光,刺激视锥细胞产生的视神经信号是等效的),这就是三色加法模型。所以说"三原色"的原理是由生理因素造成的。
RGB色彩空间
要展示彩色像素可以通过三原色来表示,即我们常用的R(Red)、G(Green)、B(Blue)颜色编码方式,
android中的颜色就是通过RGB形式展现的,一个字节代表一个颜色,共需要三个字节,例如#FF0000代表红色,#00FF00代表绿色,#0000FF代表蓝色。
RGB颜色的几何立体模型如下:任何一个颜色在该立体模型中都能找到其对应的点
YUV色彩空间
YUV中的Y代表亮度信息(只靠Y亮度数据就可展现黑白图像),U和V代表色度。早期技术不发达的时候,照片打印和电视播放都只能实现黑白的灰度显示,所以Y数据就成了标准。之后才有了彩色打印和彩色电视,为了兼容之前的黑白数据,厂商发明了UV数据。YUV一起就可以实现彩色,单独使用Y可以实现黑白,这样一套数据格式就同时兼容了黑白设备和彩色设备。
采用YUV色彩空间的特点是它的亮度信号Y和色度信号U、V是分离的。如果只有 Y信号分量而没有U、V信号分量,那么这样表示的图像就是黑白灰度图像。Y'CbCr也称为YUV,是YUV的压缩版本,不同之处在于Y'CbCr用于数字图像领域,YUV用于模拟信号领域。Y'为亮度,Cb、Cr分量代表当前颜色对蓝色和红色的偏移程度。
Y'=0.5时,Cb、Cr构成的颜色平面
由于人眼对色度的敏感度不及对亮度的敏感度,图像的色度分量不需要有和亮度分量相同的清晰度,所以可以抛弃部分色度数据,进行色度抽样,从而达到压缩图像数据降低带宽的效果。
YUV色彩抽样方式主流的有三种YUV4:4:4,YUV4:2:2,YUV4:2:0,用三个图来直观地表示采集的方式,以黑点表示采样该像素点的Y分量,以空心圆圈表示采用该像素点的UV分量。
YUV 4:4:4采样,每一个Y对应一组UV分量。
YUV 4:2:2采样,每两个Y共用一组UV分量。
YUV 4:2:0采样,每四个Y共用一组UV分量。
在渲染时,不管是OpenGL还是iOS,都不支持直接渲染YUV数据,底层都是转为RGB。
2.编码
视频编码
视频编码是指连续图像的编码,与静态图像编码着眼于消除图像内的冗余信息相对,视频编码主要通过消除连续图像之间的时域冗余信息来压缩视频。
视频编码是压缩和可能改变视频内容格式的过程,有时甚至将模拟源更改为数字源。在压缩方面,目标是减少占用空间。这是因为它是一个有损的过程,会抛弃与视频相关的信息。在解压缩以进行回放时,创建原始的近似值。应用的压缩越多,抛出的数据越多,近似值与原始数据相比越差。
为什么可以压缩?(本质为去除冗余信息)
1)空间冗余:图像相邻像素之间有较强的相关性 2)时间冗余:视频序列的相邻图像之间内容相似 3)编码冗余:不同像素值出现的概率不同 4)视觉冗余:人的视觉系统对某些细节不敏感 5)知识冗余:规律性的结构可由先验知识和背景知识得到
常用名词简介
分辨率:帧宽度(Width) x 帧高度(Height)
帧率/帧速率:单位:Frame per Second,(FPS)。即这个视频每秒钟播放多少帧图像,如果帧率为30fps,则说明这个视频每秒钟播放30帧图像。
视频码率:视频码率就是数据传输时单位时间传送的数据位数,一般我们用的单位是kbps即千位每秒。通俗一点的理解就是取样率,单位时间内取样率越大,精度就越高,处理出来的文件就越接近原始文件。
I帧、B帧、P帧
I帧表示关键帧。你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成。(因为包含完整画面)P帧表示这一帧跟之前的一个关键帧(或P帧)的差别。解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。(也就是差别帧,P帧没有完整画面数据,只有与前一帧的画面差别的数据)B帧是双向差别帧。B帧记录的是本帧与前后帧的差别(具体比较复杂,有4种情况)。换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是编解码时会比较耗费CPU,而且在直播中可能会增加直播延时,因此在移动端上一般不使用B帧。
3.传输
传输的阶段包括主播端推流到服务端,服务端的流分发,观众端的拉流几部分。
下图介绍了项目中主播推流和观众端拉流的大体流程。
直播协议的选择
国内常见公开的直播协议有几个:RTMP、HLS、HDL(HTTP-FLV)、RTP
RTMP协议:
是Adobe的专利协议,现在大部分国外的CDN已不支持。在国内流行度很高。原因有几个方面:1、 开源软件和开源库的支持稳定完整。 如斗鱼主播常用的OBS软件,开源的librtmp库,服务端有nginx-rtmp插件。2、 播放端安装率高。只要浏览器支持FlashPlayer就能非常简易的播放RTMP的直播,相对其他协议而言,RTMP协议初次建立连接的时候握手过程过于复杂(底层基于TCP,这里说的是RTMP协议本身的交互),视不同的网络状况会带来给首开带来100ms以上的延迟。基于RTMP的直播一般内容延迟在2~5秒。
HTTP-FLV协议:
即使用HTTP协议流式的传输媒体内容。相对于RTMP,HTTP更简单和广为人知,而且不担心被Adobe的专利绑架。内容延迟同样可以做到2~5秒,打开速度更快,因为HTTP本身没有复杂的状态交互。所以从延迟角度来看,HTTP-FLV要优于RTMP。
HLS 协议:
即Http Live Streaming,是由苹果提出基于HTTP的流媒体传输协议。HLS有一个非常大的优点:HTML5可以直接打开播放;这个意味着可以把一个直播链接通过微信等转发分享,不需要安装任何独立的APP,有浏览器即可,所以流行度很高。社交直播APP,HLS可以说是刚需。基于HLS的直播流URL是一个m3u8的文件,里面包含了最近若干个小视频TS文件,假设列表里面的包含5个TS文件,每个TS文件包含5秒的视频内容,那么整体的延迟就是25秒。当然可以缩短列表的长度和单个TS文件的大小来降低延迟,极致来说可以缩减列表长度为1,1秒内容的m3u8文件,但是极易受网络波动影响造成卡顿。通过公网的验证,目前按同城网络可以做到比较好的效果是5~7秒的延迟,也是综合流畅度和内容延迟的结果。
RTP协议:
即Real-time Transport Protocol,用于Internet上针对多媒体数据流的一种传输层协议。实际应用场景下经常需要RTCP(RTP Control Protocol)配合来使用,可以简单理解为RTCP传输交互控制的信令,RTP传输实际的媒体数据。RTP在视频监控、视频会议、IP电话上有广泛的应用,因为视频会议、IP电话的一个重要的使用体验:内容实时性强。对比与上述3种或实际是2种协议,RTP和它们有一个重要的区别就是默认是使用UDP协议来传输数据,而RTMP和HTTP是基于TCP协议传输。
为什么UDP 能做到如此实时的效果呢?
关于TCP和UDP差别的分析文章一搜一大把,这里不在赘述,简单概括:UDP:单个数据报,不用建立连接,简单,不可靠,会丢包,会乱序;TCP:流式,需要建立连接,复杂,可靠 ,有序。实时音视频流的场景不需要可靠保障,因此也不需要有重传的机制,实时的看到图像声音,网络抖动时丢了一些内容,画面模糊和花屏,完全不重要。TCP为了重传会造成延迟与不同步,如某一截内容因为重传,导致1秒以后才到,那么整个对话就延迟了1秒,随着网络抖动,延迟还会增加成2秒、3秒,如果客户端播放是不加以处理将严重影响直播的体验。
WebRTC协议
WebRTC 是一个由Google开源的实时通信项目, 主要目标是对Web/原生App平台上的语音、视频、以及数据传输等实时通讯提供支持,底层也是基于UDP。
总结:
以延时从低到高来看,协议上方案选择为:RTP/UDP: 可以做到秒内延时,目前国内的CDN都不支持,但有些公司开发了私有协议实现了基于它们的直播,而且它们的延时都小于1秒,甚至小于500ms, 像YY, 映客直播采用的第三方技术等;webRTC: 可以做到秒内延时,实际上它也是使用的RTP,是Google开源出来的,目前社区也开始活跃,做的人也多了;依据它出服务的公司国内有声网,中国电信研究院等;HTTP-FLV: 内容延迟可以做到2~5秒,打开快;RTMP: 内容延迟可以做2~5秒,当网络不好造成重传时,延时会大量增加;HTML5 WebSocket: 方案还不成熟,延时可能也会在2~5秒;HLS: 有5~7秒的内容延迟
4.FFmpeg简单介绍
FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多code都是从头开发的。
FFmpeg在Linux平台下开发,但它同样也可以在其它操作系统环境中编译运行,包括Windows、Mac OS X等。这个项目最早由Fabrice Bellard发起,2004年至2015年间由Michael Niedermayer主要负责维护。许多FFmpeg的开发人员都来自MPlayer项目,而且当前FFmpeg也是放在MPlayer项目组的服务器上。项目的名称来自MPEG视频编码标准,前面的"FF"代表"Fast Forward"。
Mac安装FFmpeg
如果你的本本应装上XCode最新的版本那就最好不过的了,如果不是最新的版本,得先上App Store更新(安装一系列的操作需要用到,可减少耗时),如果没有安装XCode的话,建议还是别玩MAC系统了
先安装HomeBrew(官网:https://brew.sh/)
执行命令/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)”
开始安装FFmpeg,运行命令:
brew install ffmpeg
查看mp3信息
ffprobe xxx.mp3
ffprobe高级用法
ffprobe -show_format pm.mp4 //输出格式化信息
ffprobe -print_format json -show_streams pm.mp4 // 输出每个流的具体信息(以JSON格式)
ffprobe -show_frames pm.mp4 //显示帧信息
ffprobe -show_packets pm.mp4 //查看包信息
ffprobe -show_streams pm.mp4 //查看流信息
参照 https://www.jianshu.com/p/e14bc2551cfd
将Mp3转为pcm数据
```ffmpeg -i 饿狼传说.mp3 -f s16le audio1.pcm```
(PS:s16le 指定pcm的音频格式为(signed 16 bits little endian, 有符号 16 位小端))
播放pcm
ffplay -ar 48000 -channels 2 -f s16le audio1.pcm
播放的时候显示音频波形
ffplay -showmode 1 -ar 48000 -channels 2 -f s16le audio1.pcm
将pcm转为mp3
ffmpeg -f s16le -ar 44100 -ac 2 -acodec pcm_s16le -i audio1.pcm audio1.mp3
给mp3加封面等信息
ffmpeg -i audio1.mp3 -i guazi.png -map 0:0 -map 1:0 -codec copy -id3v2_version 3 out.mp3
添加图片水印到视频上
ffmpeg -i out.mp4 -i iQIYI_logo.png -filter_complex overlay output.mp4
添加到右上方
ffmpeg -i out.mp4 -vf "movie=guazi.png[watermark];[in][watermark] overlay=700:10[out]" out_logo_r.mp4
去除水印
ffmpeg -i out.mp4 -vf delogo=x=768:y=20:w=78:h=60:show=1 out_delogo.mp4
抓取视频的一些帧,存为jpeg图片
ffmpeg -i out.mp4 -r 1 -q:v 2 -f image2 pic-%03d.jpeg
-r 表示每一秒几帧
-q:v表示存储jpeg的图像质量,一般2是高质量。
ffmpeg -i out.mp4 -ss 00:00:20 -t 10 -r 1 -q:v 2 -f image2 pic-%03d.jpeg
-ss 表示开始时间
-t表示共要多少时间。
转换为Yuv
ffmpeg -i out.mp4 out.yuv
播放yuv
ffplay -video_size 848x478 out.yuv
知识图谱