文档首页 > > 推流SDK> Android 推流SDK> 摄像头推流

摄像头推流

分享
更新时间: 2019/08/21 14:29

本节内容主要介绍如何使用Android推流SDK进行摄像头推流。

Step1:初始化

主要对采集特效和推流相关类进行初始化。

采集媒体流的相关操作在NvsStreamingContext类中。NvsStreamingContext是流媒体上下文类,在使用采集特效等相关操作的时候,需要先初始化NvsStreamingContext类,在其它Activity里使用时获取NvsStreamingContext的对象。

NvsStreamingContext为单例类,不再使用采集特效或程序退出前销毁NvsStreamingContext类的对象,请务必保证不要中途销毁NvsStreamingContext类的对象。

编码推流的相关操作在HwPublisher中,HwPublisher为编码推流录制相关入口,需要实现RtmpHandler.RtmpListener、 HwEncodeHandler.HwEncodeListener和HwRecordHandler.HwRecordListener三个监听。

  • 初始化NvsStreamingContext类
    String licensePath = "livepush.lic";
    NvsStreamingContext.init(MainActivity.this, licensePath, NvsStreamingContext.STREAMING_CONTEXT_FLAG_SUPPORT_4K_EDIT);

    其中licensePath为美颜工具的授权文件的路径,License申请请参见License申请。若无License文件,可直接设置为空字符串,使用美颜功能时将带有华为水印。NvsStreamingContext.STREAMING_CONTEXT_FLAG_SUPPORT_4K_EDIT,可忽略。

  • 初始化AR Effect,全局只需初始化一次 。
    if (m_canUseARFace) {
    com.meicam.sdk.NvsFaceEffectV1.setup("assets:/NvFaceData.asset", authpack.A());
    com.meicam.sdk.NvsFaceEffectV1.setMaxFaces(2);
    }

    其中assets:/NvFaceData.asset为人脸检测资源,authpack为人脸检测相关授权证书,即您在License申请时获取的AR License文件。

  • 初始化编码、推流和录制等。
    //初始化推流
    mPublisher = new HwPublisher(CaptureActivity.this);
    mPublisher.setEncodeHandler(new HwEncodeHandler(CaptureActivity.this));
    mPublisher.setRtmpHandler(new RtmpHandler(CaptureActivity.this));
    mPublisher.setRecordHandler(new HwRecordHandler(CaptureActivity.this));
    //设置预览分辨率
    mPublisher.setPreviewResolution(1280, 720);
    //设置编码分辨率
    mPublisher.setOutputResolution(720, 1280);
    //设置编码模式
    mPublisher.setVideoHDMode();

Step2:采集预览

  • 开始预览
    //将采集预览输出连接到mSurface,mSurface为当前渲染的SurfaceTexture
    mStreamingContext.connectCapturePreviewWithSurfaceTexture(mSurface);
    //设置采集设备回调,并实现NvsStreamingContext.CaptureDeviceCallback
    mStreamingContext.setCaptureDeviceCallback(this);
    //开始预览,startCapturePreview中的参数标识具体含义见接口文档。
    if (getCurrentEngineState() != NvsStreamingContext.STREAMING_ENGINE_STATE_CAPTUREPREVIEW) {
        if (!mStreamingContext.startCapturePreview(id, NvsStreamingContext.VIDEO_CAPTURE_RESOLUTION_GRADE_HIGH,
             NvsStreamingContext.STREAMING_ENGINE_CAPTURE_FLAG_DONT_USE_SYSTEM_RECORDER
             |NvsStreamingContext.STREAMING_ENGINE_CAPTURE_FLAG_CAPTURE_BUDDY_HOST_VIDEO_FRAME
             |NvsStreamingContext.STREAMING_ENGINE_CAPTURE_FLAG_STRICT_PREVIEW_VIDEO_SIZE
             |NvsStreamingContext.STREAMING_ENGINE_CAPTURE_FLAG_DONT_CAPTURE_AUDIO, null))
                 Log.e(TAG, "Failed to start capture preview!");
    }
  • 切换摄像头
     private boolean startCapturePreview(boolean deviceChanged) {
            // 判断当前引擎状态是否为采集预览状态
            int captureResolutionGrade = ParameterSettingValues.instance().getCaptureResolutionGrade();
            if ( deviceChanged || getCurrentEngineState() != NvsStreamingContext.STREAMING_ENGINE_STATE_CAPTUREPREVIEW) {
                m_supportAutoFocus = false;
                if (!mStreamingContext.startCapturePreview(mCurrentDeviceIndex,
                        captureResolutionGrade,
                        NvsStreamingContext.STREAMING_ENGINE_CAPTURE_FLAG_DONT_USE_SYSTEM_RECORDER |
                                NvsStreamingContext.STREAMING_ENGINE_CAPTURE_FLAG_CAPTURE_BUDDY_HOST_VIDEO_FRAME
                                | NvsStreamingContext.STREAMING_ENGINE_CAPTURE_FLAG_STRICT_PREVIEW_VIDEO_SIZE, null)) {
                    Log.e(TAG, "Failed to start capture preview!");
                    return false;
                }
            }
            return true;
        }
  • 设置变焦
    //zoomVaule取值范围,通过mStreamingContext.getCaptureDeviceCapability(deviceIndex)获取
    mStreamingContext.setZoom(zoomVaule);
  • 设置曝光补偿
    //exposeVaule取值范围,通过mStreamingContext.getCaptureDeviceCapability(deviceIndex)获取
    mStreamingContext.setExposureCompensation(exposeVaule);
  • 闪光灯
    if (mStreamingContext.isFlashOn()) {
       mStreamingContext.toggleFlash(false);
       mFlashButton.setImageResource(R.mipmap.icon_flash_off);
       mFlashButton.setImageAlpha(255);
    } else {
       mStreamingContext.toggleFlash(true);
       mFlashButton.setImageResource(R.mipmap.icon_flash_on);
       mFlashButton.setImageAlpha(255);
    }

