You need to enable JavaScript to run this app.
导航

进阶功能

最近更新时间2024.04.15 20:07:27

首次发布时间2022.01.17 10:33:21

本章节为您介绍推流 SDK 进阶功能的接入方式,支持的进阶功能包括但不限于 RTM协议推流、QUIC 协议推流、多 URL 推流、H.265硬件编码等。您可以根据实际业务需求,借助推流 SDK 实现更复杂的功能。

前提条件

注意事项

真机调试:由于 SDK 使用了大量 Android 系统的音视频接口,这些接口在仿真模拟器下可能会出现异常,推荐您使用真机进行代码调试。

功能接入

RTM 协议推流

视频直播推流 SDK 支持 RTM 协议推流,详细信息可参考超低延时直播介绍

  1. 使用视频直播控制台的地址生成器,生成 RTM 推流地址。

  2. 开始推流时,将 SDK 推流地址设置为 RTM 地址。代码示例如下所示:

    mLivePusher.startPush("http://example.push/stream.sdp");//添加 RTM 协议推流地址
    
  3. (可选)配置自动降级。代码示例如下所示:

    说明

    配置自动降级后,RTM 推流失败时,推流 SDK 将自动降级到 RTMP 推流。使用此功能需同时设置 RTM 和 RTMP 推流地址。

    List<String> urls = new ArrayList<>();
    urls.add("http://example.push/stream.sdp"); // 添加 RTM 协议推流地址
    urls.add("rtmp://example.push/stream"); // 添加 RTMP 协议推流降级地址
    mLivePusher.startPushWithUrls(urls.toArray(new String[0]));
    

RTMPS 协议推流

视频直播推流 SDK 支持 RTMPS 协议推流。

  1. 使用视频直播控制台的地址生成器,生成 RTMP 推流地址。

  2. 修改推流地址协议,将 RTMP 推流地址中的 rtmp 协议修改为 rtmps。例如:

    • 获取的 RTMP 地址为:rtmp://example.push/stream
    • 修改后的 RTMPS 地址为:rtmps://example.push/stream
    mLivePusher.startPush("rtmps://example.push/stream");//添加 RTMPS 协议推流地址
    
  3. (可选)配置自定降级。代码示例如下所示:

    说明

    配置自动降级后,RTMPS 推流失败时,推流 SDK 将自动降级到 RTMP 推流。使用此功能需同时设置 RTMPS 和 RTMP 推流地址。

    List<String> urls = new ArrayList<>();
    urls.add("rtmps://example.push/stream"); // 添加 RTMPS 协议推流地址
    urls.add("rtmp://example.push/stream"); // 添加 RTMP 协议推流降级地址
    mLivePusher.startPushWithUrls(urls.toArray(new String[0]));
    

QUIC 协议推流

视频直播推流 SDK 支持 QUIC 协议推流。

  1. 使用视频直播控制台的地址生成器,生成 RTMP 推流地址。

  2. 修改推流地址协议,将 RTMP 推流地址中的 rtmp 协议修改为 rtmpq。例如:

    • 获取的 RTMP 地址为:rtmp://example.push/stream
    • 修改后的 QUIC 地址为:rtmpq://example.push/stream
    mLivePusher.startPush("rtmpq://example.push/stream");//添加 QUIC 协议推流地址
    

    说明

    推流 SDK 默认开启 QUIC 协议推流的自动降级策略。无需额外配置, QUIC 协议推流失败后,SDK 将自动降级为 RTMP 协议推流。

多 URL 推流

使用多 URL 推流,可以在推流失败后自动切换到下一个推流地址继续推流,提高推流的稳定性和可靠性。

说明

多 URL 推流的地址数量无限制,推流引擎会按顺序遍历所有的推流地址,直至最后无可用地址后报错。

代码示例如下所示:

List<String> urls = new ArrayList<>();
urls.add("rtmp://example.push/stream_1");
urls.add("rtmp://example.push/stream_2");
mLivePusher.startPushWithUrls(urls.toArray(new String[0]));

H.265 硬件编码

使用 H.265 硬件编码,可在相同画质下有效降低带宽开销;也可在带宽开销相同时,提供更优异的画质体验。

说明

