1. 项目背景
视频传输: 在一台电脑上播放视频(捕捉摄像头画面),同局域网内另一台电脑上实时播放,尽量不卡顿。
先放最后的照片,和用gif展示一下视频效果。
传输视频可以采取图片或者流的形式,本文采取传输图片的形式,在1s之内显示多张图片从而形成连续的视频画面。
经费有限,所有实验均基于笔记本电脑。
使用的视频源是本机摄像头,以及进击的巨人720p资源。
2. 解决方案
1. 使用Python的Socket,使用opencv捕捉摄像头/视频的画面。
2. 原始的图片很大(720p的大小是1920*1080*3),整图就算压缩成jpg格式其大小也非常大。而UDP最大只能传输65535字节大小的数据区,故对图片进行分块,分块过后的数据压缩成jpg格式,并对图片分块数据进行编号。
3. 实验检测表明,本文实验环境发送端不需要使用发送队列,基本上新生成的帧很快就能被socket传输掉。
4. 接收端使用多线程接收,每个线程是一个socket,接收过后的数据存储于数据片池。
5. 接收端另开一个线程,用于反复从数据片池 读取数据片,根据数据片的编号更新幕布,这里幕布是专门用于图像显示的一个数组,其维度是720p(1920*1080*3)。更新过后的结果暂存于图片池
6. 主线程反复从图片池读取图片,并显示。
3. 实现细节
3.1 TCP/UDP的选择
为了实现低延迟,毫无疑问选取无连接的UDP传输。
3.2 图片分片算法
这里来2源gaodaima#com搞(代@码&网其实也谈不上什么算法,就是将图片水平分割。这种做法的好处在于,分割后图片的编号可以和区域一一对应。本文没有探索更为复杂的图片分片算法。
经过处理,图片变为一个个分片,如下:
对上述图片进行编号,很显然可以编号0,1,2,3,对于任意分块(例如2)在图像数组中对应的区域是frame[2*piece_size:(2+1)*piece_size],其中piece_size表示一片数据的大小。
这种对应关系方便解压后的图像还原操作。
3.3 JPG压缩
这其实是个很小的技术点,因为使用的压缩算法都是现成的。但是值得一提的是,JPG的压缩率是真的高,在实验数据上实现了10-20倍的压缩率。
使用了多线程压缩,压缩完过后,更新对应的桶,这里的桶实际上就是数据片。
由主线程Main Thread反复从桶里取数据片(t1),每取1片发送一次,然后再取下一片(t2),直到所有桶都被取了一次(例子中有10片)。