Step3:美颜特效

  • 美颜
    添加美颜特效后,在预览窗口可以看到美颜效果。美颜特效参数Strength与Whitening分别对应磨皮与美白,Samples的beauty示例的所给值即推荐值。
     NvsFxDescription fxDescription = m_streamingContext.getVideoFxDescription("Beauty");
    //获取美颜特技描述信息         
    List<NvsFxDescription.ParamInfoObject> paramInfo =  fxDescription.getAllParamsInfo();
    //获取描述的所有参数信息         
    for (NvsFxDescription.ParamInfoObject param:paramInfo) {             
    String paramName = param.getString("paramName");             
    if (paramName.equals("Strength")) { 
         //获取美颜磨皮最大值                  
         double maxValue = param.getFloat("floatMaxVal");  
        //获取美颜磨皮当前值              
        m_strengthValue = param.getFloat("floatDefVal");            
                                      }       
                                                           }  
    //添加美颜采集特效         
    NvsCaptureVideoFx fx = m_streamingContext.appendBeautyCaptureVideoFx();  
    //设置美颜磨皮值        
    fx.setFloatVal("Strength", m_strengthValue);  
    //设置美白强度值
    fx.setFloatVal("Whitening", m_whiteningValue);
  • 采集特效

    采集特效分为内建采集特效和扩展采集特效。扩展采集特效即通过资源包安装而得到的采集特效。

    • 添加内建采集特效。
      //获取所有内建采集特效的名称         
      m_streamingContext.getAllBuiltinCaptureVideoFxNames();          
      //添加内建采集特效。特效名称可参见下表。  
      m_streamingContext.appendBuiltinCaptureVideoFx(fxName);         
      //移除所有采集视频特效         
      //m_streamingContext.removeAllCaptureVideoFx();
    • 添加扩展采集特效。
      //首先需要安装扩展采集特效所对应的资源包,获取资源包对应的包ID值,然后才可添加扩展采集特效。资源包包括主题包,字幕样式包,动画贴纸包,转场包,滤镜包等。
      //安装一个视频采集特效包,此处采用同步安装方式,如果资源包尺寸太大或者根据需要可使用异步安装方式         
      String package1Path = "assets:/7FFCF99A-5336-4464-BACD-9D32D5D2DC5E.videofx";         
      m_fxPackageId = new StringBuilder();         
      int error = m_streamingContext.getAssetPackageManager().installAssetPackage(package1Path, null, NvsAssetPackageManager.ASSET_PACKAGE_TYPE_VIDEOFX, true, m_fxPackageId);         if (error != NvsAssetPackageManager.ASSET_PACKAGE_MANAGER_ERROR_NO_ERROR                 
          && error != NvsAssetPackageManager.ASSET_PACKAGE_MANAGER_ERROR_ALREADY_INSTALLED) {            
          Log.e(TAG, "Failed to install asset package!");         
         }         
       //添加扩展采集特效         
      m_streamingContext.appendPackagedCaptureVideoFx(m_fxPackageId.toString());
    表1 内建采集特效及名称

    特效类型

    特效名称

    内建音频特效(Builtin Audio Fx)

    Audio Echo、Male Voice、Female Voice、Cartoon Voice、Fast Cartoon Voice、Monster Voice、Audio Reverb、Audio Wahwah

    内建视频特效(Builtin Video Fx)

    Sage、Maid、Mace、Lace、Mall、Sap、Sara、Pinky、Sweet、Fresh、Beauty、Color Property、Transform 2D、CC Basic、Lut

    内建视频采集特效(Builtin Capture VideoFx)

    Sage、Maid、Mace、Lace、Mall、Sap、Sara、Pinky、Sweet、Fresh、Beauty、Face Effect、Lut

    内建视频转场(Builtin Video Transition)

    Fade、Turning、Swap、Stretch In、Page Curl、Lens Flare、Star、Dip To Black、Dip To White、Push To Right、Push To Top、Upper Left Into

    各特效的参数说明请参见参数说明