License 版本为高级版的 SDK 应用支持 H.265 硬件解码。

  1. 配置白名单。

    说明

    部分 Android 机型不支持 H.265 硬件编码,视频直播云端提供机型白名单,使用 H.265 硬件编码前请联系技术支持配置云端白名单。

  2. 配置硬件编码并创建推流引擎。代码示例如下所示:

    // 创建推流配置
    VeLivePusherConfiguration config = new VeLivePusherConfiguration();
    // 视频编码配置
    VeLivePusherDef.VeLiveVideoEncoderConfiguration encoderConfiguration = new VeLivePusherDef.VeLiveVideoEncoderConfiguration();
    // 配置编码类型为 H.265
    encoderConfiguration.setCodec(VeLivePusherDef.VeLiveVideoCodec.VeLiveVideoCodecByteVC1);
    // 创建推流引擎
    mLivePusher = config.build();
    

外部采集源推流

如您的 App 已经实现了音视频的采集和处理,希望将推流 SDK 作为推流引擎使用,可参考以下外部采集源推流功能的使用方式。

外部视频源

推流引擎支持传入 OpenGL 纹理ByteBufferByteArray 格式的视频数据。

说明

  • OpenGL 纹理支持 2D 和 OES 格式;
  • 二进制数据支持视频帧像素格式 I420;
  • 二进制数据必须传入视频帧的宽高属性;
  • OpenGL 纹理必须和用推流引擎使用相同的 OpenGL 环境,可以通过 VeLivePusher.getEGLContext() 获取。
  1. 推流引擎开启外部视频采集。代码示例如下所示:
    mLivePusher.startVideoCapture(VeLiveVideoCaptureExternal);
    
  2. 送入视频帧数据。代码示例如下所示:
VeLiveVideoFrame videoFrame = new VeLiveVideoFrame(720, 1280, TimeUtils.currentTimeUs(), 0, false, null);
videoFrame.setReleaseCallback(() -> {
		// 当videoFrame释放的时候调用,释放内存
});
mLivePusher.pushExternalVideoFrame(videoFrame);

外部音频源

推流引擎支持传入 ByteBuffer 类型的音频数据。

说明

二进制数据支持音频采样率为 8000/16000/32000/44100/48000 Hz,单/双声道音频数据。

  1. 推流引擎开启外部音频采集。代码示例如下所示:

    mLivePusher.startAudioCapture(VeLiveAudioCaptureExternal);
    
  2. 送入音频数据。代码示例如下所示:

    // 此处示例音频采样率为 44100 Hz,位深 16 bit,双通道
    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(44100 * 2 * 2);
    VeLiveAudioFrame audioFrame = new VeLiveAudioFrame(VeLiveAudioSampleRate44100, VeLiveAudioChannelStereo, TimeUtils.currentTimeUs(), byteBuffer);
    mLivePusher.pushExternalAudioFrame(audioFrame);
    

视频混流

除主要视频输入源 Main Input,推流引擎支持添加多个视频输入源,推流引擎内部会自动将所有输入源合并成同一视图后传送给传输模块。

  1. 添加视频源输入流。代码示例如下所示:

    VeLiveMixerManager mixerManager = mLivePusher.getMixerManager();
    mMixerVideoId = mixerManager.addVideoStream();
    
  2. 更新视频源输入信息。代码示例如下所示:

    • streamId(图层 ID):用于识别输入的数据流,即要混流的视频流的标识。通常在创建混流配置时使用。

    • 视频画面展示位置及大小:通过设置 x、y、width、height 来控制视频图层在画布中的位置和大小,例如 (0.0, 0.0, 1.0, 1.0) 表示平铺整个屏幕。

      • videoLayout.x = 0;这表示视频图层在水平方向(x轴)上的位置,取值范围为 [0.0, 1.0],其中 0.0 表示位于左边缘,1.0 表示位于右边缘。
      • videoLayout.y = 0;这表示视频图层在垂直方向(y轴)上的位置,取值范围也为 [0.0, 1.0],其中 0.0 表示位于顶部,1.0 表示位于底部。
      • videoLayout.width = 0.5;这表示视频图层的宽度,取值范围为 [0.0, 1.0],其中 1.0 表示等于整个画布宽度。
      • videoLayout.height = 0.3;这表示视频图层的高度,取值范围同样为 [0.0, 1.0],其中 1.0 表示等于整个画布高度。
    • zOrder(图层位置):图层的层级位置,值越大,图层越高,显示在其他图层之上。

    • renderMode(填充模式):枚举值,用于指定视频的填充模式,决定了如何在画布中展示视频。分为三种模式:

      • VeLivePusherRenderModeHidden 视窗填满优先:视频帧等比缩放,填满视窗,多余部分被裁剪。
      • VeLivePusherRenderModeFit 视频帧内容全部显示优先:将视频尺寸等比缩放,保证视频内容全部显示。未填满的区域会被背景颜色填充。
      • VeLivePusherRenderModeFill 视频帧自适应画布:视频帧非等比缩放,填满画布,可能会导致视频帧的长宽比例变化。
    VeLivePusherDef.VeLiveMixVideoLayout videoLayout = new VeLivePusherDef.VeLiveMixVideoLayout();
    videoLayout.streamId = mMixerVideoId;
    videoLayout.x = 0;
    videoLayout.y = 0;
    videoLayout.width = 0.5f;
    videoLayout.height = 0.3f;
    videoLayout.zOrder = 1;
    videoLayout.renderMode = VeLivePusherRenderModeHidden;
    description.mixVideoStreams.add(videoLayout);
    mLivePusher.getMixerManager().updateStreamMixDescription(description);
    
  3. 输入视频数据。代码示例如下所示:

    说明

    • VeLivePusher 提供了可指定 streamId 的采集输入函数,可将数据传到指定图层渲染上屏并推流。
    • videoFrame 更多可支持数据格式可参考外部采集源推流
    VeLiveVideoFrame videoFrame = new VeLiveVideoFrame(720, 1280, TimeUtils.currentTimeUs(), 0, false, null);
    videoFrame.setReleaseCallback(() -> {
        // 当videoFrame释放的时候调用,释放内存
    });
    mLivePusher.getMixerManager().sendCustomVideoFrame(videoFrame, mMixerVideoId);
    
  4. 移除视频源输入流。代码示例如下所示:

    mLivePusher.getMixerManager().removeVideoStream(mMixerVideoId);
    

