当前位置: 首页 > news >正文

网站制作公司怎么样青岛房产交易中心官网

网站制作公司怎么样,青岛房产交易中心官网,自己建网站做推广,沈阳有什么服务网站最近一段时间#xff0c;视频直播可谓大火。在视频直播领域#xff0c;有不同的商家提供各种的商业解决方案#xff0c;包括软硬件设备#xff0c;摄像机#xff0c;编码器#xff0c;流媒体服务器等。本文要讲解的是如何使用一系列免费工具#xff0c;打造一套视频直播…最近一段时间视频直播可谓大火。在视频直播领域有不同的商家提供各种的商业解决方案包括软硬件设备摄像机编码器流媒体服务器等。本文要讲解的是如何使用一系列免费工具打造一套视频直播方案。 视频直播流程 视频直播的流程可以分为如下几步 采集 —处理—编码和封装—推流到服务器—服务器流分发—播放器流播放 1.采集 采集是整个视频推流过程中的第一个环节它从系统的采集设备中获取原始视频数据将其输出到下一个环节。视频的采集涉及两方面数据的采集音频采集和图像采集它们分别对应两种完全不同的输入源和数据格式。 音频采集 音频数据既能与图像结合组合成视频数据也能以纯音频的方式采集播放后者在很多成熟的应用场景如在线电台和语音电台等起着非常重要的作用。音频的采集过程主要通过设备将环境中的模拟信号采集成 PCM 编码的原始数据然后编码压缩成 MP3 等格式的数据分发出去。常见的音频压缩格式有MP3AACHE-AACOpusFLACVorbis (Ogg)Speex 和 AMR等。 音频采集和编码主要面临的挑战在于延时敏感、卡顿敏感、噪声消除Denoise、回声消除AEC、静音检测VAD和各种混音算法等。图像采集 将图像采集的图片结果组合成一组连续播放的动画即构成视频中可肉眼观看的内容。图像的采集过程主要由摄像头等设备拍摄成 YUV 编码的原始数据然后经过编码压缩成 H.264 等格式的数据分发出去。常见的视频封装格式有MP4、3GP、AVI、MKV、WMV、MPG、VOB、FLV、SWF、MOV、RMVB 和 WebM 等。 图像由于其直观感受最强并且体积也比较大构成了一个视频内容的主要部分。图像采集和编码面临的主要挑战在于设备兼容性差、延时敏感、卡顿敏感以及各种对图像的处理操作如美颜和水印等。视频采集 视频采集的采集源主要有摄像头采集、屏幕录制和从视频文件推流。 2.处理 视频或者音频完成采集之后得到原始数据为了增强一些现场效果或者加上一些额外的效果我们一般会在将其编码压缩前进行处理比如打上时间戳或者公司 Logo 的水印祛斑美颜和声音混淆等处理。在主播和观众连麦场景中主播需要和某个或者多个观众进行对话并将对话结果实时分享给其他所有观众连麦的处理也有部分工作在推流端完成。 如上图所示处理环节中分为音频和视频处理音频处理中具体包含混音、降噪和声音特效等处理视频处理中包含美颜、水印、以及各种自定义滤镜等处理。 3.编码和封装 1编码 如果把整个流媒体比喻成一个物流系统那么编解码就是其中配货和装货的过程这个过程非常重要它的速度和压缩比对物流系统的意义非常大影响物流系统的整体速度和成本。同样对流媒体传输来说编码也非常重要它的编码性能、编码速度和编码压缩比会直接影响整个流媒体传输的用户体验和传输成本。 视频编码的意义 原始视频数据存储空间大一个 1080P 的 7 s 视频需要 817 MB 原始视频数据传输占用带宽大10 Mbps 的带宽传输上述 7 s 视频需要 11 分钟。而经过 H.264 编码压缩之后视频大小只有 708 k 10 Mbps 的带宽仅仅需要 500 ms 可以满足实时传输的需求所以从视频采集传感器采集来的原始视频势必要经过视频编码。 基本原理 为什么巨大的原始视频可以编码成很小的视频呢?这其中的技术是什么呢?核心思想就是去除冗余信息 1空间冗余图像相邻像素之间有较强的相关性 2时间冗余视频序列的相邻图像之间内容相似 3编码冗余不同像素值出现的概率不同 4视觉冗余人的视觉系统对某些细节不敏感 5知识冗余规律性的结构可由先验知识和背景知识得到 编码器的选择 视频编码器经历了数十年的发展已经从开始的只支持帧内编码演进到现如今的 H.265 和 VP9 为代表的新一代编码器下面是一些常见的视频编码器 1H.264/AVC 2HEVC/H.265 3VP8 4VP9 5FFmpeg 注音频编码器有Mp3, AAC等。 2封装 沿用前面的比喻封装可以理解为采用哪种货车去运输也就是媒体的容器。 所谓容器就是把编码器生成的多媒体内容(视频音频字幕章节信息等)混合封装在一起的标准。容器使得不同多媒体内容同步播放变得很简单而容器的另一个作用就是为多媒体内容提供索引也就是说如果没有容器存在的话一部影片你只能从一开始看到最后不能拖动进度条而且如果你不自己去手动另外载入音频就没有声音。下面是几种常见的封装格式 1AVI 格式(后缀为 .avi) 2DV-AVI 格式(后缀为 .avi) 3QuickTime File Format 格式(后缀为 .mov) 4MPEG 格式(文件后缀可以是 .mpg .mpeg .mpe .dat .vob .asf .3gp .mp4等) 5WMV 格式(后缀为.wmv .asf) 6Real Video 格式(后缀为 .rm .rmvb) 7Flash Video 格式(后缀为 .flv) 8Matroska 格式(后缀为 .mkv) 9MPEG2-TS 格式 (后缀为 .ts) 目前我们在流媒体传输尤其是直播中主要采用的就是 FLV 和 MPEG2-TS 格式分别用于 RTMP/HTTP-FLV 和 HLS 协议。 4.推流到服务器 推流是直播的第一公里直播的推流对这个直播链路影响非常大如果推流的网络不稳定无论我们如何做优化观众的体验都会很糟糕。所以也是我们排查问题的第一步如何系统地解决这类问题需要我们对相关理论有基础的认识。 推送协议主要有三种 RTSPReal Time Streaming Protocol实时流传送协议是用来控制声音或影像的多媒体串流协议, 由RealNetworks和Netscape共同提出的RTMP(Real Time MessagingProtocol)实时消息传送协议是Adobe公司为Flash播放器和服务器之间音频、视频和数据传输 开发的开放协议HLS(HTTP Live Streaming)是苹果公司(Apple Inc.)实现的基于HTTP的流媒体传输协议 RTMP协议基于 TCP是一种设计用来进行实时数据通信的网络协议主要用来在 flash/AIR 平台和支持 RTMP 协议的流媒体/交互服务器之间进行音视频和数据通信。支持该协议的软件包括 Adobe Media Server/Ultrant Media Server/red5 等。 它有三种变种 - RTMP工作在TCP之上的明文协议使用端口1935 - RTMPT封装在HTTP请求之中可穿越防火墙 - RTMPS类似RTMPT但使用的是HTTPS连接 RTMP 是目前主流的流媒体传输协议广泛用于直播领域可以说市面上绝大多数的直播产品都采用了这个协议。 RTMP协议就像一个用来装数据包的容器这些数据可以是AMF格式的数据,也可以是FLV中的视/音频数据。一个单一的连接可以通过不同的通道传输多路网络流。这些通道中的包都是按照固定大小的包传输的。 5.服务器流分发 流媒体服务器的作用是负责直播流的发布和转播分发功能。 流媒体服务器有诸多选择如商业版的Wowza。但我选择的是Nginx它是一款优秀的免费Web服务器后面我会详细介绍如何搭建Nginx服务器。 6.播放器流播放 主要是实现直播节目在终端上的展现。因为我这里使用的传输协议是RTMP 所以只要支持 RTMP 流协议的播放器都可以使用譬如 电脑端VLC等 手机端Vitamio以及ijkplayer等 一般情况下我们把上面流程的前四步称为第一部分即视频主播端的操作。视频采集处理后推流到流媒体服务器第一部分功能完成。第二部分就是流媒体服务器负责把从第一部分接收到的流进行处理并分发给观众。第三部分就是观众啦只需要拥有支持流传输协议的播放器即可。 第一部分采集推流SDK 目前市面上集视频采集、编码、封装和推流于一体的SDK已经有很多了例如商业版的NodeMedia但NodeMedia SDK按包名授权未授权包名应用使用有版权提示信息。 我这里使用的是别人分享在github上的一个免费SDK下载地址。 下面我就代码分析一下直播推流的过程吧 先看入口界面 很简单一个输入框让你填写服务器的推流地址另外一个按钮开启推流。 public class StartActivity extends Activity {public static final String RTMPURL_MESSAGE rtmppush.hx.com.rtmppush.rtmpurl;private Button _startRtmpPushButton null;private EditText _rtmpUrlEditText null;private View.OnClickListener _startRtmpPushOnClickedEvent new View.OnClickListener() {Overridepublic void onClick(View arg0) {Intent i new Intent(StartActivity.this, MainActivity.class);String rtmpUrl _rtmpUrlEditText.getText().toString();i.putExtra(StartActivity.RTMPURL_MESSAGE, rtmpUrl);StartActivity.this.startActivity(i);}};private void InitUI(){_rtmpUrlEditText (EditText)findViewById(R.id.rtmpUrleditText);_startRtmpPushButton (Button)findViewById(R.id.startRtmpButton);_rtmpUrlEditText.setText(rtmp://192.168.1.104:1935/live/12345);_startRtmpPushButton.setOnClickListener(_startRtmpPushOnClickedEvent);}Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_start);InitUI();} } 主要的推流过程在MainActivity里面同样先看界面 布局文件 RelativeLayout xmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:toolshttp://schemas.android.com/toolsandroid:idid/cameraRelativeandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid:paddingBottomdimen/activity_vertical_marginandroid:paddingLeftdimen/activity_horizontal_marginandroid:paddingRightdimen/activity_horizontal_marginandroid:paddingTopdimen/activity_vertical_marginandroid:themeandroid:style/Theme.NoTitleBar.FullscreenSurfaceViewandroid:idid/surfaceViewExandroid:layout_widthmatch_parentandroid:layout_heightmatch_parent/Buttonandroid:idid/SwitchCamerabuttonandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_alignBottomid/surfaceViewExandroid:textstring/SwitchCamera / /RelativeLayout 其实就是用一个SurfaceView显示摄像头拍摄画面并提供了一个按钮切换前置和后置摄像头。从入口函数看起 Overrideprotected void onCreate(Bundle savedInstanceState) {requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);Intent intent getIntent();_rtmpUrl intent.getStringExtra(StartActivity.RTMPURL_MESSAGE);InitAll();PowerManager pm (PowerManager) getSystemService(Context.POWER_SERVICE);_wakeLock pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, My Tag);} 首先设置全屏显示常亮竖屏获取服务器的推流url再初始化所有东西。 private void InitAll() {WindowManager wm this.getWindowManager();int width wm.getDefaultDisplay().getWidth();int height wm.getDefaultDisplay().getHeight();int iNewWidth (int) (height * 3.0 / 4.0);RelativeLayout rCameraLayout (RelativeLayout) findViewById(R.id.cameraRelative);RelativeLayout.LayoutParams layoutParams new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT);int iPos width - iNewWidth;layoutParams.setMargins(iPos, 0, 0, 0);_mSurfaceView (SurfaceView) this.findViewById(R.id.surfaceViewEx);_mSurfaceView.getHolder().setFixedSize(HEIGHT_DEF, WIDTH_DEF);_mSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);_mSurfaceView.getHolder().setKeepScreenOn(true);_mSurfaceView.getHolder().addCallback(new SurceCallBack());_mSurfaceView.setLayoutParams(layoutParams);InitAudioRecord();_SwitchCameraBtn (Button) findViewById(R.id.SwitchCamerabutton);_SwitchCameraBtn.setOnClickListener(_switchCameraOnClickedEvent);RtmpStartMessage();//开始推流} 首先设置屏幕比例3:4显示给SurfaceView设置一些参数并添加回调再初始化AudioRecord最后执行开始推流。音频在这里初始化了那么相机在哪里初始化呢其实在SurfaceView的回调函数里。 Overridepublic void surfaceCreated(SurfaceHolder holder) {_iDegrees getDisplayOritation(getDispalyRotation(), 0);if (_mCamera ! null) {InitCamera(); //初始化相机return;}//华为i7前后共用摄像头if (Camera.getNumberOfCameras() 1) {_bIsFront false;_mCamera Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);} else {_mCamera Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);}InitCamera();}Overridepublic void surfaceDestroyed(SurfaceHolder holder) {}} 相机的初始化就在这里啦 public void InitCamera() {Camera.Parameters p _mCamera.getParameters();Size prevewSize p.getPreviewSize();showlog(Original Width: prevewSize.width , height: prevewSize.height);ListSize PreviewSizeList p.getSupportedPreviewSizes();ListInteger PreviewFormats p.getSupportedPreviewFormats();showlog(Listing all supported preview sizes);for (Camera.Size size : PreviewSizeList) {showlog( w: size.width , h: size.height);}showlog(Listing all supported preview formats);Integer iNV21Flag 0;Integer iYV12Flag 0;for (Integer yuvFormat : PreviewFormats) {showlog(preview formats: yuvFormat);if (yuvFormat android.graphics.ImageFormat.YV12) {iYV12Flag android.graphics.ImageFormat.YV12;}if (yuvFormat android.graphics.ImageFormat.NV21) {iNV21Flag android.graphics.ImageFormat.NV21;}}if (iNV21Flag ! 0) {_iCameraCodecType iNV21Flag;} else if (iYV12Flag ! 0) {_iCameraCodecType iYV12Flag;}p.setPreviewSize(HEIGHT_DEF, WIDTH_DEF);p.setPreviewFormat(_iCameraCodecType);p.setPreviewFrameRate(FRAMERATE_DEF);showlog(_iDegrees_iDegrees);_mCamera.setDisplayOrientation(_iDegrees);p.setRotation(_iDegrees);_mCamera.setPreviewCallback(_previewCallback);_mCamera.setParameters(p);try {_mCamera.setPreviewDisplay(_mSurfaceView.getHolder());} catch (Exception e) {return;}_mCamera.cancelAutoFocus();//只有加上了这一句才会自动对焦。_mCamera.startPreview();} 还记得之前初始化完成之后开始推流函数吗 private void RtmpStartMessage() {Message msg new Message();msg.what ID_RTMP_PUSH_START;Bundle b new Bundle();b.putInt(ret, 0);msg.setData(b);mHandler.sendMessage(msg);} Handler处理 public Handler mHandler new Handler() {public void handleMessage(android.os.Message msg) {Bundle b msg.getData();int ret;switch (msg.what) {case ID_RTMP_PUSH_START: {Start();break;}}}}; 真正的推流实现原来在这里 private void Start() {if (DEBUG_ENABLE) {File saveDir Environment.getExternalStorageDirectory();String strFilename saveDir /aaa.h264;try {if (!new File(strFilename).exists()) {new File(strFilename).createNewFile();}_outputStream new DataOutputStream(new FileOutputStream(strFilename));} catch (Exception e) {e.printStackTrace();}}//_rtmpSessionMgr.Start(rtmp://192.168.0.110/live/12345678);_rtmpSessionMgr new RtmpSessionManager();_rtmpSessionMgr.Start(_rtmpUrl); //------point 1int iFormat _iCameraCodecType;_swEncH264 new SWVideoEncoder(WIDTH_DEF, HEIGHT_DEF, FRAMERATE_DEF, BITRATE_DEF);_swEncH264.start(iFormat); //------point 2_bStartFlag true;_h264EncoderThread new Thread(_h264Runnable);_h264EncoderThread.setPriority(Thread.MAX_PRIORITY);_h264EncoderThread.start(); //------point 3_AudioRecorder.startRecording();_AacEncoderThread new Thread(_aacEncoderRunnable);_AacEncoderThread.setPriority(Thread.MAX_PRIORITY);_AacEncoderThread.start(); //------point 4} 里面主要的函数有四个我分别标出来了现在我们逐一看一下。首先是point 1这已经走到SDK里面了 public int Start(String rtmpUrl){int iRet 0;_rtmpUrl rtmpUrl;_rtmpSession new RtmpSession();_bStartFlag true;_h264EncoderThread.setPriority(Thread.MAX_PRIORITY);_h264EncoderThread.start();return iRet;} 其实就是启动了一个线程这个线程稍微有点复杂 private Thread _h264EncoderThread new Thread(new Runnable() {private Boolean WaitforReConnect(){for(int i0; i 500; i){try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}if(_h264EncoderThread.interrupted() || (!_bStartFlag)){return false;}}return true;}Overridepublic void run() {while (!_h264EncoderThread.interrupted() (_bStartFlag)) {if(_rtmpHandle 0) {_rtmpHandle _rtmpSession.RtmpConnect(_rtmpUrl);if(_rtmpHandle 0){if(!WaitforReConnect()){break;}continue;}}else{if(_rtmpSession.RtmpIsConnect(_rtmpHandle) 0){_rtmpHandle _rtmpSession.RtmpConnect(_rtmpUrl);if(_rtmpHandle 0){if(!WaitforReConnect()){break;}continue;}}}if((_videoDataQueue.size() 0) (_audioDataQueue.size()0)){try {Thread.sleep(30);} catch (InterruptedException e) {e.printStackTrace();}continue;}//Log.i(TAG, VideoQueue length_videoDataQueue.size(), AudioQueue length_audioDataQueue.size());for(int i 0; i 100; i){byte[] audioData GetAndReleaseAudioQueue();if(audioData null){break;}//Log.i(TAG, ###RtmpSendAudioData:audioData.length);_rtmpSession.RtmpSendAudioData(_rtmpHandle, audioData, audioData.length);}byte[] videoData GetAndReleaseVideoQueue();if(videoData ! null){//Log.i(TAG, $$$RtmpSendVideoData:videoData.length);_rtmpSession.RtmpSendVideoData(_rtmpHandle, videoData, videoData.length);}try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}_videoDataQueueLock.lock();_videoDataQueue.clear();_videoDataQueueLock.unlock();_audioDataQueueLock.lock();_audioDataQueue.clear();_audioDataQueueLock.unlock();if((_rtmpHandle ! 0) (_rtmpSession ! null)){_rtmpSession.RtmpDisconnect(_rtmpHandle);}_rtmpHandle 0;_rtmpSession null;}}); 看18行主要就是一个while循环每隔一段时间去_audioDataQueue和_videoDataQueue两个缓冲数组中取数据发送给服务器发送方法_rtmpSession.RtmpSendAudioData和_rtmpSession.RtmpSendVideoData都是Native方法通过jni调用so库文件的内容每隔一段时间这个时间是多少呢看第4行原来是5秒钟也就是说我们的视频数据会在缓冲中存放5秒才被取出来发给服务器所有直播会有5秒的延时我们可以修改这块来控制直播延时。 上面说了我们会从_audioDataQueue和_videoDataQueue两个Buffer里面取数据那么数据是何时放进去的呢看上面的point 2,3,4。首先是point 2同样走进了SDK public boolean start(int iFormateType){int iType OpenH264Encoder.YUV420_TYPE;if(iFormateType android.graphics.ImageFormat.YV12){iType OpenH264Encoder.YUV12_TYPE;}else{iType OpenH264Encoder.YUV420_TYPE;}_OpenH264Encoder new OpenH264Encoder();_iHandle _OpenH264Encoder.InitEncode(_iWidth, _iHeight, _iBitRate, _iFrameRate, iType);if(_iHandle 0){return false;}_iFormatType iFormateType;return true;} 其实这是初始化编码器具体的初始化过程也在so文件jni调用。point 3,4其实就是开启两个线程那我们看看线程中具体实现吧。 private Thread _h264EncoderThread null;private Runnable _h264Runnable new Runnable() {Overridepublic void run() {while (!_h264EncoderThread.interrupted() _bStartFlag) {int iSize _YUVQueue.size();if (iSize 0) {_yuvQueueLock.lock();byte[] yuvData _YUVQueue.poll();if (iSize 9) {Log.i(LOG_TAG, ###YUV Queue len _YUVQueue.size() , YUV length yuvData.length);}_yuvQueueLock.unlock();if (yuvData null) {continue;}if (_bIsFront) {_yuvEdit _swEncH264.YUV420pRotate270(yuvData, HEIGHT_DEF, WIDTH_DEF);} else {_yuvEdit _swEncH264.YUV420pRotate90(yuvData, HEIGHT_DEF, WIDTH_DEF);}byte[] h264Data _swEncH264.EncoderH264(_yuvEdit);if (h264Data ! null) {_rtmpSessionMgr.InsertVideoData(h264Data);if (DEBUG_ENABLE) {try {_outputStream.write(h264Data);int iH264Len h264Data.length;//Log.i(LOG_TAG, Encode H264 leniH264Len);} catch (IOException e1) {e1.printStackTrace();}}}}try {Thread.sleep(1);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}_YUVQueue.clear();}}; 也是一个循环线程第9行从_YUVQueue中取出摄像头获取的数据然后进行视频旋转第24行对数据进行编码然后执行26行InsertVideoData public void InsertVideoData(byte[] videoData){if(!_bStartFlag){return;}_videoDataQueueLock.lock();if(_videoDataQueue.size() 50){_videoDataQueue.clear();}_videoDataQueue.offer(videoData);_videoDataQueueLock.unlock();} 果然就是插入之前提到的_videoDataQueue的Buffer。这里插入的是视频数据那么音频数据呢在另外一个线程内容大致相同 private Runnable _aacEncoderRunnable new Runnable() {Overridepublic void run() {DataOutputStream outputStream null;if (DEBUG_ENABLE) {File saveDir Environment.getExternalStorageDirectory();String strFilename saveDir /aaa.aac;try {if (!new File(strFilename).exists()) {new File(strFilename).createNewFile();}outputStream new DataOutputStream(new FileOutputStream(strFilename));} catch (Exception e1) {e1.printStackTrace();}}long lSleepTime SAMPLE_RATE_DEF * 16 * 2 / _RecorderBuffer.length;while (!_AacEncoderThread.interrupted() _bStartFlag) {int iPCMLen _AudioRecorder.read(_RecorderBuffer, 0, _RecorderBuffer.length); // Fill bufferif ((iPCMLen ! _AudioRecorder.ERROR_BAD_VALUE) (iPCMLen ! 0)) {if (_fdkaacHandle ! 0) {byte[] aacBuffer _fdkaacEnc.FdkAacEncode(_fdkaacHandle, _RecorderBuffer);if (aacBuffer ! null) {long lLen aacBuffer.length;_rtmpSessionMgr.InsertAudioData(aacBuffer);//Log.i(LOG_TAG, fdk aac lengthlLen from pcmiPCMLen);if (DEBUG_ENABLE) {try {outputStream.write(aacBuffer);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}} else {Log.i(LOG_TAG, ######fail to get PCM data);}try {Thread.sleep(lSleepTime / 10);} catch (InterruptedException e) {e.printStackTrace();}}Log.i(LOG_TAG, AAC Encoder Thread ended ......);}};private Thread _AacEncoderThread null; 这就是通过循环将音频数据插入_audioDataQueue这个Buffer。 以上就是视频采集和推流的代码分析Demo中并没有对视频进行任何处理只是摄像头采集编码后推流到服务器端。 第二部分Nginx服务器搭建 流媒体服务器有诸多选择如商业版的Wowza。但我选择的是免费的Nginxnginx-rtmp-module。Nginx本身是一个非常出色的HTTP服务器它通过nginx的模块nginx-rtmp-module可以搭建一个功能相对比较完善的流媒体服务器。这个流媒体服务器可以支持RTMP和HLS。 Nginx配合SDK做流媒体服务器的原理是: Nginx通过rtmp模块提供rtmp服务, SDK推送一个rtmp流到Nginx, 然后客户端通过访问Nginx来收看实时视频流。 HLS也是差不多的原理,只是最终客户端是通过HTTP协议来访问的,但是SDK推送流仍然是rtmp的。 下面是一款已经集成rtmp模块的windows版本的Nginx。下载后即可直接使用 下载链接https://github.com/illuspas/nginx-rtmp-win32 1、rtmp端口配置 配置文件在/conf/nginx.conf RTMP监听 1935 端口启用live 和hls 两个application 所以你的流媒体服务器url可以写成rtmp://服务器IP地址:1935/live/xxx 或 rtmp://服务器IP地址:1935/hls/xxx 例如我们上面写的 rtmp://192.168.1.104:1935/live/12345 HTTP监听 8080 端口 :8080/stat 查看stream状态 :8080/index.html 为一个直播播放与直播发布测试器:8080/vod.html为一个支持RTMP和HLS点播的测试器 2、启动nginx服务 双击nginx.exe文件或者在dos窗口下运行nginx.exe即可启动nginx服务 1启动任务管理器可以看到nginx.exe进程 2打开网页输入http://localhot:8080,出现如下画面 显示以上界面说明启动成功。 第三部分直播流的播放 主播界面 上面说过了只要支持RTMP流传输协议的播放器都可以收看到我们的直播。下面举两个例子吧 1window端播放器VLC 2Android端播放器ijkplayer ijkplayer的使用请参考Android ijkplayer的使用解析 private void initPlayer() {player new PlayerManager(this);player.setFullScreenOnly(true);player.setScaleType(PlayerManager.SCALETYPE_FILLPARENT);player.playInFullScreen(true);player.setPlayerStateListener(this);player.play(rtmp://192.168.1.104:1935/live/12345);} 附Demo下载地址 另附网上一个开源的SDK 项目地址 GitHub: https://github.com/AnyRTC/AnyRTC-RTMP OSChina: https://git.oschina.net/dynctm/AnyRTC-RTMP 项目特点 1商业级开源代码高效稳定 2超小内存占有率移动直播针对性极致优化代码冗余率极低 3打破平台壁垒真正的跨平台一套核心代码支持Android、iOS、Windows等 4超过200Android手机、iOS全平台适配硬件编解码可保证99%的可用性 5接口极简推流2个 拉流2个 6底层库C核心库代码风格采用Google code style 7极简内核无需再去深扒复杂的FFMpeg代码 8实用主义那些什么坑什么优化等概念请搜索相关文章 9OpenH264软件编码FFMpeg软件解码FAAC/FAAD软件编解码适配不同系统的硬件编解码统统包含 10支持SRS、Nginx-RTMP等标准RTMP服务同时支持各大CDN厂商的接入 rtmp直播地址 可以直接用电视台的rtmp直播地址: 一般做rtmp编程的时候需要用到rtmp视频源地址通常可以自己搭建Red5等服务器到自己的机器配置好后编写客户端但是这样有点麻烦 为了方便可以直接用电视台的rtmp直播地址 rtmp://live.hkstv.hk.lxdns.com/live/hks 测试可用 rtmp://www.planeta-online.tv:1936/live/channel_4 香港卫视 rtmp://live.hkstv.hk.lxdns.com/live/hks 香港卫视 http://live.hkstv.hk.lxdns.com/live/hks/playlist.m3u8 香港卫视 http://124.160.184.137:80/live/5 … a46720.m3u8?typetv 香港卫视精品台 http://221.120.177.59/hls/i3d7ragr.m3u8 香港卫视精品台 rtmp://221.120.177.59/livestream/ucagm8kk 更多地址详见:http://blog.csdn.net/newnewfeng/article/details/50456181
http://www.lakalapos1.cn/news/19125/

