本节为Link Visual音视频模块使用说明,包含视频播放、语音对讲的功能。

依赖SDK 概述
API 通道 提供API通道能力
长连接通道 P2P需要长连接通道

初始化

在初始化SDK前,需要正确的配置安全图片,请参见集成安全图片

混淆配置

# keep and don't warn linkvisual

-dontwarn com.aliyun.iotx.linkvisual.**

-keep class com.aliyun.iotx.linkvisual.media.** { *; }

依赖引入

// 1. 根build.gradle添加对aliyun maven仓库的引用
allprojects {
    repositories {
        maven {
            url "http://maven.aliyun.com/nexus/content/repositories/releases"
        }
    }
}

// 2. app build.gradle中添加依赖
implementation('com.aliyun.iotx:linkvisual-media:1.2.4')

使用方式

视频播放器按功能分为三种。

  • 直播播放器
    • 用于RTMP直播源,具有时延低的特点。
    • 支持P2P(需使用接入LinkVisual设备端SDK的摄像头)。
  • 点播播放器
    • 用于设备录像回放的播放,可调整播放进度。
    • 支持P2P(需使用接入LinkVisual设备端SDK的摄像头)。
  • HLS播放器
    • 用于基于HLS的云端录像回放的播放,支持MPEG-TS和FMP4容器,AES-128加密方式。

FFmpeg使用版本为n4.0.1音频编码,支持AAC_LC和G711a视频编码,支持H264/H265. Android SDK封装ExoPlayer作为HLS的播放器,版本为2.10.5。

功能 直播播放器 设备录像播放器 HLS播放器
视频播放
音频播放
暂停/恢复 x
跳至指定位置播放 x
总时长 x
当前播放进度 x
播放器状态变更通知
设置播放音量
变速播放 x x
循环播放 x x
画面缩放模式设置
播放器截图
边播边录 x

使用指南

  • 直播播放器
    // 构造播放器实例
    LivePlayer player = new LivePlayer();
    
    // 设置textureview
    player.setTextureView(textureView);
    // 设置必要的状态监听
    player.setOnPlayerStateChangedListener(new OnPlayerStateChangedListener() {
        @Override
        public void onPlayerStateChange(int playerState) {
            Log.d(TAG, "play state= " + playerState);
            switch (playerState) {
                case Player.STATE_BUFFERING:
                    break;
                case Player.STATE_IDLE:
                    break;
                case Player.STATE_READY:
                    break;
                case Player.STATE_ENDED:
                    break;
                default:
                    break;
            }
        }
    });
    // 设置错误监听
    player.setOnErrorListener(new OnErrorListener() {
        @Override
        public void onError(PlayerException exception) {
            makeToast("errorcode: " + exception.getCode() + "\n" + exception.getMessage());
        }
    });
    
    // 设置rtmp地址.
    player.setDataSource("rtmp://live.hkstv.hk.lxdns.com/live/hks2");
    // 设置数据源就绪监听器
    player.setOnPreparedListener(new OnPreparedListener() {
        @Override
        public void onPrepared() {
            // 数据源就绪后开始播放
            player.start();
        }
    });
    player.prepare();
    ...
    // 停止播放
    player.stop();
    ...
    // 释放播放器资源
    player.release();
    					
  • 点播播放器
    // 构造播放器实例
    VodPlayer player = new VodPlayer();
    
    // 设置textureview
    player.setTextureView(textureView);
    // 设置必要的状态监听
    player.setOnPlayerStateChangedListener(new OnPlayerStateChangedListener() {
        @Override
        public void onPlayerStateChange(int playerState) {
            Log.d(TAG, "play state= " + playerState);
            switch (playerState) {
                case Player.STATE_BUFFERING:
                    break;
                case Player.STATE_IDLE:
                    break;
                case Player.STATE_READY:
                    break;
                case Player.STATE_ENDED:
                    break;
                default:
                    break;
            }
        }
    });
    // 设置错误监听
    player.setOnErrorListener(new OnErrorListener() {
        @Override
        public void onError(PlayerException exception) {
            makeToast("errorcode: " + exception.getCode() + "\n" + exception.getMessage());
        }
    });
    
    // 设置支持点播的rtmp地址
    player.setDataSource("rtmp://xxxx");
    // 设置数据源就绪监听器
    player.setOnPreparedListener(new OnPreparedListener() {
        @Override
        public void onPrepared() {
            // 数据源就绪后开始播放
            player.start();
        }
    });
    player.prepare();
    ...
    // 暂停播放
    player.pause();
    ...
    // 恢复播放
    player.resume();
    ...
    // 停止播放
    player.stop();
    ...
    // 释放播放器资源
    player.release();
    					
  • HLS播放器
    ExoHlsPlayer player = new ExoHlsPlayer(getApplicationContext());
    
    // 使用Exo的SimpleExoPlayerView来作为播放器的UI组件, 也可以自己实现UI组件
    simpleExoPlayerView.setPlayer(player.getExoPlayer());
    simpleExoPlayerView.requestFocus();
    // 设置错误监听
    player.setOnErrorListener(new OnErrorListener() {
        @Override
        public void onError(PlayerException exception) {
            makeToast("errorcode: " + exception.getCode() + "\n" + exception.getMessage());
        }
    });
    // 设置状态监听
    player.setOnPlayerStateChangedListener(new OnPlayerStateChangedListener() {
        @Override
        public void onPlayerStateChange(int playerState) {
            switch (playerState) {
                case Player.STATE_BUFFERING:
                    break;
                case Player.STATE_IDLE:
                    break;
                case Player.STATE_READY:
                    break;
                case Player.STATE_ENDED:
                    break;
                default:
                    break;
            }
        }
    });
    
    // 设置m3u8地址
    player.setDataSource("http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear3/prog_index.m3u8");
    // 设置数据源就绪监听器
    player.setOnPreparedListener(new OnPreparedListener() {
        @Override
        public void onPrepared() {
            // 数据源就绪后开始播放
            player.start();
        }
    });
    player.prepare();
    ...
    // 暂停播放
    player.pause();
    ...
    // 恢复播放
    player.resume();
    ...
    // 停止播放
    player.stop();
    ...
    // 释放播放器资源
    player.release();
    					