音频混流

除主路音频流之外,推流引擎支持添加多个音频输入源,推流引擎内部会自动将所有音频流混流后传送给传输模块,同时支持在本地播放混流音频。

  1. 调用 addAudioStream添加音频源输入流。代码示例如下所示:
Object mStreamHandler = mLivePusher.getMixerManager().addAudioStream(VeLiveAudioMixPlayAndPush);
  1. (可选)调用 updateStreamMixDescription调节混流音量。代码示例如下所示:
VeLivePusherDef.VeLiveStreamMixDescription mMixDescription = new  VeLivePusherDef.VeLiveStreamMixDescription();
VeLivePusherDef.VeLiveMixAudioLayout layout = new VeLivePusherDef.VeLiveMixAudioLayout();
layout.streamId = (int)mStreamHandler;
layout.volume = volume;
mMixDescription.mixAudioStreams.add(layout);
mMixerManager.updateStreamMixDescription(mMixDescription);
  1. 输入音频帧,音频帧数据为 float32 格式小端字节序存储。详情见 VeLiveAudioFrame
ByteBuffer buffer = null;
long pts;
VeLiveAudioFrame frame = new VeLiveAudioFrame(VeLiveAudioSampleRate44100, VeLiveAudioChannelStereo, pts, buffer)
mMixerManager.sendCustomAudioFrame(frame, (int)mStreamHandler);
  1. 移除音频源输入流。代码示例如下所示:
mLivePusher.getMixerManager().removeAudioStream((int)mStreamHandler)

图片推流

推流 SDK 除支持手机摄像头采集推流外,还支持使用单张图片推流。代码示例如下所示:

Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
// 更新推流图片
mLivePusher.updateCustomImage(bitmap);
// 开启视频采集类型为自定义图片
mLivePusher.startVideoCapture(VeLiveVideoCaptureCustomImage);

背景音乐控制

在直播业务中,有些主播会在直播间 K 歌或播放背景音乐,下面为您介绍相关能力的接口。

  1. 获取媒体音乐播放器。代码示例如下所示:

    VeLiveMediaPlayer mediaPlayer = mLivePusher.createPlayer();
    
  2. 设置音乐文件路径,支持的文件格式包括 MP3、AAC、M4A、WAV。代码示例如下所示:

    // 设置文件路径
    mediaPlayer.prepare("xxx/music.mp3");
    
  3. 设置是否混音到直播流。代码示例如下所示:

    // 设置是否混音到直播流
    mediaPlayer.enableMixer(true);
    
  4. 设置是否循环播放。代码示例如下所示:

    // 设置是否循环播放。
    mediaPlayer.enableBGMLoop(true);
    
  5. 开始播放。代码示例如下所示:

    // 开始播放
    mediaPlayer.start();
    
  6. 调整背景音乐音量和主播音量。代码示例如下所示:

    // 设置背景音乐音量大小 0.0 - 1.0
    mediaPlayer.setBGMVolume(0.8f);
    // 设置主播声音音量大小 0.0 - 1.0
    mediaPlayer.setVoiceVolume(1.0f);
    
  7. 快进播放。代码示例如下所示:

    // 快进到某个时间点,可以通过 mediaPlayer.getDuration() 获取文件总时长
    mediaPlayer.seek(3000);
    
  8. 暂停播放、继续播放。代码示例如下所示:

    // 暂停
    mediaPlayer.pause();
    // 继续
    mediaPlayer.resume();
    
  9. 停止播放。代码示例如下所示:

    // 停止播放
    mediaPlayer.stop();
    

