Link Visual Android Media SDK文档

更新时间:2020-03-13 10:13:57

概述

本节为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.3')

使用方式

视频播放器

播放器按功能分为三种:
直播播放器

  • 用于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.8.3.

功能列表:

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

使用指南

直播播放器

// 构造播放器实例
LivePlayer player = new LivePlayer();

// 设置surfaceview, 必须为GLSurfaceView
// 注意:GLSurfaceView必须在Activity的onResume和onPause回调方法中调用GLSurfaceView的onResume和onPause方法
player.setSurfaceView(GLSurfaceView);
// 设置必要的状态监听
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();

// 设置surfaceview, 必须为GLSurfaceView
// 注意:GLSurfaceView必须在Activity的onResume和onPause回调方法中调用GLSurfaceView的onResume和onPause方法
player.setSurfaceView(GLSurfaceView);
// 设置必要的状态监听
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);
  • 设置surfaceview
/**
     * 设置SurfaceView, 必须为GLSurfaceView
     * @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);
  • 获取音量
/**
     * 获取音量
     * @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);
  • 设置音频流通道类型
/**
     * 设置音频流通道类型,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);
  • 设置surfaceview
/**
     * 设置SurfaceView, 必须为GLSurfaceView
     * @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);
  • 设置播放到内容结束事件监听器
/**
     * 设置播放到内容结束事件监听器
     * 收到该事件,播放器状态并不会切到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);
  • 设置音频流通道类型
/**
     * 设置音频流通道类型,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);
  • 设置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();

错误列表

见PlayerException:

错误主码 描述 子码 描述
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端需要做: 发起开始语音对讲请求->交换音频参数->音频采集-> 音频编码(可选)-> 上传/接收 -> 音频解码(可选) -> 音频播放->停止语音对讲 这些流程.

音频格式支持情况:

编码 解码
PCM - -
AAC_LC
G711A
G711U

使用指南

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

  1. 创建语音对讲实例
// 创建语音对讲实例
    liveIntercom = new LiveIntercom();
  1. 注册和处理语音对讲错误回调
    在语音对讲通道建立以及对讲中时都可能发生错误,需要处理,错误类型详见错误列表.
// 设置语音对讲错误回调 
    liveIntercom.setOnErrorListener(new com.aliyun.iotx.linkvisual.media.audio.listener.OnErrorListener() {
        @Override
        public void onError(LiveIntercomException error) {
            showToast(error.getMessage());
            error.printStackTrace();
            // 处理语音对讲错误,如停止录音机, 重置UI元素等
        }
    });
  1. 注册和处理语音对讲对端就绪回调
    当对讲连接于服务端连接建立后,若对端已就绪,会告知本端事件talk ready. 此时向对端发送音频数据都会被对端收到并处理.
liveIntercom.setOnTalkReadyListener(new OnTalkReadyListener() {
            @Override
            public void onTalkReady() {
                showToast("可以开始说话了");
            }
        });
  1. 注册和处理对端音频参数变更回调
    当语音对讲通道建立后,若对端支持录音,会先收到对端发送过来的音频参数信息,后续对端发送的音频数据按照此音频参数来做解码. 该事件是语音对讲通道建立成功的标志. 可以在此时构建音频播放器实例用于对端采集音频的实时播放.
// 设置对端音频参数变更回调
    liveIntercom.setOnAudioParamsChangeListener(new OnAudioParamsChangeListener() {
        @Override
        public void onAudioParamsChange(AudioParams audioParams) {
            // 收到对端发送的音频参数,用于初始化AuudioTrack
        }
    });
  1. 注册和处理对端音频数据接收回调
    若对端支持录音,语音对讲中会持续不断的收到对端发送过来的音频数据.
// 设置对端音频数据回调         
    liveIntercom.setOnAudioBufferReceiveListener(new OnAudioBufferReceiveListener() {
            @Override
            public void onAudioBufferRecevie(byte[] bytes, int i) {
            //收到对端发过来的音频数据, 送入播放器播放
            }
        });
  1. 音频采集和发送
    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);
  • 启动录音
void start();
  • 获取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 接收语音流数据失败

ChangeLog

1.0.0:

  • 初始版本

1.1.0(2019.2.20):

  • 包名由LinkVision变更为LinkVisual

  • 适配服务端API2.0.0接口

  • 移除ExoHlsPlayer中的void setDataSourceByIPCRecordEventId(String iotId, String eventId)方法

  • 修改按时间请求本地录像播放地址接口入参类型为int

  • 修复前一个播放器实例销毁中下一个实例创建偶现的画面残影问题

  • 修复若干稳定性问题

1.2.0(2019.4.1):

  • 废弃LivePlayer(Context context, String appkey, String authcode)、VodPlayer(Context context, String appkey, String authcode)、LiveIntercom(Context context, String appkey, String authcode)构造方法

  • 去除对H2通道依赖

  • 优化语音对讲启动速度

  • 优化P2P建连速度和成功率

  • 直播/点播支持H265

  • 修复若干稳定性问题

1.2.1(2019.4.19):

  • 对讲增加5S连接未建立的超时

  • 增加VodPlayer和ExoHlsPlayer的setOnCompletionListener(OnCompletionListener listener)方法

  • 新增VodPlayer的void setDataSourceByIPCRecordTime(String iotId, int beginTimeInS, int endTimeInS, boolean encrypted, int encryptType, long seekToPositionInMs)方法

  • 优化SDK大小

1.2.3(2019.7.1)

  • 新增armeabi-v7a、arm64-v8a、x86平台支持

  • 新增LiveIntercom的setOnTalkReadyListener(OnTalkReady)方法,用于接收对讲对端就绪事件

  • 支持ALog.setLogLevel()来调整底层库日志输出级别

  • 修复保存的Mp4文件声音快放问题

  • 修复H265源保存的Mp4文件在MacOS和iOS上不能播放的问题

  • 改善P2P效果

  • 优化视频解码性能,支持低性能设备

  • 细化错误码,补充子码描述

  • 修复若干稳定性问题


版权信息

LinkVisual视频Media SDK使用了librtmp和FFmpeg开源软件,相关版权声明如下。
librtmp

Copyright (C) 2005-2008 Team XBMC
     http://www.xbmc.org
     Copyright (C) 2008-2009 Andrej Stepanchuk
     Copyright (C) 2009-2010 Howard Chu

 librtmp is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as
 published by the Free Software Foundation; either version 2.1,
 or (at your option) any later version.

 librtmp is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 GNU General Public License for more details.

 You should have received a copy of the GNU Lesser General Public License
 along with librtmp see the file COPYING.  If not, write to
 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 Boston, MA  02110-1301, USA.
 http://www.gnu.org/copyleft/lgpl.html

FFmpeg

FFmpeg is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

FFmpeg is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with FFmpeg; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

results matching ""

    No results matching ""