播放器状态

通过设置播放器状态监听器,可接收到状态变更事件,用于相关UI元素的变更。

状态变更事件如:播放中发生错误、主动停止播放。

播放器状态
  • IDLE:播放器没有任何内容播放时的状态。
  • BUFFERING:播放器正在缓冲,当前的位置还不可以播放。状态变更事件如:开始播放时缓冲、seek后重新缓冲。
  • READY:播放器已经有内容在播放。状态变更事件如:首帧数据已经渲染、seek缓冲完成开始播放新内容。对于点播播放器,若已seek或播放到文件结尾,则会回调OnCompletionListener.onCompletion()方法。
  • ENDED:播放器已结束播放。

接口说明

  • LivePlayer
    • 构造方法
      /**
         * 构造方法
         */
        LivePlayer();
    • 设置非加密播放源
      /**
         * 设置播放源
         * @param url RTMP地址
         */
        void setDataSource(String url) throws IllegalArgumentException;
    • 设置加密播放源
      /**
         * 设置加密播放源(请确保源是做过AES加密)
         * @param url         rtmp源地址
         * @param isEncrypted 是否是加密源
         * @param decryptIv   解密向量,16 byte array
         * @param decryptKey  解密密钥,16 byte array
         * @throws IllegalArgumentException
         */
        void setDataSource(String url, boolean isEncrypted, byte[] decryptIv, byte[] decryptKey) throws IllegalArgumentException;
    • 设置IPC直播数据源
      /**
         * 设置IPC直播数据源.
         * @param iotId            IPC设备的iotId
         * @param streamType       流的类型:0-主码流,1-辅码流,若有多路码流请关注该参数,否则请填0
         * @param relayEncrypted   云转是否加密,强烈建议开启,对于出海产品,务必保持开启
         * @param relayEncryptType 云转加密类型:目前只支持0(AES-128)加密
         * @param forceIFrame      是否需要强制I帧,建议默认开启
         */
         void setIPCLiveDataSource(String iotId, int streamType, boolean relayEncrypted, int relayEncryptType, boolean forceIFrame);
    • 校验和准备数据
      /**
         * 校验和准备数据
         */
        void prepare();
    • 开始播放视频
      /**
         * 开始播放视频
         */
        void start();
    • 停止播放
      /**
         * 停止播放
         */
        void stop();
    • 重置播放器
      /**
         * 重置播放器
         */
        void reset();
    • 释放播放器资源
      /**
         * 释放播放器资源
         */
        void release();
    • 截图
      /**
         * 当前视频画面截图
         * @return 如果当前无画面则返回 null
         */
        Bitmap snapShot();
    • 开始录屏
      /**
         * 开始录制当前播放内容,生成MPEG-4格式转存到指定的文件中
         * 文件名后缀必须为.mp4
         * 须在{@link PlayerState#STATE_READY}时调用有效
         * @param contentFile
         * @return 操作成功与否
         */
        boolean startRecordingContent(File contentFile) throws IOException;
    • 结束录屏
      /**
         * 停止记录播放内容
         * @return 操作成功与否
         */
        boolean stopRecordingContent();
    • 设置播放器音量
      /**
         * 设置播放器音量
         * @param audioVolume 范围 0-1,0为静音
         */
        void setVolume(float audioVolume);
    • 设置音频流通道类型
      /**
         * 设置音频流通道类型,see {@link android.media.AudioManager}
         * 如果音频正在播放,则会因为重新创建AudioTrack导致有短暂停顿
         * @param streamType
         */
        void setAudioStreamType(int streamType);
    • 设置画面缩放模式
      /**
         * 设置视频画面缩放模式,默认为{@link android.media.MediaCodec#VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING}
         * @param videoScalingMode 参考:
         * {@link android.media.MediaCodec#VIDEO_SCALING_MODE_SCALE_TO_FIT}
         * {@link android.media.MediaCodec#VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING}
         */
        void setVideoScalingMode(int videoScalingMode);
    • 设置播放器固定缓存帧数
      /**
         * 设置播放器固定缓存帧数
         * @param frameCount 播放器固定缓存帧数,范围0-16帧,数值越大播放器延迟越大,流畅性越好
         */
        void setBufferedFrameCount(int frameCount);
    • 设置surfaceview
      /**
           * 设置SurfaceView, 必须为GLSurfaceView,同一个Window中同时只允许一个播放器播放,若需要支持多播放实例,请使用TextureView
           * 注意:GLSurfaceView必须在Activity的onResume和onPause回调方法中调用GLSurfaceView的onResume和onPause方法
           * @param surfaceview
           */
        void setSurfaceView(SurfaceView surfaceview);
    • 清除surfaceview
      /**
         * 清除surfaceview
         */
        void clearSurfaceView();
    • 设置textureview
      /**
           * 设置TextureView
           * @param textureview
           */
          void setTextureView(TextureView textureView);
    • 清除textureview
      /**
           * 清除textureview
           */
          void clearTextureView();
    • 设置数据源准备就绪事件监听器
      /**
         * 设置数据源准备就绪事件监听器
         * @param listener
         */
        void setOnPreparedListener(OnPreparedListener listener);
    • 设置播放器错误事件监听器
      /**
         * 设置播放器错误事件监听器,错误类型参考:
         * {@link PlayerException.SOURCE_ERROR}
         * {@link PlayerException.RENDER_ERROR}
         * {@link PlayerException.UNEXPECTED_ERROR}
         * @param listener
         */
        void setOnErrorListener(OnErrorListener listener);
    • 设置播放状态变更事件监听器
      /**
         * 设置播放状态变更事件监听器
         * @param listener
         */
        void setOnPlayerStateChangedListener(OnPlayerStateChangedListener listener);
    • 设置首帧被渲染事件监听器
      /**
         * 设置首帧被渲染事件监听器
         * @param listener
         */
        void setOnRenderedFirstFrameListener(OnRenderedFirstFrameListener listener);
    • 获取音量
      /**
         * 获取音量
         * @return 范围0-1,0为静音
         */
        float getVolume();
    • 获取播放器状态
      /**
         * 获取播放状态
         * @return 状态枚举,参考:
         * {@link PlayerState#STATE_IDLE} 播放器初始状态
         * {@link PlayerState#STATE_BUFFERING} 缓冲中状态
         * {@link PlayerState#STATE_READY} 缓冲结束开始播放状态
         * {@link PlayerState#STATE_ENDED} 播放完成状态
         */
        int getPlayState();
    • 获取播放器当前流的连接类型
      /**
         * 获取播放器当前流的连接类型
         * 播放器状态为{@link PlayerState#STATE_READY}时调用有效
         *
         * @return {@link StreamConnectType}
         */
        StreamConnectType getStreamConnectType();
    • 获取播放器当前的帧率/码率等信息
      /**
         * 获取播放器当前的帧率/码率等信息
         * 播放器状态为{@link PlayerState#STATE_READY}时调用有效
         * @return 包含帧率/码率等信息的json string
         */
        PlayInfo getCurrentPlayInfo();
  • VodPlayer
    • 构造方法
      /**
         * 构造方法
         */    
        VodPlayer();
    • 设置非加密播放源
      /**
         * 设置播放源
         * @param url RTMP地址
         */
        void setDataSource(String url) throws IllegalArgumentException;
    • 设置加密播放源
      /**
         * 设置加密播放源(请确保源是做过AES加密)
         * @param url         rtmp源地址
         * @param isEncrypted 是否是加密源
         * @param decryptIv   解密向量,16 byte array
         * @param decryptKey  解密密钥,16 byte array
         * @throws IllegalArgumentException
         */
        void setDataSource(String url, boolean isEncrypted, byte[] decryptIv, byte[] decryptKey) throws IllegalArgumentException;
    • 设置播放源为IPC录像(按录像文件名)
      /**
         * 设置播放源为IPC录像(按录像文件名)
         *
         * @param iotId         设备iotId
         * @param fileName      录像文件名
         * @param encrypted     是否流需要加密
         * @param encryptType   流加密类型
         */
         void setDataSourceByIPCRecordFileName(String iotId, String fileName, boolean encrypted, int encryptType);
    • 设置播放源为IPC录像(按录像时间段)
      /**
         * 设置播放地址为已接入生活物联网平台的IPC设备,指定录像时间段的本地录像文件地址,播放偏移量为0
         * see {@link #setDataSourceByIPCRecordTime(String, int, int, boolean, int, long)}
         */
        public void setDataSourceByIPCRecordTime(String iotId, String beginTime, String endTime, boolean encrypted, int encryptType);
      
        /**
         * 设置播放地址为已接入生活物联网平台的IPC设备,指定录像时间段的本地录像文件地址
         *
         * @param iotId              设备iotId
         * @param beginTimeInS       录像开始时间,1970年1月1日开始的秒数
         * @param endTimeInS         录像结束时间,1970年1月1日开始的秒数
         * @param encrypted          是否流需要加密
         * @param encryptType        流加密类型
         * @param seekToPositionInMs 相对于beginTime的播放偏移量,单位为ms
         */
        public void setDataSourceByIPCRecordTime(String iotId, int beginTimeInS, int endTimeInS, boolean encrypted, int encryptType, long seekToPositionInMs) 
    • 校验和准备数据
      /**
         * 校验和准备数据
         */
        void prepare();
    • 开始或恢复播放视频
      /**
         * 开始播放或恢复播放视频
         */
        void start();
    • 暂停播放
      /**
         * 暂停播放,调用start()恢复播放
         */
        void pause();
    • seek到指定位置
      /**
         * seek到指定位置
         * @param position 毫秒
         */
        void seekTo(long positionInMs);
    • 停止播放
      /**
         * 停止播放
         */
        void stop();
    • 重置播放器
      /**
         * 重置播放器
         */
        void reset();
    • 释放播放器资源
      /**
         * 释放播放器资源
         */
        void release();
    • 截图
      /**
         * 当前视频画面截图
         * @return 如果当前无画面则返回 null
         */
        Bitmap snapShot();
    • 开始录屏
      /**
         * 开始录制当前播放内容,生成MPEG-4格式转存到指定的文件中
         * 文件名后缀必须为.mp4
         * 须在{@link PlayerState#STATE_READY}时调用有效
         * @param contentFile
         * @return 操作成功与否
         */
        boolean startRecordingContent(File contentFile) throws IOException;
    • 结束录屏
      /**
         * 停止记录播放内容
         * @return 操作成功与否
         */
        boolean stopRecordingContent();
    • 设置播放器音量
      /**
         * 设置播放器音量
         * @param audioVolume 范围 0-1,0为静音
         */
        void setVolume(float audioVolume);
    • 设置音频流通道类型
      /**
         * 设置音频流通道类型,参见{@link android.media.AudioManager}
         * 如果音频正在播放,则会因为重新创建AudioTrack导致有短暂停顿
         * @param streamType
         */
        void setAudioStreamType(int streamType);
    • 设置画面缩放模式
      /**
         * 设置视频画面缩放模式,默认为{@link android.media.MediaCodec#VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING}
         * @param videoScalingMode 参考:
         * {@link android.media.MediaCodec#VIDEO_SCALING_MODE_SCALE_TO_FIT}
         * {@link android.media.MediaCodec#VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING}
         */
        void setVideoScalingMode(int videoScalingMode);
    • 设置播放器固定缓存帧数
      /**
         * 设置播放器固定缓存帧数
         * @param frameCount 播放器固定缓存帧数,范围0-16帧,数值越大播放器延迟越大,流畅性越好
         */
        void setBufferedFrameCount(int frameCount);
    • 设置surfaceview
      /**
           * 设置SurfaceView, 必须为GLSurfaceView,同一个Window中同时只允许一个播放器播放,若需要支持多播放实例,请使用TextureView
           * 注意:GLSurfaceView必须在Activity的onResume和onPause回调方法中调用GLSurfaceView的onResume和onPause方法
           * @param surfaceview
           */
        void setSurfaceView(SurfaceView surfaceview);
    • 清除surfaceview
      /**
         * 清除surfaceview
         */
        void clearSurfaceView();
    • 设置textureview
      /**
           * 设置TextureView
           * @param textureview
           */
          void setTextureView(TextureView textureView);
    • 清除textureview
      /**
           * 清除textureview
           */
          void clearTextureView();
    • 设置数据源准备就绪事件监听器
      /**
         * 设置数据源准备就绪事件监听器
         * @param listener
         */
        void setOnPreparedListener(OnPreparedListener listener);
    • 设置播放器错误事件监听器
      /**
         * 设置播放器错误事件监听器,错误类型参考:
         * {@link PlayerException.SOURCE_ERROR}
         * {@link PlayerException.RENDER_ERROR}
         * {@link PlayerException.UNEXPECTED_ERROR}
         * @param listener
         */
        void setOnErrorListener(OnErrorListener listener);
    • 设置播放状态变更事件监听器
      /**
         * 设置播放状态变更事件监听器
         * @param listener
         */
        void setOnPlayerStateChangedListener(OnPlayerStateChangedListener listener);
    • 设置首帧被渲染事件监听器
      /**
         * 设置首帧被渲染事件监听器
         * @param listener
         */
        void setOnRenderedFirstFrameListener(OnRenderedFirstFrameListener listener);
    • 设置播放到内容结束事件监听器
      /**
         * 设置播放到内容结束事件监听器
         * 收到该事件,播放器状态并不会切到STATE_END, 需要调用stop才会切
         * @param listener
         */
        void setOnCompletionListener(OnCompletionListener listener);
    • 获取当前播放进度
      /**
         * 获取当前播放进度
         * 播放器状态为{@link PlayerState#STATE_READY}时调用有效
         * @return 单位MS
         */
        long getCurrentPosition();
    • 获取视频总时长
      /**
         * 获取视频总时长
         * 播放器状态为{@link #STATE_READY}时调用有效
         * @return 单位MS
         */
        long getDuration();
    • 获取音量
      /**
         * 获取音量
         * @return 范围0-1, 0为静音
         */
        float getVolume();
    • 获取播放器状态
      /**
         * 获取播放状态
         * @return 状态枚举,参考:
         * {@link PlayerState#STATE_IDLE} 播放器初始状态
         * {@link PlayerState#STATE_BUFFERING} 缓冲中状态
         * {@link PlayerState#STATE_READY} 缓冲结束开始播放状态
         * {@link PlayerState#STATE_ENDED} 播放完成状态
         */
        int getPlayState();
    • 获取播放器当前流的连接类型
      /**
         * 获取播放器当前流的连接类型
         * 播放器状态为{@link PlayerState#STATE_READY}时调用有效
         * @return {@link StreamConnectType}
         */
        StreamConnectType getStreamConnectType();
    • 获取播放器当前的帧率/码率等信息
      /**
         * 获取播放器当前的帧率/码率等信息
         * 播放器状态为{@link PlayerState#STATE_READY}时调用有效
         * @return 包含帧率/码率等信息的json string
         */
        PlayInfo getCurrentPlayInfo();
  • ExoHlsPlayer
    • 构造方法
      ExoHlsPlayer(Context context);
    • 设置m3u8播放地址
      /**
         * 设置播放源
         * @param url m3u8地址
         */
        void setDataSource(String url);
    • 设置播放地址为IPC云存录像(按文件名)
      /**
         * 设置播放地址为IPC云存录像(按文件名)
         * @param iotId    设备iotId
         * @param fileName 录像文件名
         */
         void setDataSourceByIPCRecordFileName(String iotId, String fileName);
    • 校验和准备数据
      /**
         * 校验和准备数据
         */
        void prepare();
    • 开始或恢复播放视频
      /**
         * 开始播放或恢复播放视频
         */
        void start();
    • 暂停播放
      /**
         * 暂停播放, 调用start()恢复播放
         */
        void pause();
    • seek到指定位置
      /**
         * seek到指定位置
         * @param position 毫秒
         */
        void seekTo(long positionInMs);
    • 停止播放
      **
         * 停止播放
         */
        void stop();
    • 重置播放器
      /**
         * 重置播放器
         */
        void reset();
    • 释放播放器资源
      /**
         * 释放播放器资源
         */
        void release();
    • 设置是否循环播放
      /**
        * 设置是否循环播放
        * @param circlePlay true为循环播放
        */
        void setCirclePlay(boolean circlePlay);
    • 设置回放速率
      /**
        * 设置回放的播放速率
        * @param speed 速率因子,需大于0
        */
        void setPlaybackSpeed(float speed);
    • 设置播放器音量
      /**
         * 设置播放器音量
         * @param audioVolume 范围 0-1,0为静音
         */
        void setVolume(float audioVolume);
    • 设置音频流通道类型
      /**
         * 设置音频流通道类型,参见{@link android.media.AudioManager}
         * 如果音频正在播放,则会因为重新创建AudioTrack导致有短暂停顿.
         * @param streamType
         */
        void setAudioStreamType(int streamType);
    • 设置画面缩放模式
      /**
         * 设置视频画面缩放模式,默认为{@link android.media.MediaCodec#VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING}
         * @param videoScalingMode 参考:
         * {@link android.media.MediaCodec#VIDEO_SCALING_MODE_SCALE_TO_FIT}
         * {@link android.media.MediaCodec#VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING}
         */
        void setVideoScalingMode(int videoScalingMode);
    • 设置surfaceview
      /**
         * 设置SurfaceView
         * @param surfaceview
         */
        void setSurfaceView(SurfaceView surfaceview);
    • 清除surfaceview
      /**
         * 清除surfaceview
         */
        void clearSurfaceView();
    • 设置数据源准备就绪事件监听器
      /**
         * 设置数据源准备就绪事件监听器
         * @param listener
         */
        void setOnPreparedListener(OnPreparedListener listener);
    • 设置播放器错误事件监听器
      /**
         * 设置播放器错误事件监听器,错误类型参考:
         * {@link PlayerException.SOURCE_ERROR}
         * {@link PlayerException.RENDER_ERROR}
         * {@link PlayerException.UNEXPECTED_ERROR}
         * @param listener
         */
        void setOnErrorListener(OnErrorListener listener);
    • 设置播放状态变更事件监听器
      /**
         * 设置播放状态变更事件监听器
         * @param listener
         */
        void setOnPlayerStateChangedListener(OnPlayerStateChangedListener listener);
    • 设置首帧被渲染事件监听器
      /**
         * 设置首帧被渲染事件监听器
         * @param listener
         */
        void setOnRenderedFirstFrameListener(OnRenderedFirstFrameListener listener);
    • 获取当前播放进度
      /**
         * 获取当前播放进度
         * 播放器状态为{@link PlayerState#STATE_READY}时调用有效
         * @return 单位MS
         */
        long getCurrentPosition();
    • 获取视频总时长
      /**
         * 获取视频总时长
         * 播放器状态为{@link #STATE_READY}时调用有效
         * @return 单位MS
         */
        long getDuration();
    • 获取音量
      /**
         * 获取音量
         * @return 范围:0-1
         */
        float getVolume();
    • 获取播放器状态
      /**
         * 获取播放状态
         * @return 状态枚举,参考:
         * {@link PlayerState#STATE_IDLE} 播放器初始状态
         * {@link PlayerState#STATE_BUFFERING} 缓冲中状态
         * {@link PlayerState#STATE_READY} 缓冲结束开始播放状态
         * {@link PlayerState#STATE_ENDED} 播放完成状态
         */
        int getPlayState();