截图控制

直播过程中,支持主播将自己的精彩直播瞬间截图并保存在手机上,推流 SDK 提供了相应的截图能力。代码示例如下所示:

mLivePusher.snapshot(new VeLivePusherDef.VeLiveSnapshotListener() {
    @Override
    public void onSnapshotComplete(Bitmap image) {
        // 保存截图
    }
});

SEI

在直播过程中,有些信息需要跟随视频帧到达每一个观众,推流引擎提供了发送 SEI 的接口,可以编码自定义信息到关键帧或者每个视频帧里。代码示例如下所示:

// 发送 SEI 信息
mLivePusher.sendSeiMessage("key", "value", -1, true, true);

自定义视频处理

在使用推流引擎过程中,如果需要自行处理 SDK 采集的视频帧,可以使用下面的方法实现。

  1. 设置自定义视频帧处理回调监听。代码示例如下所示:

    mLivePusher.setVideoFrameFilter(new VeLivePusherDef.VeLiveVideoFrameFilter() {
        @Override
        public int onVideoProcess(VeLiveVideoFrame srcFrame, VeLiveVideoFrame dstFrame) {
            // 自行处理视频帧数据,设置给 dstFrame
            dstFrame.adopt(srcFrame.getWidth(), srcFrame.getHeight(), srcFrame.getPts(), 0, false, null);
            return 0;
        }
    });
    
  2. 移除自定义视频帧处理回调监听。代码示例如下所示:

    mLivePusher.setVideoFrameFilter(null);
    

自定义音频处理

在使用推流引擎过程中,如果需要自行处理 SDK 采集的音频数据,可以使用下面的方法实现。

  1. 设置自定义音频处理回调。代码示例如下所示:

    mLivePusher.setAudioFrameFilter(new VeLivePusherDef.VeLiveAudioFrameFilter() {
        @Override
        public int onAudioProcess(VeLiveAudioFrame srcFrame, VeLiveAudioFrame dstFrame) {
    		    // 自行处理音频数据,设置给 dstFrame
            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(srcFrame.getBuffer().capacity());
            dstFrame.adopt(srcFrame.getSampleRate(), srcFrame.getChannels(), srcFrame.getPts(), byteBuffer);
            return 0;
        }
    });
    
  2. 移除自定义音频处理回调。代码示例如下所示:

    mLivePusher.setAudioFrameFilter(null);
    

订阅视频数据

在推流的过程中,保存采集或编码前的视频数据可以通过以下 API 实现。

  1. 添加视频数据订阅回调。代码示例如下所示:

    mLivePusher.addVideoFrameListener(this);
    
  2. 实现监听接口VeLivePusherDef.VeLiveVideoFrameListener。代码示例如下所示:

    @NonNull
    @Override
    public VeLivePusherDef.VeLiveVideoFrameSource getObservedVideoFrameSource() {
    		// 获取当前 Listener 需要的视频帧来源, 同时获取采集和编码前数据
       return new VeLivePusherDef.VeLiveVideoFrameSource(VeLiveVideoFrameSourceCapture | VeLiveVideoFrameSourcePreEncode);
    }
    @Override
    public void onCaptureVideoFrame(VeLiveVideoFrame frame) {
    	  // 采集视频帧回调。
    }
    @Override
    public void onPreEncodeVideoFrame(VeLiveVideoFrame frame) {
    		// 编码前视频帧回调。
    }
    
  3. 移除视频数据订阅回调。代码示例如下所示:

    mLivePusher.removeVideoFrameListener(this);
    

订阅音频数据

