凡科可以做淘客网站吗网站关键词词库怎么做
web/
2025/9/28 13:17:10/
文章来源:
凡科可以做淘客网站吗,网站关键词词库怎么做,找推广平台需要多少钱,wordpress建个人博客背景
随着智能门禁等物联网产品的普及#xff0c;越来越多的开发者对音视频互动体验提出了更高的要求。目前市面上大多一对一互动都是基于WebRTC#xff0c;优点不再赘述#xff0c;我们这里先说说可能需要面临的问题#xff1a;WebRTC的服务器部署非常复杂#xff0c;可…背景
随着智能门禁等物联网产品的普及越来越多的开发者对音视频互动体验提出了更高的要求。目前市面上大多一对一互动都是基于WebRTC优点不再赘述我们这里先说说可能需要面临的问题WebRTC的服务器部署非常复杂可以私有部署但是非常复杂。传输基于UDP很难保证传输质量由于UDP是不可靠的传输协议在复杂的公网网络环境下各种突发流量、偶尔的传输错误、网络抖动、超时等等都会引起丢包异常都会在一定程度上影响音视频通信的质量难以应对复杂的互联网环境如跨区跨运营商、低带宽、高丢包等场景行话说的好从demo到实用,中间还差1万个WebRTC。
其他技术方案
内网环境下的RTSP轻量级服务基于RTMP的公网或内网技术方案。
本方案系基于现有RTMP或内置RTSP服务、RTMP/RTSP直播播放模块产品稳定度高在保证超低延迟的基础上加入噪音抑制、回音消除、自动增益控制等特性确保通话体验如需更好的消除效果亦可考虑如麦克风阵列等技术方案采用通用的RTMP服务器如nginx、SRS或自身的轻量级RTSP服务更有利于私有部署便于支持H.264的扩展SEI消息发送机制方便扩展特定机型H.265编码支持。
技术实现
废话不多说先上图 关键demo代码说明
拉流播放 btnPlaybackStartStopPlayback.setOnClickListener(new Button.OnClickListener() { // Override public void onClick(View v) { if(isPlaybackViewStarted){Log.i(PLAY_TAG, Stop playback stream);btnPlaybackStartStopPlayback.setText(开始播放 );//btnPopInputText.setEnabled(true);btnPlaybackPopInputUrl.setEnabled(true);btnPlaybackHardwareDecoder.setEnabled(true);btnPlaybackSetPlayBuffer.setEnabled(true);btnPlaybackFastStartup.setEnabled(true);if ( playerHandle ! 0 ){libPlayer.SmartPlayerStopPlay(playerHandle);libPlayer.SmartPlayerClose(playerHandle);playerHandle 0;}isPlaybackViewStarted false;Log.i(PLAY_TAG, Stop playback stream--);}else{Log.i(PLAY_TAG, Start playback stream);playerHandle libPlayer.SmartPlayerOpen(curContext);if(playerHandle 0){Log.e(PLAY_TAG, surfaceHandle with nil..);return;}libPlayer.SetSmartPlayerEventCallbackV2(playerHandle,new EventHandePlayerV2());libPlayer.SmartPlayerSetSurface(playerHandle, playerSurfaceView); //if set the second param with null, it means it will playback audio only..// libPlayer.SmartPlayerSetSurface(playerHandle, null); libPlayer.SmartPlayerSetRenderScaleMode(playerHandle, 1);// External Render test//libPlayer.SmartPlayerSetExternalRender(playerHandle, new RGBAExternalRender());//libPlayer.SmartPlayerSetExternalRender(playerHandle, new I420ExternalRender());libPlayer.SmartPlayerSetExternalAudioOutput(playerHandle, new PlayerExternalPcmOutput());libPlayer.SmartPlayerSetAudioOutputType(playerHandle, 1);libPlayer.SmartPlayerSetBuffer(playerHandle, playbackBuffer);libPlayer.SmartPlayerSetFastStartup(playerHandle, isPlaybackFastStartup?1:0);if ( isPlaybackMute ){libPlayer.SmartPlayerSetMute(playerHandle, isPlaybackMute?1:0);}if (isPlaybackHardwareDecoder) {int isSupportHevcHwDecoder libPlayer.SetSmartPlayerVideoHevcHWDecoder(playerHandle,1);int isSupportH264HwDecoder libPlayer.SetSmartPlayerVideoHWDecoder(playerHandle,1);Log.i(TAG, isSupportH264HwDecoder: isSupportH264HwDecoder , isSupportHevcHwDecoder: isSupportHevcHwDecoder);}if( playbackUrl null ){Log.e(PLAY_TAG, playback URL with NULL...); return;}libPlayer.SmartPlayerSetAudioVolume(playerHandle, curAudioVolume);libPlayer.SmartPlayerSetUrl(playerHandle, playbackUrl);int iPlaybackRet libPlayer.SmartPlayerStartPlay(playerHandle);if( iPlaybackRet ! 0 ){libPlayer.SmartPlayerClose(playerHandle);playerHandle 0;Log.e(PLAY_TAG, StartPlayback strem failed..); return;}btnPlaybackStartStopPlayback.setText(停止播放 );btnPlaybackPopInputUrl.setEnabled(false);btnPlaybackHardwareDecoder.setEnabled(false);btnPlaybackSetPlayBuffer.setEnabled(false);btnPlaybackFastStartup.setEnabled(false);isPlaybackViewStarted true;Log.i(PLAY_TAG, Start playback stream--);}}});
拉流端实时音量调节 audioVolumeBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {Overridepublic void onProgressChanged(SeekBar seekBar, int i, boolean b) {}Overridepublic void onStartTrackingTouch(SeekBar seekBar) {//Log.i(TAG, 开始拖动);}Overridepublic void onStopTrackingTouch(SeekBar seekBar) {Log.i(TAG, 停止拖动, CurProgress: seekBar.getProgress());curAudioVolume seekBar.getProgress();audioVolumeText.setText(当前音量: curAudioVolume);if(playerHandle ! 0){libPlayer.SmartPlayerSetAudioVolume(playerHandle, curAudioVolume);}}});}
回调后的PCM数据传给推送端用于音频处理 class NTAudioRecordV2CallbackImpl implements NTAudioRecordV2Callback{Overridepublic void onNTAudioRecordV2Frame(ByteBuffer data, int size, int sampleRate, int channel, int per_channel_sample_number){/*Log.i(TAG, onNTAudioRecordV2Frame size size sampleRate sampleRate channel channel per_channel_sample_number per_channel_sample_number);*/if ( (isPushingRtmp || isRTSPPublisherRunning) publisherHandle ! 0 ){libPublisher.SmartPublisherOnPCMData(publisherHandle, data, size, sampleRate, channel, per_channel_sample_number);}}} class PlayerExternalPcmOutput implements NTExternalAudioOutput{ private int sample_rate_ 0;private int channel_ 0;private int sample_size 0;private int buffer_size 0;private ByteBuffer pcm_buffer_ null;Overridepublic ByteBuffer getPcmByteBuffer(int size){//Log.i(getPcmByteBuffer, size: size);if(size 1){return null;}if(buffer_size ! size){buffer_size size;pcm_buffer_ ByteBuffer.allocateDirect(buffer_size);}return pcm_buffer_;}public void onGetPcmFrame(int ret, int sampleRate, int channel, int sampleSize, int is_low_latency){/*Log.i(onGetPcmFrame, ret: ret , sampleRate: sampleRate , channel: channel , sampleSize: sampleSize ,is_low_latency: is_low_latency buffer_size buffer_size);*/if ( pcm_buffer_ null)return;pcm_buffer_.rewind();if ( ret 0 (isPushingRtmp || isRTSPPublisherRunning)){libPublisher.SmartPublisherOnFarEndPCMData(publisherHandle, pcm_buffer_, sampleRate, channel, sampleSize, is_low_latency);if (is_audio_mix_){libPublisher.SmartPublisherOnMixPCMData(publisherHandle, 1, pcm_buffer_, 0, buffer_size, sampleRate, channel, sampleSize);}/*java.nio.ByteOrder old_order pcm_buffer_.order();pcm_buffer_.order(java.nio.ByteOrder.nativeOrder());java.nio.ShortBuffer short_buffer pcm_buffer_.asShortBuffer();pcm_buffer_.order(old_order);short[] short_array new short[short_buffer.remaining()];short_buffer.get(short_array);libPublisher.SmartPublisherOnMixPCMShortArray(publisherHandle, 1, short_array, 0, short_array.length, sampleRate, channel, sampleSize);*/}// test/*byte[] test_buffer new byte[16];pcm_buffer_.get(test_buffer);Log.i(TAG, onGetPcmFrame data: bytesToHexString(test_buffer));*/}}
推送端
RTMP推送 class ButtonPushStartListener implements OnClickListener{public void onClick(View v){ if (isPushingRtmp){stopPush();if (!isRTSPPublisherRunning) {ConfigControlEnable(true);}btnPushStartStop.setText(推送RTMP);isPushingRtmp false;return;}Log.i(PUSH_TAG, onClick start push rtmp..);if (libPublisher null)return;if (!isRTSPPublisherRunning) {InitPusherAndSetConfig();}if ( inputPushURL ! null inputPushURL.length() 1 ){publishURL inputPushURL;Log.i(PUSH_TAG, start, input publish url: publishURL);}else{publishURL basePushURL String.valueOf((int)( System.currentTimeMillis() % 1000000));Log.i(PUSH_TAG, start, generate random url: publishURL);}printPushText URL: publishURL;Log.i(PUSH_TAG, printPushText);textPushCurURL (TextView)findViewById(R.id.txt_push_cur_url);textPushCurURL.setText(printPushText);Log.i(PUSH_TAG, videoWidth: pushVideoWidth videoHeight: pushVideoHeight pushType: pushType);if ( libPublisher.SmartPublisherSetURL(publisherHandle, publishURL) ! 0 ){Log.e(PUSH_TAG, Failed to set rtmp pusher URL..);}int startRet libPublisher.SmartPublisherStartPublisher(publisherHandle);if (startRet ! 0) {isPushingRtmp false;Log.e(TAG, Failed to start push stream..);return;}if ( !isRTSPPublisherRunning ) {if (pushType 0 || pushType 1) {CheckInitAudioRecorder(); //enable pure video publisher..}ConfigControlEnable(false);}btnPushStartStop.setText(停止推送 );isPushingRtmp true;}};
轻量级RTSP服务模式 //启动/停止RTSP服务class ButtonRtspServiceListener implements OnClickListener {public void onClick(View v) {if (isRTSPServiceRunning) {stopRtspService();btnRtspService.setText(启动RTSP服务);btnRtspPublisher.setEnabled(false);isRTSPServiceRunning false;return;}Log.i(TAG, onClick start rtsp service..);rtsp_handle_ libPublisher.OpenRtspServer(0);if (rtsp_handle_ 0) {Log.e(TAG, 创建rtsp server实例失败! 请检查SDK有效性);} else {int port 8554;if (libPublisher.SetRtspServerPort(rtsp_handle_, port) ! 0) {libPublisher.CloseRtspServer(rtsp_handle_);rtsp_handle_ 0;Log.e(TAG, 创建rtsp server端口失败! 请检查端口是否重复或者端口不在范围内!);}//String user_name admin;//String password 12345;//libPublisher.SetRtspServerUserNamePassword(rtsp_handle_, user_name, password);if (libPublisher.StartRtspServer(rtsp_handle_, 0) 0) {Log.i(TAG, 启动rtsp server 成功!);} else {libPublisher.CloseRtspServer(rtsp_handle_);rtsp_handle_ 0;Log.e(TAG, 启动rtsp server失败! 请检查设置的端口是否被占用!);}btnRtspService.setText(停止RTSP服务);btnRtspPublisher.setEnabled(true);isRTSPServiceRunning true;}}}//发布/停止RTSP流class ButtonRtspPublisherListener implements OnClickListener {public void onClick(View v) {if (isRTSPPublisherRunning) {stopRtspPublisher();if (!isPushingRtmp) {ConfigControlEnable(true);}btnRtspPublisher.setText(发布RTSP流);btnGetRtspSessionNumbers.setEnabled(false);btnRtspService.setEnabled(true);isRTSPPublisherRunning false;return;}Log.i(TAG, onClick start rtsp publisher..);if (!isPushingRtmp) {InitPusherAndSetConfig();}if (publisherHandle 0) {Log.e(TAG, Start rtsp publisher, publisherHandle is null..);return;}String rtsp_stream_name stream1;libPublisher.SetRtspStreamName(publisherHandle, rtsp_stream_name);libPublisher.ClearRtspStreamServer(publisherHandle);libPublisher.AddRtspStreamServer(publisherHandle, rtsp_handle_, 0);if (libPublisher.StartRtspStream(publisherHandle, 0) ! 0) {Log.e(TAG, 调用发布rtsp流接口失败!);return;}if (!isPushingRtmp) {if (pushType 0 || pushType 1) {CheckInitAudioRecorder(); //enable pure video publisher..}ConfigControlEnable(false);}btnRtspPublisher.setText(停止RTSP流);btnGetRtspSessionNumbers.setEnabled(true);btnRtspService.setEnabled(false);isRTSPPublisherRunning true;}};RTMP推送和轻量级RTSP服务可以在一个实例里面处理所以推送参数的初始化只需要调用一次即可。 private void InitPusherAndSetConfig() {Log.i(TAG, videoWidth: pushVideoWidth videoHeight: pushVideoHeight pushType: pushType);int audio_opt 1;int video_opt 1;if ( pushType 1 ){video_opt 0;}else if (pushType 2 ){audio_opt 0;}publisherHandle libPublisher.SmartPublisherOpen(curContext, audio_opt, video_opt,pushVideoWidth, pushVideoHeight);if ( publisherHandle 0 ){return;}if(videoEncodeType 1){int h264HWKbps setHardwareEncoderKbps(true, pushVideoWidth,pushVideoHeight);Log.i(TAG, h264HWKbps: h264HWKbps);int isSupportH264HWEncoder libPublisher.SetSmartPublisherVideoHWEncoder(publisherHandle, h264HWKbps);if (isSupportH264HWEncoder 0) {Log.i(TAG, Great, it supports h.264 hardware encoder!);}}else if (videoEncodeType 2){int hevcHWKbps setHardwareEncoderKbps(false, pushVideoWidth,pushVideoHeight);Log.i(TAG, hevcHWKbps: hevcHWKbps);int isSupportHevcHWEncoder libPublisher.SetSmartPublisherVideoHevcHWEncoder(publisherHandle, hevcHWKbps);if (isSupportHevcHWEncoder 0) {Log.i(TAG, Great, it supports hevc hardware encoder!);}}if(is_sw_vbr_mode){int is_enable_vbr 1;int video_quality CalVideoQuality(pushVideoWidth,pushVideoHeight, true);int vbr_max_bitrate CalVbrMaxKBitRate(pushVideoWidth,pushVideoHeight);libPublisher.SmartPublisherSetSwVBRMode(publisherHandle, is_enable_vbr, video_quality, vbr_max_bitrate);}libPublisher.SetSmartPublisherEventCallbackV2(publisherHandle, new EventHandePublisherV2());//如果想和时间显示在同一行请去掉\nString watermarkText 大牛直播(daniulive)\n\n;String path pushLogoPath;if( pushWatemarkType 0 ){if ( isPushWritelogoFileSuccess )libPublisher.SmartPublisherSetPictureWatermark(publisherHandle, path, WATERMARK.WATERMARK_POSITION_TOPRIGHT, 160, 160, 10, 10);}else if( pushWatemarkType 1 ){if ( isPushWritelogoFileSuccess )libPublisher.SmartPublisherSetPictureWatermark(publisherHandle, path, WATERMARK.WATERMARK_POSITION_TOPRIGHT, 160, 160, 10, 10);libPublisher.SmartPublisherSetTextWatermark(publisherHandle, watermarkText, 1, WATERMARK.WATERMARK_FONTSIZE_BIG, WATERMARK.WATERMARK_POSITION_BOTTOMRIGHT, 10, 10);//libPublisher.SmartPublisherSetTextWatermarkFontFileName(/system/fonts/DroidSansFallback.ttf);//libPublisher.SmartPublisherSetTextWatermarkFontFileName(/sdcard/DroidSansFallback.ttf);}else if(pushWatemarkType 2){libPublisher.SmartPublisherSetTextWatermark(publisherHandle, watermarkText, 1, WATERMARK.WATERMARK_FONTSIZE_BIG, WATERMARK.WATERMARK_POSITION_BOTTOMRIGHT, 10, 10);//libPublisher.SmartPublisherSetTextWatermarkFontFileName(/system/fonts/DroidSansFallback.ttf);}else{Log.i(TAG, no watermark settings..);}//endif ( !is_push_speex ){// set AAC encoderlibPublisher.SmartPublisherSetAudioCodecType(publisherHandle, 1);}else{// set Speex encoderlibPublisher.SmartPublisherSetAudioCodecType(publisherHandle, 2);libPublisher.SmartPublisherSetSpeexEncoderQuality(publisherHandle, 8);}libPublisher.SmartPublisherSetNoiseSuppression(publisherHandle, is_push_noise_suppression?1:0);libPublisher.SmartPublisherSetAGC(publisherHandle, is_push_agc?1:0);libPublisher.SmartPublisherSetEchoCancellation(publisherHandle, 1, echoCancelDelay);libPublisher.SmartPublisherSetAudioMix(publisherHandle, is_audio_mix_?1:0);libPublisher.SmartPublisherSetInputAudioVolume(publisherHandle, 0 , mic_audio_volume_);if ( is_audio_mix_ ){libPublisher.SmartPublisherSetInputAudioVolume(publisherHandle, 1 , mix_audio_volume_);}libPublisher.SmartPublisherSetClippingMode(publisherHandle, 0);libPublisher.SmartPublisherSetSWVideoEncoderProfile(publisherHandle, push_sw_video_encoder_profile);//libPublisher.SetRtmpPublishingType(0);//libPublisher.SmartPublisherSetGopInterval(publisherHandle, 18*3);//libPublisher.SmartPublisherSetFPS(publisherHandle, 18);libPublisher.SmartPublisherSetSWVideoEncoderSpeed(publisherHandle, sw_video_encoder_speed);//libPublisher.SmartPublisherSetSWVideoBitRate(600, 1200);}相关封装 //停止rtmp推送private void stopPush() {if(!isPushingRtmp){return;}if ( !isRTSPPublisherRunning) {if (audioRecord_ ! null) {Log.i(TAG, stopPush, call audioRecord_.StopRecording..);audioRecord_.Stop();if (audioRecordCallback_ ! null) {audioRecord_.RemoveCallback(audioRecordCallback_);audioRecordCallback_ null;}audioRecord_ null;}}if (libPublisher ! null) {libPublisher.SmartPublisherStopPublisher(publisherHandle);}if (!isRTSPPublisherRunning) {if (publisherHandle ! 0) {if (libPublisher ! null) {libPublisher.SmartPublisherClose(publisherHandle);publisherHandle 0;}}}}//停止发布RTSP流private void stopRtspPublisher() {if(!isRTSPPublisherRunning){return;}if (!isPushingRtmp) {if (audioRecord_ ! null) {Log.i(TAG, stopRtspPublisher, call audioRecord_.StopRecording..);audioRecord_.Stop();if (audioRecordCallback_ ! null) {audioRecord_.RemoveCallback(audioRecordCallback_);audioRecordCallback_ null;}audioRecord_ null;}}if (libPublisher ! null) {libPublisher.StopRtspStream(publisherHandle);}if (!isPushingRtmp) {if (publisherHandle ! 0) {if (libPublisher ! null) {libPublisher.SmartPublisherClose(publisherHandle);publisherHandle 0;}}}}//停止RTSP服务private void stopRtspService() {if(!isRTSPServiceRunning){return;}if (libPublisher ! null rtsp_handle_ ! 0) {libPublisher.StopRtspServer(rtsp_handle_);libPublisher.CloseRtspServer(rtsp_handle_);rtsp_handle_ 0;}}
传递采集到的视频数据摄像头数据采集也可选用camera2的接口对焦和体验更好 Overridepublic void onPreviewFrame(byte[] data, Camera camera) {pushFrameCount;if ( pushFrameCount % 3000 0 ){Log.i(OnPre, gc);System.gc();Log.i(OnPre, gc-);}if (data null) {Parameters params camera.getParameters();Size size params.getPreviewSize();int bufferSize (((size.width|0x1f)1) * size.height * ImageFormat.getBitsPerPixel(params.getPreviewFormat())) / 8;camera.addCallbackBuffer(new byte[bufferSize]);} else {if(isPushingRtmp || isRTSPPublisherRunning){libPublisher.SmartPublisherOnCaptureVideoData(publisherHandle, data, data.length, pushCurrentCameraType, currentPushOrigentation);}camera.addCallbackBuffer(data);}}
如果内网环境下用轻量级RTSP服务的话需判断对方有没有播放自己的流数据的话可以通过获取RTSP会话数来判断是否链接。 //当前RTSP会话数弹出框private void PopRtspSessionNumberDialog(int session_numbers) {final EditText inputUrlTxt new EditText(this);inputUrlTxt.setFocusable(true);inputUrlTxt.setEnabled(false);String session_numbers_tag RTSP服务当前客户会话数: session_numbers;inputUrlTxt.setText(session_numbers_tag);AlertDialog.Builder builderUrl new AlertDialog.Builder(this);builderUrl.setTitle(内置RTSP服务).setView(inputUrlTxt).setNegativeButton(确定, null);builderUrl.show();}//获取RTSP会话数class ButtonGetRtspSessionNumbersListener implements OnClickListener {public void onClick(View v) {if (libPublisher ! null rtsp_handle_ ! 0) {int session_numbers libPublisher.GetRtspServerClientSessionNumbers(rtsp_handle_);Log.i(TAG, GetRtspSessionNumbers: session_numbers);PopRtspSessionNumberDialog(session_numbers);}}};
总结
Android平台的一对一互动除了WebRTC外在保证低延迟的前提下RTMP或RTSP技术方案也是非常不错的选择。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/83350.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!