错误列表

错误主码 描述 子码 描述
SOURCE_ERROR 数据源相关错误 SUB_CODE_SOURCE_STREAM_CONNECT_ERROR(1005) 与数据源建立连接失败
SUB_CODE_SOURCE_INVALID_DECRYPTE_KEY(1006) 无效的解密密钥
SUB_CODE_SOURCE_INVALID_RTMP_URL(1007) 无效的播放地址
SUB_CODE_SOURCE_PARAMETER_ERROR(1008) 错误的数据源参数
SUB_CODE_SOURCE_QUERY_URL_FAILED(1009) 请求播放地址失败
RENDER_ERROR 渲染相关错误 SUB_CODE_RENDER_DECODE_ERROR(1000) 解码错误
UNEXPECTED_ERROR 不符合预期错误 SUB_CODE_UNEXPECTED_PULL_STREAM_ERROR(1100) 拉流失败,8S未拉取到流或连接被异常断开

语音对讲

提供App和IPC设备之间端到端的双向实时音频传输能力。

语音对讲支持双工模式,App端需要完成流程如下。

语音对讲流程

音频格式支持情况如下。

类型 编码 解码
PCM - -
AAC_LC
G711A
G711U

使用指南

语音对讲集成分为以下几个步骤。

  1. 创建语音对讲实例。
    // 创建语音对讲实例
     liveIntercom = new LiveIntercom();
    					
  2. 注册和处理语音对讲错误回调。

    处理在语音对讲通道建立以及对讲中时都可能发生错误,错误类型详见错误列表

    // 设置语音对讲错误回调 
     liveIntercom.setOnErrorListener(new com.aliyun.iotx.linkvisual.media.audio.listener.OnErrorListener() {
         @Override
         public void onError(LiveIntercomException error) {
             showToast(error.getMessage());
             error.printStackTrace();
             // 处理语音对讲错误,如停止录音机,重置UI元素等
         }
     });
  3. 注册和处理语音对讲对端就绪回调

    当对讲连接于服务端连接建立后,若对端已就绪,会告知本端事件“talk ready”。此时向对端发送的音频数据,都会被对端收到并处理。

       liveIntercom.setOnTalkReadyListener(new OnTalkReadyListener() {
             @Override
             public void onTalkReady() {
                 showToast("可以开始说话了");
             }
         });
    					
  4. 注册和处理对端音频参数变更回调。

    当语音对讲通道建立后,若对端支持录音,会先收到对端发送过来的音频参数信息,后续对端发送的音频数据按照此音频参数来做解码。该事件是语音对讲通道建立成功的标志。可以在此时构建音频播放器实例用于对端采集音频的实时播放。

    // 设置对端音频参数变更回调
     liveIntercom.setOnAudioParamsChangeListener(new OnAudioParamsChangeListener() {
         @Override
         public void onAudioParamsChange(AudioParams audioParams) {
             // 收到对端发送的音频参数,用于初始化AuudioTrack
         }
     });
  5. 注册和处理对端音频数据接收回调。

    若对端支持录音,语音对讲中会持续不断的收到对端发送过来的音频数据。

    // 设置对端音频数据回调         
     liveIntercom.setOnAudioBufferReceiveListener(new OnAudioBufferReceiveListener() {
             @Override
             public void onAudioBufferRecevie(byte[] bytes, int i) {
             //收到对端发过来的音频数据, 送入播放器播放
             }
         });
  6. 采集和发送音频。

    SDK提供了录音机(SimpleAudioRecord)和流音频播放器(SimpleStreamAudioTrack),可用于语音对讲音频采集和播放,且可作为一种参考实现。

    // 创建录音机用于采集pcm数据
     audioRecord = new SimpleAudioRecord(AudioSource.VOICE_COMMUNCATION,AudioParams.AUDIOPARAM_MONO_8K_PCM);
     audioRecord.setAudioRecordListener(new AudioRecordListener() {
         @Override
         public void onRecordStart() {
             Log.d(TAG, "onRecordStart");
             // 录音开始后,再启动语音对讲,指定SDK将音频数据转成G711A格式后再发送
             liveIntercom.start(iotId, AudioParams.AUDIOPARAM_MONO_8K_G711A);
         }
    
         @Override
         public void onRecordEnd() {
             Log.d(TAG, "onRecordEnd");
             // 录音结束时, 关闭语音对讲
             liveIntercom.stop();
         }
    
         @Override
         public void onBufferReceived(byte[] buffer, int offset, int size) {
             Log.d(TAG, "onBufferReceived:" + size);
             // 收到录音机PCM数据,调用语音对讲接口发送给对端
             liveIntercom.sendAudioBuffer(buffer, offset, size);
         }
    
         @Override
         public void onError(int error, String message) {
             Log.e(TAG, "onError:" + error + message);
             showToast("录音机错误:" + error + message);
             // 处理录音机错误,如停止语音对讲、重置UI元素等
         }
     });
    
     // 启动录音机
     audioRecord.start();                 

