福州网站关键词推广,杭州网站建设技术,企业名录搜索网站,wordpress 搜索制作实现背景
录像有什么难的#xff1f;无非就是数据过来#xff0c;编码保存mp4而已#xff0c;这可能是好多开发者在做录像模块的时候的思考输出。是的#xff0c;确实不难#xff0c;但是做好#xff0c;或者和其他模块有非常好的逻辑配合#xff0c;确实不容易。
好多…实现背景
录像有什么难的无非就是数据过来编码保存mp4而已这可能是好多开发者在做录像模块的时候的思考输出。是的确实不难但是做好或者和其他模块有非常好的逻辑配合确实不容易。
好多开发者希望聊聊录像模块实际上录像这块需求层面的东西大家都清楚无非就是设计的时候做的更智能逻辑清晰而已。
设计思路
以大牛直播SDK的录像模块的技术实现为例我们在设计的时候确保录像模块和RTMP推送、内置轻量级RTSP服务、转发模块、GB28181设备接入模块完全隔离可以组合使用也可以分开始用。
录像数据源这块很好理解无非就是编码前的yuv、nv12、nv21、rgb、pcm等 比如Android camera、camera2或者otg采集到的数据等编码成H.264/H.265/AAC或外部接口直接投递的编码后的264、h265、aac等。
录像模块的功能层面比较好理解比如需要支持随时录像设置单个录像文件大小、录像路径等并支持纯音频、纯视频、音视频录制模式此外最好支持录像过程中暂停录像、恢复录像。 从开始录像到录像结束需要设计event callback告诉上层逻辑什么时候开始录像了什么时候生成了个录像文件路径是什么。
文件格式MP4涉及相关库libSmartPublisher.so头文件SmartPublisherJniV2.javaJarsmartavengine.jar
接口概述 Android录像模块接口概述 调用描述 接口 接口描述 录像设置 是否录像 SmartPublisherSetRecorder 设置是否启用本地录像 创建录像目录 SmartPublisherCreateFileDirectory 创建录像文件目录 设置录像目录 SmartPublisherSetRecorderDirectory 设置录像文件目录 音频录像 SmartPublisherSetRecorderAudio 音频录制开关 视频录像 SmartPublisherSetRecorderVideo 视频录制开关 设置录像文件大小 SmartPublisherSetRecorderFileMaxSize 设置每个录像文件的大小比如100M超过这个大小后会自动生成下一个录像文件 开始录像 SmartPublisherStartRecorder 开始录像 暂停/恢复录像 SmartPublisherPauseRecorder Pause recorder(暂停/恢复录像) 停止录像 SmartPublisherStopRecorder 停止录像
调用示例 录像配置 void ConfigRecorderParam() {if (libPublisher ! null publisherHandle ! 0) {if (recDir ! null !recDir.isEmpty()) {int ret libPublisher.SmartPublisherCreateFileDirectory(recDir);if (0 ret) {if (0 ! libPublisher.SmartPublisherSetRecorderDirectory(publisherHandle, recDir)) {Log.e(TAG, Set record dir failed , path: recDir);return;}// 更细粒度控制录像的, 一般情况无需调用//libPublisher.SmartPublisherSetRecorderAudio(publisherHandle, 0);//libPublisher.SmartPublisherSetRecorderVideo(publisherHandle, 0);if (0 ! libPublisher.SmartPublisherSetRecorderFileMaxSize(publisherHandle, 200)) {Log.e(TAG, SmartPublisherSetRecorderFileMaxSize failed.);return;}} else {Log.e(TAG, Create record dir failed, path: recDir);}}}}
开始、停止录像 class ButtonStartRecorderListener implements View.OnClickListener {public void onClick(View v) {if (isRecording) {stopRecorder();if (!isPushingRtmp !isRTSPPublisherRunning !isGB28181StreamRunning) {ConfigControlEnable(true);}btnStartRecorder.setText(实时录像);btnPauseRecorder.setText(暂停录像);btnPauseRecorder.setEnabled(false);isPauseRecording true;return;}Log.i(TAG, onClick start recorder..);if (libPublisher null)return;if (!isPushingRtmp !isRTSPPublisherRunning !isGB28181StreamRunning) {InitAndSetConfig();}ConfigRecorderParam();int startRet libPublisher.SmartPublisherStartRecorder(publisherHandle);if (startRet ! 0) {if (!isPushingRtmp !isRTSPPublisherRunning !isGB28181StreamRunning) {if (publisherHandle ! 0) {long handle publisherHandle;publisherHandle 0;libPublisher.SmartPublisherClose(handle);}}Log.e(TAG, Failed to start recorder.);return;}if (!isPushingRtmp !isRTSPPublisherRunning !isGB28181StreamRunning) {CheckInitAudioRecorder();ConfigControlEnable(false);}startLayerPostThread();btnStartRecorder.setText(停止录像);isRecording true;btnPauseRecorder.setEnabled(true);isPauseRecording true;}}停止录像封装 //停止录像private void stopRecorder() {if(!isRecording)return;isRecording false;if (!isPushingRtmp !isRTSPPublisherRunning !isGB28181StreamRunning)stopLayerPostThread();if (!isPushingRtmp !isRTSPPublisherRunning !isGB28181StreamRunning) {if (audioRecord_ ! null) {Log.i(TAG, stopRecorder, call audioRecord_.StopRecording..);audioRecord_.Stop();if (audioRecordCallback_ ! null) {audioRecord_.RemoveCallback(audioRecordCallback_);audioRecordCallback_ null;}audioRecord_ null;}}if (null libPublisher || 0 publisherHandle)return;libPublisher.SmartPublisherStopRecorder(publisherHandle);if (!isPushingRtmp !isRTSPPublisherRunning !isGB28181StreamRunning) {releasePublisherHandle();}}
暂停/恢复录像 class ButtonPauseRecorderListener implements View.OnClickListener {public void onClick(View v) {if (isRecording) {if(isPauseRecording){int ret libPublisher.SmartPublisherPauseRecorder(publisherHandle, 1);if (ret 0){isPauseRecording false;btnPauseRecorder.setText(恢复录像);}else if(ret 3){Log.e(TAG, Pause recorder failed, please re-try again..);}else{Log.e(TAG, Pause recorder failed..);}}else{int ret libPublisher.SmartPublisherPauseRecorder(publisherHandle, 0);if (ret 0){isPauseRecording true;btnPauseRecorder.setText(暂停录像);}else if(ret 3){Log.e(TAG, Resume recorder failed, please re-try again..);}else{Log.e(TAG, Resume recorder failed..);}}}}}
event回调
case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_RECORDER_START_NEW_FILE:publisher_event 开始一个新的录像文件 : param3;break;
case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_ONE_RECORDER_FILE_FINISHED:publisher_event 已生成一个录像文件 : param3;break;
技术总结
录像模块单纯地实现不难如果是需要和GB28181设备接入模块、RTMP推送、轻量级RTSP服务模块一起使用的时候需要考虑的就多了感兴趣的开发者可以酌情参考。