该文章面向对WebRTC有一定基础的码农,如果完全没了解过WebRTC的朋友,可以点赞并私信我进行一对一辅导哦。
其实WebRTC已经提供了一个org.webrtc.VideoFileRenderer.java的渲染器,专门用于把画面数据存储到本地文件,该渲染器与SurfaceViewRenderer.java一样实现了VideoSink接口。
通过VideoTrack.addSink(VideoSink sink)方法把渲染器添加到画面轨道中,即开始录制画面。
通过VideoTrack.removeSink(VideoSink sink)方法可把渲染器从画面轨道中移除,即停止录制画面。
mStartRecordBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 开始录制
String filePath = getExternalFilesDir(null).getAbsolutePath() + File.separator + System.currentTimeMillis() + ".y4m";
try {
mVideoFileRenderer = new VideoFileRenderer(filePath, 480, 640, mEglContext);
} catch (IOException e) {
e.printStackTrace();
mVideoFileRenderer = null;
return;
}
mVideoTrack.addSink(mVideoFileRenderer);
}
});
mStopRecordBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 停止录制
if (mVideoFileRenderer != null) {
mVideoTrack.removeSink(mVideoFileRenderer);
mVideoFileRenderer.release();
mVideoFileRenderer = null;
}
}
});
WebRTC-Android SDK自带的实现方式因为有两个重大的缺陷,导致正常的业务基本用不上这种实现方式。
但万幸的是flutter-webrtc项目早已看透了这一切,然后大喊一声我自己来,然后com.cloudwebrtc.webrtc.record.VideoFileRenderer.java这个类就出来了。
跟WebRTC-Android SDK的VideoFileRenderer一样,该渲染器也实现了VideoSink接口,并且额外实现了SamplesReadyCallback接口,实现VideoSink接口是为了获取画面数据,SamplesReadyCallback则是为了获取音频数据。
废话不多,直接上代码
mInitPeerConnectionFactoryBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 初始化PeerConnectionFactory
......
mPeerConnectionFactory = new PeerConnectionFactory.Builder()
......
.setAudioDeviceModule(JavaAudioDeviceModule.builder(context)
.setSamplesReadyCallback(new JavaAudioDeviceModule.SamplesReadyCallback() {
@Override
public void onWebRtcAudioRecordSamplesReady(JavaAudioDeviceModule.AudioSamples audioSamples) {
if (mVideoFileRenderer != null) {
// 把音频数据传给VideoFileRenderer
mVideoFileRenderer.onWebRtcAudioRecordSamplesReady(audioSamples);
}
}
})
......
.createAudioDeviceModule());
......
}
});
mStartRecordBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 开始录制
String filePath = getExternalFilesDir(null).getAbsolutePath() + File.separator + System.currentTimeMillis() + ".mp4";
try {
mVideoFileRenderer = new VideoFileRenderer(filePath, mEglContext, true);
} catch (IOException e) {
e.printStackTrace();
mVideoFileRenderer = null;
return;
}
mVideoTrack.addSink(mVideoFileRenderer);
}
});
mStopRecordBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 停止录制
if (mVideoFileRenderer != null) {
mVideoTrack.removeSink(mVideoFileRenderer);
mVideoFileRenderer.release();
mVideoFileRenderer = null;
}
}
});
至此,我们就可以边直播边录像了!而且录制出来的是mp4文件,视频经过了压缩,文件大小就是正常的mp4文件大小了。
但是,flutter-webrtc的VideoFileRenderer还是有点小问题,就是对于音频的时间计算有点问题,里面直接固定写死音频的采样率是48000Hz,所以我们还需要对VideoFileRenderer进行一点小修改:
@Override
public void onWebRtcAudioRecordSamplesReady(JavaAudioDeviceModule.AudioSamples audioSamples) {
if (!isRunning)
return;
audioThreadHandler.post(() -> {
......
if (bufferIndex >= 0) {
......
// presTime += data.length * 125 / 12; // 1000000 microseconds / 48000hz / 2 bytes
presTime += data.length * (1_000_000 / audioSamples.getSampleRate() / 2); //16位最后那个数字是2,8位是1
}
drainAudio();
});
}
完美结束~
在上一篇 SignalR 文章中,演示了如何通过 SignalR 实现了简单的聊天室功能;本...
下表包含了元字符的完整列表以及它们在正则表达式上下文中的行为: 字符 描述 \ ...
JWT,全称 Json web token,是为了在网络应用环境间传递声明而执行的一种基于JSO...
前言 由于编程思想与数据库的设计模式不同,生出了一些ORM框架。核心都是将关系...
痴月熊学习python 开始学习 注释 个人总结 开始学习 第一次使用CSDN发文章。GIAO...
本文实例为大家分享了JS代码实现页面切换效果的具体代码,供大家参考,具体内容...
Redis是什么 redis是一个基于内存的高性能的 key-value 数据库。 Redis与Memcach...
在html页面中,我们有时需要让div中的内容超出后自动显示滚动条,我们可以这样设...
普通的替换函数 复制代码 代码如下: public function HighLight(S,F) dim tL,tM,...
本文实例讲述了tp5.1 框架路由操作-URL生成。分享给大家供大家参考,具体如下: ...