关于回声消除,Android设备差异较大,即使设置采集源为AudioSource.VOICE_COMMUNCATION或使用AcousticEchoCanceler在有些手机上也并未启用回声抑制,如对效果有较高的要求,可自行实现AEC(如使用Speex或WebRTC AEC模块来实现)。

接口说明

  • LiveIntercom
    • 构造方法
      /**
         * 构造语音对讲实例
         */
        LiveIntercom()          
    • 开始语音对讲
      /**
         * 建立语音对讲通道
         * @param iotId iotId 设备iotId
         * @param audioParams 指定App端上行音频参数格式,如采样率、通道数、采样位宽、音频格式,请确保对端能支持该音频参数配置
         */
        void start(String iotId, AudioParams audioParams);            
    • 关闭语音对讲
      /**
         * 关闭语音对讲通道
         * @return
         */
        void stop();      
    • 发送语音数据
      /**
         * 发送音频数据
         * 数据格式为PCM
         * 内部会依据{@link #start(String, AudioParams)}时传入的音频格式来做重新编码
         * 若语音对讲还未建立成功,送入的数据将会被丢弃
         * @param data
         * @param offset
         * @param length
         */
        void sendAudioBuffer(byte[] data, int offset, int length);       
    • 设置对讲就绪回调
       /**
         * 设置对讲就绪回调
         * @param listener
         */
        void setOnTalkReadyListener(OnTalkReadyListener listener);
      
        public interface OnTalkReadyListener {
            /**
             * 语音对讲对端就绪,表明双方连接已建立成功,对端已经做好对讲准备,可以开始发送数据
             */
            void onTalkReady();
        }               
    • 设置接收对端音频数据回调
       /**
         * 若设备端不支持录音则无需关注
         * 设置接收对端音频数据回调
         * 数据格式为PCM
         * @param listener
         */
        void setOnAudioBufferReceiveListener(OnAudioBufferReceiveListener listener);
        public interface OnAudioBufferReceiveListener {
            /**
            * 收到对端的PCM数据
            * @param buffer  PCM buffer 
            * @param size    buffer size
            */
            void onAudioBufferRecevie(byte[] buffer, int size);
        }              
    • 设置对端音频参数变更回调
       /**
         * 若设备端不支持录音则无需关注
         * 设置对端音频参数变更回调接口,语音通道刚建立成功或对端音频参数变更时会被回调
         * @param listener
         */
        void setOnAudioParamsChangeListener(OnAudioParamsChangeListener listener);
        public interface OnAudioParamsChangeListener {
            /**
            * 收到对端发送过来的音频头,描述PCM数据格式
            * @param audioParams 新的音频参数
            */
            void onAudioParamsChange(AudioParams audioParams);
        }
    • 设置错误回调
       /**
         * 设置错误回调接口
         * @param listener
         */
        void setOnErrorListener(OnErrorListener listener);
      
        public interface OnErrorListener {
            /**
            * 错误回调
            * @param error 参考错误列表
            */
            void onError(LiveIntercomException error);
        }
  • SimpleAudioRecord
    • 创建录音机实例
      /**
      * 按照指定的音频参数创建录音机实例子
      * @param audioSource 指定源
      * @param audioParams 指定录音机的通道数、采样率、采样位宽
      */
      SimpleAudioRecord(int audioSource, AudioParams audioParams);  
    • 获取AudioSession id
      int getAudioSessionId()     
    • 设置录音事件回调
      void setAudioRecordListener(AudioRecordListener listener)
      
      public interface AudioRecordListener {
          /**
           * 开始录音
           */
          void onRecordStart();
      
          /**
           * 结束录音
           */
          void onRecordEnd();
      
          /**
           * 录音数据回调(PCM数据)
           * @param buffer
           * @param offset
           * @param size
           */
          void onBufferReceived(byte[] buffer, int offset, int size);
      
          /**
           * 录音机错误
           * {@link SimpleAudioRecord#ERR_INIT_RECORD}
           * {@link SimpleAudioRecord#ERR_READ_BUFFER}
           * {@link SimpleAudioRecord#ERR_START_RECORD}
           * @param error
           * @param message
           */
          void onError(int error, String message);
      }
    • 结束录音
      void stop();
  • SimpleStreamAudioTrack
    • 创建播放器实例
      /**
         * 创建流播放器
         * @param audioParams     音频参数
         * @param audioStreamType 流类型,见{@link android.media.AudioManager}
         * @param audioBuffer     数据阻塞队列,向该队列中加入数据即播放
         * @param audioSessionId  audio session id,用于回声消除
         * @throws IllegalArgumentException
         */
      SimpleStreamAudioTrack(AudioParams audioParams, int audioStreamType, BlockingQueue audioBuffer) throws IllegalArgumentException;
    • 开始播放
      void start()
    • 恢复播放
      void resume()
    • 暂停播放
      void pause()
    • 停止播放
      void stop()
    • 获取播放状态,见AudioTrack#PLAYSTATE
      int getPlayState()
    • 设置播放音量
      void setVolume(float volume)
    • 释放播放器
      void release()

错误列表

错误枚举 描述
LiveIntercomException.INVALID_AUDIO_PARAMS 无效的语音对讲音频参数(对端上报的音频参数SDK不支持)
LiveIntercomException.START_LIVE_INTERCOM_REQUEST_FAILED 启动语音对讲失败
LiveIntercomException.CONNECTION_STREAM_FAILED 语音流建立失败(5S未建立成功会超时)
LiveIntercomException.SEND_STREAM_DATA_FAILED 发送语音流数据失败
LiveIntercomException.RECEIVE_STREAM_DATA_FAILED 接收语音流数据失败