相关文章:

  • 网站和二级目录权重郑州360房产网查询
  • 网站开发环境的配置网站开发与设计实训报告
  • 分享几款做淘客网站的服务器好男人好资源在线观看免费官网
  • 成品网站管系统零基础是学不了ui的
  • 网站开发代码无中文企业网站seo手机
  • 滕州做网站网站对图片优化吗
  • 天津营销网站建设公司排名公司网站 百度
  • it在线学习网站开发兰州七里河
  • 公司网站建设情况报告数据中台系统
  • 天津seo网站管理江苏省交通运输厅门户网站建设管理办法
  • 网站建设经验大总结专建网站
  • 网站推荐入口域名怎么卖出去
  • 正安县网站seo优化排名移动网站不备案吗
  • 企业网站建设案例哪个品牌好ui设计接单价目表
  • 做民宿怎么登录网站初中毕业如何提升学历
  • 做网站卖印度药做网站搞笑口号
  • 如何开发网站平台开发专门做网页的软件
  • 宝应建设局网站江苏省住房和城乡建设局
  • 网站后台seo设置子域名的网站放到哪里去
  • 如何进行网站建设和推广app哪个网站开发好
  • 手机网站建设策划书南昌市,做网站的公司
  • 国际营销网站建设企业网络搭建技能大赛
  • 电子商务网站建设规划范文深圳网站关键词推广
  • 沧州市任丘建设局网站网站pc转移动端代码
  • 佛山网站到首页排名设计制作生态瓶教案
  • 潍坊做网站建设的公司2023北京封控了
  • 网站备案无前置审批文件信息技术网站建设教案
  • 公众平台的微信网站开发黑龙江省建设厅官网
  • 在线做漫画的网站好建设外贸型网站流程
  • 做营销型网站一般要多少钱网站title