在推流的过程中,保存采集或者是编码前的音频数据可以通过以下 API 实现。

  1. 添加音频数据订阅回调。代码示例如下所示:

    mLivePusher.addAudioFrameListener(this);
    
  2. 实现监听接口 VeLivePusherDef.VeLiveAudioFrameListener。代码示例如下所示:。

    @NonNull
    @Override
    public VeLivePusherDef.VeLiveAudioFrameSource getObservedAudioFrameSource() {
        // 获取当前 Listener 需要的音频帧来源,同时获取采集和编码前数据
        return new VeLivePusherDef.VeLiveAudioFrameSource(VeLiveAudioFrameSourceCapture | VeLiveAudioFrameSourcePreEncode);
    }
    @Override
    public void onCaptureAudioFrame(VeLiveAudioFrame frame) {
        // 采集音频帧回调。
    }
    @Override
    public void onPreEncodeAudioFrame(VeLiveAudioFrame frame) {
        // 编码前音频帧回调。
    }
    
  3. 移除音频数据订阅回调。代码示例如下所示:

    mLivePusher.removeAudioFrameListener(this);
    

直播录制

直播过程中,支持主播将自己的精彩直播录制并保存在手机上,推流 SDK 提供了相应的录制能力。

  1. 配置录制参数,开始录制。代码示例如下所示:

    // 设置录制参数
    VeLivePusherDef.VeLiveFileRecorderConfiguration recordConfig = new VeLivePusherDef.VeLiveFileRecorderConfiguration();
    // 录制视频的宽度
    recordConfig.setWidth(720);
    // 录制视频的高度
    recordConfig.setHeight(1280);
    // 录制视频的帧率
    recordConfig.setFps(15);
    // 录制视频的码率
    recordConfig.setBitrate(2000);
    
    mLivePusher.startFileRecording("xxx/record.mp4", recordConfig, new VeLivePusherDef.VeLiveFileRecordingListener() {
        @Override
        public void onFileRecordingStarted() {
            // 直播录制开始回调。
        }
        @Override
        public void onFileRecordingStopped() {
            // 直播录制停止回调。
        }
        @Override
        public void onFileRecordingError(int errorCode, String message) {
            // 错误码,详情请参见 VeLivePusherCode
            // 直播录制错误回调。
        }
    });
    
  2. 停止录制。代码示例如下所示:

    mLivePusher.stopFileRecording();
    

后台推流

直播过程中,支持主播在 App 进入到后台时持续推流,推流 SDK 提供了相应的后台推流能力。

说明

  1. 使用后台推流能力,需先打开 App 的后台音频采集权限;
  2. 后台推流提供尾帧、黑帧、图片三种模式推流。

根据不同的模式,切换后台视频采集类型。代码示例如下所示:

@Override
protected void onPause() {
    super.onPause();
    // 尾帧推流
    mLivePusher.switchVideoCapture(VeLiveVideoCaptureLastFrame);
    // 黑帧推流
    // mLivePusher.switchVideoCapture(VeLiveVideoCaptureDummyFrame);
    // 后台图片推流
    // Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    // mLivePusher.updateCustomImage(bitmap);
    // mLivePusher.switchVideoCapture(VeLiveVideoCaptureCustomImage);
}

@Override
protected void onResume() {
    super.onResume();
    // 这里业务上可以记录上次开启的视频采集类型,在进入前台后切换为上次的采集类型
    mLivePusher.switchVideoCapture(VeLiveVideoCaptureFrontCamera);
}

录屏推流

推流 SDK 除了支持手机摄像头采集推流外,还支持手机屏幕采集推流。屏幕采集推流适用于游戏直播、移动端 App 演示等场景。

  1. 申请录屏权限,获取屏幕采集 Intent。代码示例如下所示:

    //获取屏幕采集 Intent。
    private Intent mScreenIntent; 
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = null;
        if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.LOLLIPOP) {
            MediaProjectionManager mgr = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
            if (mgr != null) {
                intent = mgr.createScreenCaptureIntent();
                startActivityForResult(intent, REQUESTCODE_FROM_PROJECTION_SERVICE);
            }
        }
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode == REQUESTCODE_FROM_PROJECTION_SERVICE && resultCode == RESULT_OK){
    		    mScreenIntent = data;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }
    
  2. 开始屏幕采集。代码示例如下所示:

    // 开启屏幕采集
    mLivePusher.startScreenRecording(true, mScreenIntent);
    // 开启视频采集类型为屏幕采集
    mLivePusher.startVideoCapture(VeLiveVideoCaptureScreen);