React Native + WebRTC + GPUImage一套解決方案
簡(jiǎn)介
想給爸媽視頻的時(shí)候加點(diǎn)美顏效果鞠呈,然后再電腦上也能看融师,本人是前端,所以技術(shù)選型如下:
- react-native-webrtc
- WebRTC 57版本
- GPUImage + BeautifyFaceDemo
- Swift + OC混編
大體步驟如下
- 更改WebRTC源碼蚁吝,將攝像頭獲取到的CMSampleBuffer傳遞出去旱爆,然后新增一個(gè)接口接受更改好的CVPixelBuffer。
- 將接收到的sample buffer傳遞給GPUImageMovie進(jìn)行處理窘茁,給GPUImageMovie添加任意濾鏡
- 使用最新master上的GPUImage怀伦,其給GPUImageFrameBuffer暴露了獲取CVPixelBuffer的接口
- 自己寫(xiě)一個(gè)簡(jiǎn)單的GPUImagePixelOutput用上一條說(shuō)的接口輸出加好濾鏡的CVPixelBuffer。
- 然后將這個(gè)pixel buffer傳回到WebRTC中山林。
- 你傳回去的這個(gè)pixel buffer已經(jīng)被GPUImage處理成RGBA顏色的了房待,可是WebRTC只支持解析YUV的視頻,為了讓它能正常展示驼抹,我們需要用H264編碼桑孩,而不是默認(rèn)的VP8,如果在SDP文件中寫(xiě)明了視頻是H264的框冀,視頻傳遞給別的客戶端之前是會(huì)被進(jìn)行編碼的褒纲,這個(gè)時(shí)候就不管你輸入是RGBA還是YUV都能得到正確的處理裸扶。
- 然而烫沙,這個(gè)時(shí)候WebRTC有兩個(gè)流程漫试,當(dāng)沒(méi)有peer connection的時(shí)候极谊,自己本地的視頻流預(yù)覽并不會(huì)走編碼就直接到renderer了诡右。而上面說(shuō)了WebRTC自己的renderer是不認(rèn)RGBA的。所以只有兩條路走:1. 自己寫(xiě)一個(gè)兼容的renderer轻猖,2. 自己的流就不走WebRTC的renderer了帆吻,反正有更好用的GPUImageView能用。這兩種都實(shí)現(xiàn)過(guò)之后咙边,選擇使用后者猜煮。
- 更改react-native-webrtc源碼,讓其支持H264的SDP败许。
- 將自己寫(xiě)的GPUImageView暴露給React Native
- 用react-native-webrtc完成所有流程
WebRTC更改編譯
54版本
問(wèn)題在于王带,沒(méi)有編譯成.framework的腳本,得自己寫(xiě)市殷。
已經(jīng)鎖定的版本號(hào)有編譯錯(cuò)誤
- BUILD.gn 增加編譯成framework的代碼
- sdk.gyp
- 修復(fù)未使用結(jié)果的警告
57版本
- BUILD.gn 增加新增文件
添加代理愕撰,將CMSampleBuffer轉(zhuǎn)發(fā)、接收
Header中新建RTCVideoProxy.h文件,Classes中新建RTCVideoProxy.m文件
react-native-webrtc源碼更改
找到AppRTCDemo里的增加h264描述的函數(shù)
其他問(wèn)題
- 獲取到的圖被旋轉(zhuǎn)了90度
- 關(guān)于性能優(yōu)化
性能優(yōu)化
少開(kāi)動(dòng)畫(huà)少開(kāi)動(dòng)畫(huà)少開(kāi)動(dòng)畫(huà)~8阏酢4佟!
或者所有動(dòng)畫(huà)都用lottie實(shí)現(xiàn)囱桨,盡可能降低js開(kāi)銷
盡量減小javascript開(kāi)銷
消除無(wú)用動(dòng)畫(huà)示例:
// AnimatedComponent
value = new Animated.Value(0)
animate = () => { this._animate() }
_animate = (force: boolean = false) => {
if (this.props.animated || force) {
this.value.setValue(0)
Animated.timing(this.value, {
toValue: 1,
duration: 6000,
}).start(this.animate)
}
}
componentDidMount() { this.animate() }
componentWillReceiveProps(nextProps: LoadingAvatarProps) {
if (this.props.animated !== nextProps.animated) {
if (nextProps.animated) {
this._animate(nextProps.animated)
} else {
this.value.stopAnimation()
}
}
}
componentWillUnmount() {
this.value.stopAnimation()
}
React-native-webrtc深坑不能設(shè)置getusermedia的設(shè)置仓犬。。舍肠。做客戶端webrtc開(kāi)發(fā)還是得用原生的方法搀继。
附錄:WebRTC源碼中比較讓人在意的點(diǎn)
- VideoBroadcast中分發(fā)frame給接收者
- 旋轉(zhuǎn)
工作比較忙....持續(xù)更新