Step4:设置软硬编码

主要包括编码相关接口,判断是否正在使用软编码,以及切换软编码和硬编码。

if (mPublisher.isSoftEncoder()) {
   Toast.makeText(CaptureActivity.this,"编码 状态:"+"硬编码",Toast.LENGTH_LONG).show();
   mPublisher.switchToHardEncoder();
} else {
   Toast.makeText(CaptureActivity.this,"编码 状态:"+"软编码",Toast.LENGTH_LONG).show();
   mPublisher.switchToSoftEncoder();
}

Step5:推流

主要包括开始推流和结束推流,其中开始推流需要填入推流地址。

if(!isConnected) {
   mSwitchEncoderLayout.setEnabled(false);
   mSwitchEncoderLayout.getChildAt(0).setAlpha((float) 0.4);
   mOpenRecordLayout.setEnabled(true);
   mOpenRecordLayout.getChildAt(0).setAlpha((float) 1);
   isConnecting =true;
   
   //设置推流地址
   mPublisher.startPublish(rtmpUrl);

   capture_btn.setText("结束推流");
   capture_btn.setTextColor(Color.RED);
}else{
   mSwitchEncoderLayout.setEnabled(true);
   mSwitchEncoderLayout.getChildAt(0).setAlpha((float) 1);

   isRecording = false;
   mOpenRecordLayout.getChildAt(0).setBackgroundColor(Color.TRANSPARENT);
   mOpenRecordLayout.getChildAt(0).setAlpha((float) 1);
   Toast.makeText(CaptureActivity.this,"编码 状态:"+"停止录制"+recPath,Toast.LENGTH_LONG).show();
   mPublisher.stopRecord();
   mOpenRecordLayout.setEnabled(false);
   mOpenRecordLayout.getChildAt(0).setAlpha((float) 0.4);

   isConnected=false;
   mPublisher.stopPublish();
   capture_btn.setText("开始推流");
   capture_btn.setTextColor(Color.WHITE);
 }

开始推流后,需要通过pushRgbaFrame将采集的RGBA数据输入到推流SDK。

mPublisher.pushRgbaFrame(RGBA_b, 720, 1280);

Step5:录制

主要包括开始录制和停止录制,其中开始录制时,要填入文件保存路径。

  • 开始录制
    if (!isRecording) {
       isRecording = true;
       mOpenRecordLayout.getChildAt(0).setBackgroundColor(Color.RED);
    
       Toast.makeText(CaptureActivity.this,"录制 状态:"+"开始录制",Toast.LENGTH_LONG).show();
       mPublisher.startRecord(recPath);
    } else {
       isRecording = false;
       mOpenRecordLayout.getChildAt(0).setBackgroundColor(Color.TRANSPARENT);
    
       Toast.makeText(CaptureActivity.this,"编码 状态:"+"停止录制"+recPath,Toast.LENGTH_LONG).show();
       mPublisher.stopRecord();
    }
  • 暂停录制
    mPublisher.pauseRecord();
  • 恢复录制
    mPublisher.resumeRecord();

获取推流信息

  • 获取推流信息

    主要对推流的信息进行获取,可以用于数据做分析等用途。其中包括,视频的分辨率、码率、帧率和编码器类型等信息。

    回调实时帧率码率

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
        @Override
        public void onRtmpVideoFpsChanged(double fps) {
            vfps = (int) fps;
        }
    
        @Override
        public void onRtmpVideoBitrateChanged(double bitrate) {
            vbitrate = (int) (bitrate/1000);
        }
    
        @Override
        public void onRtmpAudioBitrateChanged(double bitrate) {
            abitrate = (int) bitrate;
        }
    
  • 获取设置信息
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    String isSoftEnc;
    if(mPublisher.isSoftEncoder()){
        isSoftEnc="soft";
    }
    else{
        isSoftEnc="hard";
    }
    mLogText.setText("vFPS:  "+vfps+"\n"+"vGOP:  "+mPublisher.getVgop()+"\n"
                     + "vBitrate:  "+vbitrate+"\n"
                     +"vOutWidth:  "+mPublisher.getVOutWidth()+"\n"+"vOutHeigth:  "+mPublisher.getVOutHeight()+"\n"
                     +"vPreViewWidth:  "+mPublisher.getPreviewWidth()+"\n"+"vPreViewHeigth:  "+mPublisher.getPreviewHeight()+"\n"
                     +"vEncoder:  "+isSoftEnc+"\n"
                     +"aSamplerate:  "+mPublisher.getASamplerate()+"\n"
                     +"aBitrate:  "+abitrate/1000);
    
分享:

    相关文档

    相关产品

文档是否有解决您的问题?

提交成功!

非常感谢您的反馈,我们会继续努力做到更好!

反馈提交失败,请稍后再试!

*必选

请至少选择或填写一项反馈信息

字符长度不能超过200

提交反馈 取消

如您有其它疑问,您也可以通过华为云社区问答频道来与我们联系探讨

跳转到云社区