LinkVisual Media SDK

更新时间:
复制 MD 格式

The LinkVisual software development kit (SDK) for applications provides features such as audio and video playback and voice intercom.

Dependent SDK

Overview

API channel

Provides API channel capabilities.

Initialization

For more information about initialization, see SDK initialization.

Import dependencies

// 1. Add a reference to the Alibaba Cloud Maven repository in the build.gradle file of the root directory.
allprojects {
    repositories {
        maven {
            url "http://maven.aliyun.com/nexus/content/repositories/releases"
        }
    }
}

// 2. Add dependencies in the build.gradle file of the app.
implementation('com.aliyun.iotx:linkvisual-media:2.7.5-ilop')

For more information about release versions, see Link Visual SDK Update History.

Obfuscation configuration

# Keep and do not warn Link Visual.

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

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

SDK API documentation

LinkVisual Media SDK Documentation (Android)

Player

Video players are classified into three types based on their features.

  • Live player

    • Supports live playback for devices connected to LinkVisual.

    • Provides low playback latency.

    • Supports peer-to-peer (P2P) communication with devices.

  • Video-on-demand (VOD) player (device recordings)

    • Plays back local device recordings. You can adjust the playback progress.

    • Supports P2P communication with devices.

  • VOD player (HLS cloud recordings)

    • Plays back HLS-based cloud recordings. It supports MPEG-TS and fMP4 containers and the AES-128 encryption method.

Player feature table

Feature

Live player

VOD player (device recordings)

VOD player (HLS cloud recordings)

Video playback

Audio playback

Pause/Resume

-

Playback reconnection

-

-

Seek to a specific position

-

Total duration

-

Current playback progress

-

Player status change notifications

Mute playback

Variable speed playback

-

Frame-by-frame stepping

-

Video scaling mode settings

Display mode settings when playback stops

NVR multi-screen playback

Digital zoom

Take a screenshot of the playback window

Save screenshot to a file

Record while playing

Hardware decoding

Get stream information

Provide YUV data

Provide raw stream data

Provide SEI data

Player usage examples:

  • Live player

    // Construct a player instance.
    LVLivePlayer player = new LVLivePlayer(getApplicationContext());
    
    // Set the texture view. You can use the ZoomableTextureView component provided by the SDK, which supports video scaling. The video is not rotated.
    player.setTextureView(zoomableTextureView, LVVideoRotationMode.LV_VIDEO_ROTATE_0_CLOCKWISE);
    // Set the required listener.
    player.setPlayerListener(new ILVPlayerListener() {
        @Override
        public void onError(LVPlayerError error) {
            // An error occurred during playback.
        }
        @Override
        public void onPlayerStateChange(LVPlayerState state) {
            Log.d(TAG, "play state= " + state.name());
            switch (state) {
                case STATE_BUFFERING:
                    // Display buffering.
                    break;
                case STATE_IDLE:
                    break;
                case STATE_READY:
                    // Hide buffering.
                    updatePlayInfo();
                    break;
                case STATE_ENDED:
                    // Hide buffering.
                    break;
                default:
                    break;
            }
        }
        @Override
        public void onRenderedFirstFrame(int elapsedTimeInMs) {
            // Display callback. elapsedTimeInMs indicates the time consumed to render the first frame.
        }
        @Override
        public void onVideoSizeChanged(int width, int height) {
            // Callback for width and height changes.
        }
        @Override
        public void onSeiInfoUpdate(byte[] buffer, int length, long timeStamp) {
            // Callback for SEI data frames in a private format in the stream. This is no longer recommended.
        }
        @Override
        public void onStandardSeiInfoUpdate(byte[] buffer, int length, long timeStamp) {
            // Callback for standard SEI data frames in the stream.
        }
        @Override
        public void onVideoJitterBufferEmpty() {
        }
    });
    
    // Set the data source. The data source is the IotId of the device.
    player.setLiveDataSource(iotId, LVStreamType.LV_STREAM_TYPE_MAJOR);
    // Set the number of automatic reconnections.
    player.setReconnectCount(3);
    // Set the decoding strategy to hardware-first.
    player.setDecoderStrategy(LVDecoderStrategy.LV_DECODER_STRATEGY_HARDWARE_FIRST);
    // Set the video scaling mode to fit.
    player.setVideoScalingMode(LVVideoScalingMode.LV_VIDEO_SCALING_MODE_FIT);
    // Set the display mode to keep the last frame when playback stops.
    player.setPlayerStoppedDrawingMode(LVPlayerStoppedDrawingMode.LV_ALWAYS_KEEP_LAST_FRAME);
    ...
    // Start playback.
    player.start();
    ...
    // Stop playback.
    player.stop();
    ...
    // Release player resources.
    player.release();     
  • VOD player (device recordings)

    // Construct a player instance.
    LVVodPlayer player = new LVVodPlayer(getApplicationContext());
    // Set the texture view. You can use the ZoomableTextureView component provided by the SDK, which supports video scaling.
    player.setTextureView(zoomableTextureView);
    
    // Set the required listener.
    player.setPlayerListener(new ILVPlayerListener() {
        @Override
        public void onError(LVPlayerError error) {
            // An error occurred during playback.
        }
        @Override
        public void onPlayerStateChange(LVPlayerState state) {
            Log.d(TAG, "play state= " + state.name());
            switch (state) {
                case STATE_BUFFERING:
                    // Display buffering.
                    break;
                case STATE_IDLE:
                    break;
                case STATE_READY:
                    // Hide buffering.
                    updatePlayInfo();
                    break;
                case STATE_ENDED:
                    // Hide buffering.
                    break;
                default:
                    break;
            }
        }
        @Override
        public void onRenderedFirstFrame(int elapsedTimeInMs) {
            // Display callback. elapsedTimeInMs indicates the time consumed to render the first frame.
        }
        @Override
        public void onVideoSizeChanged(int width, int height) {
            // Callback for width and height changes.
        }
        @Override
        public void onSeiInfoUpdate(byte[] buffer, int length, long timeStamp) {
            // Callback for SEI data frames in a private format in the stream. This is no longer recommended.
        }
        @Override
        public void onStandardSeiInfoUpdate(byte[] buffer, int length, long timeStamp) {
            // Callback for standard SEI data frames in the stream.
        }
        @Override
        public void onVideoJitterBufferEmpty() {
        }
    });
    
    // Set the listener for playback completion.
    player.setVodCompletionListener(new ILVVodPlayerCompletionListener() {
        @Override
        public void onCompletion() {
            // Playback is complete.
        }
    });
    
    // Set the data source. You can use one of the following methods.
    // 1. By device filename. The initial playback offset is 20s.
    player.setDataSourceByLocalRecordFileName(iotId, "fileNamexxxxxxxx", 20000);
    // 2. By device time. The recording is from 2022-08-29 17:54:14 to 2022-08-30 02:47:34. The initial playback offset is 20s. The type is all recordings.
    player.setDataSourceByLocalRecordTime(iotId, 1661766854, 1661798854, 20000, 99);
    
    // Set the decoding strategy to hardware-first.
    player.setDecoderStrategy(LVDecoderStrategy.LV_DECODER_STRATEGY_HARDWARE_FIRST);
    // Set the video scaling mode to fit.
    player.setVideoScalingMode(LVVideoScalingMode.LV_VIDEO_SCALING_MODE_FIT);
    ...
    // Start playback.
    player.start();
    ...
    // Pause.
    player.pause();
    ...
    // Resume.
    player.resume();
    ...
    // Stop playback.
    player.stop();
    ...
    // Release player resources.
    player.release();                 
  • VOD player (HLS cloud storage)

    // Construct a player instance.
    LVVodPlayer player = new LVVodPlayer(getApplicationContext());
    // Set the texture view. You can use the ZoomableTextureView component provided by the SDK, which supports video scaling.
    player.setTextureView(zoomableTextureView);
    // Set the required listener.
    player.setPlayerListener(new ILVPlayerListener() {
        @Override
        public void onError(LVPlayerError error) {
            // An error occurred during playback.
        }
        @Override
        public void onPlayerStateChange(LVPlayerState state) {
            Log.d(TAG, "play state= " + state.name());
            switch (state) {
                case STATE_BUFFERING:
                    // Display buffering.
                    break;
                case STATE_IDLE:
                    break;
                case STATE_READY:
                    // Hide buffering.
                    updatePlayInfo();
                    break;
                case STATE_ENDED:
                    // Hide buffering.
                    break;
                default:
                    break;
            }
        }
        @Override
        public void onRenderedFirstFrame(int elapsedTimeInMs) {
            // Display callback. elapsedTimeInMs indicates the time consumed to render the first frame.
        }
        @Override
        public void onVideoSizeChanged(int width, int height) {
            // Callback for width and height changes.
        }    
        @Override
        public void onSeiInfoUpdate(byte[] buffer, int length, long timeStamp) {
            // Callback for SEI data frames in a private format in the stream. This is no longer recommended.
        }
        @Override
        public void onStandardSeiInfoUpdate(byte[] buffer, int length, long timeStamp) {
            // Callback for standard SEI data frames in the stream.
        }
        @Override
        public void onVideoJitterBufferEmpty() {
        }
    });
    // Set the listener for playback completion.
    player.setVodCompletionListener(new ILVVodPlayerCompletionListener() {
        @Override
        public void onCompletion() {
            // Playback is complete.
        }
    });
    
    // Set the data source by cloud recording filename. The initial playback offset is 20s.
    player.setDataSourceByCloudRecordFileName(iotId, "fileNamexxxxxxxx", 20000);
    
    // Set the decoding strategy to hardware-first.
    player.setDecoderStrategy(LVDecoderStrategy.LV_DECODER_STRATEGY_HARDWARE_FIRST);
    // Set the video scaling mode to fit.
    player.setVideoScalingMode(LVVideoScalingMode.LV_VIDEO_SCALING_MODE_FIT);
    ...
    // Start playback.
    player.start();
    ...
    // Pause.
    player.pause();
    ...
    // Resume.
    player.resume();
    ...
    // Stop playback.
    player.stop();
    ...
    // Release player resources.
    player.release();                 

Player status description

You can set a player status listener to receive status change events and update related UI elements.

Status change events include playback errors and manual playback stops.

播放器状态图

  • IDLE: The player is not playing any content.

  • BUFFERING: The player is buffering and not ready for playback. Status change events include buffering at the start of playback, re-buffering after a `seekTo()` call, or VOD buffering due to poor network conditions.

  • READY: The player is playing content. Status change events include the rendering of the first frame and the start of playback of new content after `seekTo()` buffering is complete. For a VOD player, if you call `seekTo()` or the playback reaches the end of the file, the OnCompletionListener.onCompletion() method is called, and the status automatically changes to ENDED.

  • ENDED: The player has finished playback. The status changes to ENDED when a playback error occurs, `stop()` is called, or playback finishes.

Player error list

Primary error code

Sub error code

Description

Solution

LV_PLAYER_ERROR_CODE_SOURCE

LV_PLAYER_ERROR_SUB_CODE_SOURCE_STREAM_CONNECT

Failed to connect to the data source.

This is usually caused by network issues. Make sure your network is working and retry.

LV_PLAYER_ERROR_SUB_CODE_SOURCE_INVALID_PARAMETER

Invalid data source parameters.

Check if the configuration parameters are valid and retry.

LV_PLAYER_ERROR_SUB_CODE_SOURCE_QUERY_URL_FAILED

Failed to request the playback URL.

Identify and fix the problem based on the description in the `msg` field of the error message.

LV_PLAYER_ERROR_CODE_RENDER

LV_PLAYER_ERROR_SUB_CODE_RENDER_DECODE

Decoding error.

If decoding fails continuously, dump the stream data for analysis. The steps are as follows:

  • Run the command adb shell setprop debug.lv.dump.enable true.

  • Restart the application and play the video.

  • Run the command adb pull /sdcard/Android/data/${pkgname}/files/LinkVisual_dump/ to pull the data.

LV_PLAYER_ERROR_CODE_UNEXPECTED

LV_PLAYER_ERROR_SUB_CODE_UNEXPECTED_PULL_STREAM_TIMEOUT

Failed to pull the stream for more than 8 seconds, or the connection was unexpectedly disconnected.

Check the following items and retry: 1. Check if the device is not ingesting the stream. 2. Check if the network is abnormal on the application side or the device side.

LV_PLAYER_ERROR_SUB_CODE_UNEXPECTED_PLAY_DURATION_EXCEED

The continuous playback duration exceeds the limit.

This limit prevents unnecessary bandwidth consumption from long, unattended playback. If you need continuous viewing, consider upgrading your traffic plan to remove this limit.

Voice intercom

Provides end-to-end one-way or two-way real-time intercom capabilities between the app and an IPC device.

  • One-way talk: The app captures and sends audio data to the device for playback. The phone remains silent while the app is capturing audio.

  • Full-duplex intercom: Both the app and the device capture and play audio simultaneously. The device must support Acoustic Echo Cancellation (AEC). Otherwise, this solution is not recommended.

  • Half-duplex intercom: Both the app and the device can capture and play audio, but only one direction is active at a time. Therefore, the device is not required to support AEC. This works like a walkie-talkie, where the app user can manually control the start and end of recording multiple times within a single intercom session.

The following audio formats are supported.

Type

Sample rate

Encoding

Decoding

G711A

8 kHz/16 kHz

G711U

8 kHz/16 kHz

AAC_LC

8 kHz/16 kHz

How to use the voice intercom:

  1. Create a voice intercom instance and set the audio parameters.

    liveIntercom = new LVLiveIntercom(getApplicationContext(), AudioParams.AUDIOPARAM_MONO_8K_G711A);
  2. Register a listener and handle voice intercom callbacks.

    You can handle the corresponding event callbacks, including the start of the intercom, the start and end of recording, and the volume callback for UI display.

    For information about errors that may occur during voice channel establishment and the intercom process, see the voice intercom error list.

    liveIntercom.setLiveIntercomListener(new ILVLiveIntercomListener() {
        @Override
        public void onTalkReady() {
            // The peer is connected. You can start talking.
        }
        @Override
        public void onRecorderStart() {
            speakBtn.setEnabled(false);
            // Recording starts.
        }
        @Override
        public void onRecorderEnd() {
            // Recording ends.
        }
        @Override
        public void onRecorderVolume(int volume) {
        }
        @Override
        public void onError(LVLiveIntercomError error) {
            // An error occurred during the intercom: code: + error.getCode() + error.getSubCode() +  msg: + error.getMessage());
        }});
    }
  3. Set the gain level.

    You can set the gain value for audio capture on the app side. Seven levels are available: -1 (None), 0 (Mild), 1 (Medium), 2 (High), 3 (Aggressive), 4 (Very Aggressive), and 5 (Max). The default value is None. Adjust the level based on the device's performance.

    liveIntercom.setGainLevel(-1);
  4. Set the intercom mode.

    Five modes are available:

    • One-way talk: The app captures and sends audio data to the device for playback. The phone remains silent while the app is capturing audio.

    • Full-duplex intercom (independent): Both the app and the device capture and play audio simultaneously. The device must support AEC. Otherwise, this solution is not recommended. The audio from the device's intercom channel is used for playback. This mode can exist independently of the live stream channel.

    • Full-duplex intercom (with live stream): Both the app and the device capture and play audio simultaneously. The device must support AEC. Otherwise, this solution is not recommended. The audio from the device's live stream channel is used for playback. This requires an active live stream channel. You can call the `LVLivePlayer.audioFocus()` method to select the corresponding existing live stream channel before you start the intercom.

    • Half-duplex intercom (independent): Both the app and the device capture and play audio, but only one direction is active at a time. Therefore, the device is not required to support AEC. This works like a walkie-talkie, where the app user can manually control the start and end of recording multiple times within a single intercom session. The audio from the device's intercom channel is used for playback. This mode can exist independently of the live stream channel. Note: This mode requires the device-side SDK to be v2.3.3 or later. If an older device SDK is used, the mode is downgraded to full-duplex intercom.

    • Half-duplex intercom (with live stream): Both the app and the device capture and play audio, but only one direction is active at a time. Therefore, the device is not required to support AEC. This works like a walkie-talkie, where the app user can manually control the start and end of recording multiple times within a single intercom session. The audio from the device's live stream channel is used for playback. This requires an active live stream channel. You can call the `LVLivePlayer.audioFocus()` method to select the corresponding existing live stream channel before you start the intercom. Note: This mode requires the device-side SDK to be v2.3.3 or later. If an older device SDK is used, the mode is downgraded to full-duplex intercom.

    liveIntercom.setLiveIntercomMode(LVLiveIntercomMode.DoubleTalk);
  5. Start the intercom.

    After the intercom starts, it requests audio focus, sets the mode to communication, and routes the audio from the device to the speaker. If a Bluetooth or wired headset is connected, the audio is routed to the headset.

    // Start the intercom.
    liveIntercom.start(iotId);
  6. Switch the walkie-talkie speaking state (only for half-duplex intercom).

    After you start a half-duplex intercom, the user switches the intercom state to receive or send audio as needed.

    // In this state, the app stops playback and captures audio to send to the device. The device stops audio capture and plays the audio captured by the app.
    liveIntercom.listen(true);
    ...
    // In this state, the app resumes playback. The device stops playing audio and resumes audio capture.
    liveIntercom.listen(false);
  7. End the intercom.

    After the intercom ends, it releases the audio focus, sets the mode to normal, and cancels the forced audio routing to the speaker. The phone's echo cancellation is enabled by default during the intercom.

    // Stop the intercom.
    liveIntercom.stop();
  8. Release intercom resources.

    You can release the resources when the intercom feature is no longer needed.

    // Release the intercom.
    liveIntercom.release();

Voice intercom error list

Error enumeration

Description

Solution

LV_LIVE_INTERCOM_ERROR_START_REQUEST_FAILED

Failed to initiate a voice intercom request. For more information, see subCode.

Check for and fix the following issues, and then retry:

  • Check for network failures.

  • Check if the device is offline.

  • Check for server-side exceptions.

LV_LIVE_INTERCOM_ERROR_CONNECT_STREAM_FAILED

Failed to establish a voice intercom stream channel.

Check for and fix the following issues, and then retry:

  • Check for network failures.

  • Check if a timeout occurred. A timeout occurs if the device does not respond within 5 seconds.

LV_LIVE_INTERCOM_ERROR_SEND_STREAM_DATA_FAILED

Failed to send audio data.

The network is unstable. Switch to a stable network and retry.

LV_LIVE_INTERCOM_ERROR_RECEIVE_STREAM_DATA_FAILED

Failed to receive audio data.

The network is unstable. Switch to a stable network and retry.

LV_LIVE_INTERCOM_ERROR_INIT_AUDIO_RECORDER_FAILED

Recorder initialization error.

Check for and fix the following issues, and then retry:

  • You can check if the recording permission is not granted.

  • Check if another application is using the recorder. If so, stop the application process and retry.

LV_LIVE_INTERCOM_ERROR_START_AUDIO_RECORDER_FAILED

Recorder startup error.

Check if another application is using the recorder. If so, stop the application process and retry.

LV_LIVE_INTERCOM_ERROR_READ_AUDIO_RECORDER_FAILED

Recorder data read error.

The recorder is abnormal. Restart the application-side device, for example, by restarting the phone.

LV_LIVE_INTERCOM_ERROR_INIT_AUDIO_TRACK_FAILED

Audio player creation failed.

The audio player is abnormal. Restart the application-side device, for example, by restarting the phone.

Audio file recording, playback, and upload

This feature lets you record audio files, play local or network audio files, and upload audio files.

The following formats are supported for recording and playing audio files.

File type

Sample rate

Codec

AMR

8 kHz (supports recording and playback)/16 kHz (playback only)

amr

WAV

8 kHz/16 kHz

PCM

G711

How to record, play, and upload audio files:

  • Audio file recording

    // Create an audio file recorder.
    LVAudioFileRecorder recorder = new LVAudioFileRecorder(getApplicationContext());
    
    // Set the recorder listener.
    recorder.setRecorderListener(new ILVAudioFileRecorderListener() {
                @Override
                public void onRecordStart() {
                    appendLog("Recording starts.");
                    isRecording = true;
                }
    
                @Override
                public void onRecordEnd() {
                    appendLog("Recording ends.");
                    isRecording = false;
                }
    
                @Override
                public void onRecordVolume(int volume) {
                }
    
                @Override
                public void onError(LVAudioFileErrorCode code, String message) {
                    appendLog("Recording error: code:" + code + " msg:" + message);
                    isRecording = false;
                }
            });
    
    // Set the recording parameter configuration and start recording.
    File audioFile = new File(String.format("/sdcard/%d.amr", System.currentTimeMillis()));
    LVAudioFileCode code = recorder.startRecorder(AudioParams.AUDIOPARAM_MONO_8K_AMR, audioFile.getAbsolutePath());
    
    // Stop recording.
    recorder.stopRecorder();
    
    // Release recorder resources.
    recorder.release();
  • Audio file playback

    // Create an audio file player.
    LVAudioFilePlayer player = new LVAudioFilePlayer(getApplicationContext());
    
    // Set the player listener.
    player.setPlayerListener(new ILVAudioFilePlayerListener() {
            @Override
            public void onCompletion() {
                appendLog("Playback ends.");
            }
        });
    
    // Play a local file.
    LVAudioFileCode code = player.startPlay(LVAudioFileType.LV_AUDIO_FILE_TYPE_WAV, "/sdcard/test.wav");
    
    // Play a network file.
    LVAudioFileCode code = player.startPlay("https://link-vision-temp-sh.oss-cn-shanghai.aliyuncs.com/test.amr");
    
    // Stop playback.
    player.stopPlay();
    
    // Release player resources.
    player.release();
  • File upload

    // Create a file uploader.
    LVOSSUploader uploader = new LVOSSUploader(getApplicationContext());
    
    // Set the file upload listener.
    uploader.setOSSUploaderCallback(new ILVOSSUploaderListener() {
                @Override
                public void onError(String sessionId, String fileName, int code, String message) {
                    appendLog("Upload failed. sessionId=" + sessionId + " fileName=" + fileName + " code=" + code + " message=" + message);
                }
    
                @Override
                public void onProgress(long uploadBytes, long totalBytes) {
                    appendLog("Upload progress " + uploadBytes + "/" + totalBytes);
                }
    
                @Override
                public void onCompletion(String sessionId, String fileName) {
                    appendLog("Upload complete. sessionId=" + sessionId + " fileName=" + fileName);
                }
            });
    
    // Start upload.
    uploader.upload(audioFile.getAbsolutePath(), "test.wav", "123456", "https://oss.example.com/test.wav");
    
    // Release uploader resources.
    uploader.release();

Audio file error list

Error enumeration

Description

Solution

LV_AUDIO_FILE_ERROR_CREATE_FILE_FAILED

File creation failed.

Check if the file can be created and is writable.

LV_AUDIO_FILE_ERROR_INIT_AUDIO_RECORDER_FAILED

Recorder initialization error.

Check for and fix the following issues, and then retry:

  • Check if the recording permission is granted.

  • Check if another application is using the recorder. If so, stop the application process and retry.

LV_AUDIO_FILE_ERROR_START_AUDIO_RECORDER_FAILED

Recorder startup error.

Check if another application is using the recorder. If so, stop the application process and retry.

LV_AUDIO_FILE_ERROR_READ_AUDIO_RECORDER_FAILED

Recorder data read error.

The recorder is abnormal. Restart the application-side device, for example, by restarting the phone. This error is rare.

LV_AUDIO_FILE_ERROR_READ_FILE_FAILED

File read failed.

Check if the file exists and is readable.

LV_AUDIO_FILE_ERROR_INIT_AUDIO_TRACK_FAILED

Audio player creation failed.

The phone's audio player is abnormal. Restart the application or the phone. This error is rare.

Guide to migrating from SDK v1.x to v2.x

The Android Media SDK interfaces, methods, and classes were significantly changed in version 2.0.0. If you are using a version earlier than 2.0.0-ilop, we recommend that you upgrade to 2.0.0-ilop by following the instructions in this topic.

Note

For more information about the v1.x documentation, see LinkVisual Media SDK.

Important changes

Important change

v1.x

v2.x

Rendering component support

Supports both TextureView and GLSurfaceView components.

Only TextureView is provided. Support for GLSurfaceView is removed.

Live player

LivePlayer

Renamed to LVLivePlayer.

VOD player

The video-on-demand player for SD card recordings is VodPlayer.

Cloud recordings use HlsPlayer for playback.

The distinction between VOD for card recordings and cloud recordings is removed. Both are unified into `LVVodPlayer`, which automatically identifies the set data source and performs the necessary conversion.

Voice intercom

LiveIntercomV2

Renamed to LVLiveIntercom.

Upgrade steps

The Gradle integration method is similar to that of v1.x. You only need to modify the version number. The obfuscation configuration remains unchanged.

Note

Starting from v2.0.0, `linkvisual-media` no longer depends on ExoPlayer by default. To use ExoPlayer, you must add the following dependencies:

implementation('com.google.android.exoplayer:exoplayer-core:2.10.5')
implementation('com.google.android.exoplayer:exoplayer-ui:2.8.3')
implementation('com.google.android.exoplayer:exoplayer-hls:2.10.5')

You must also add the following to the obfuscation configuration:

-dontwarn com.google.android.exoplayer2.**

API change details (text search recommended)

Global components

Change details

1.x

2.x

Recommended change

Package and class name change

com.aliyun.iotx.linkvisual.media.LinkVisualMedia

com.aliyun.iotx.linkvisual.media.LVMedia

Update the package and class names.

Interface change: Live stream pre-connection

  1. void preConnectByIotId(final String iotId)

  2. void preConnectByIotId(final String iotId, int streamType)

LVPlayerCode preConnectByIotId(String iotId, LVStreamType streamType)

Modify the interface name.

Live player

Change details

1.x

2.x

Recommended change

Package and class name change

com.aliyun.iotx.linkvisual.media.video.player.LivePlayer

com.aliyun.iotx.linkvisual.media.player.LVLivePlayer

Update the package and class names.

The `decryptIv` and `decryptKey` parameters in the encrypted live data source settings are changed from Base64-decoded binary data to pre-decoded strings.

void setDataSource(String url, boolean isEncrypted, byte[] decryptIv, byte[] decryptKey)

LVPlayerCode setDataSource(String url, boolean isEncrypted, String decryptIvBase64, String decryptKeyBase64)

You no longer need to perform Base64 decoding. The SDK decodes the Base64 strings internally.

Interface name change: Set the live data source for an IPC device that is connected to IoT Platform.

  1. void setIPCLiveDataSource(String iotId, int streamType)

  2. void setIPCLiveDataSource(String iotId, int streamType, int cacheDurationInMs)

  1. LVPlayerCode setLiveDataSource(String iotId, LVStreamType streamType)

  2. LVPlayerCode setLiveDataSource(String iotId, LVStreamType streamType, int cacheDurationInMs)

In addition to the method name change, the second parameter, stream type, is changed from an `int` value to an enumeration for improved readability and maintenance.

Interface removal: Live data source for an IPC device connected to IoT Platform.

  1. void setIPCLiveDataSource(String iotId, int streamType, boolean relayEncrypted, int relayEncryptType, boolean forceIFrame)

  2. void setIPCLiveDataSource(String iotId, int streamType, boolean relayEncrypted, int relayEncryptType, boolean forceIFrame, int cacheDurationInMs)

-

In v2.0.0 and later, encryption and forced I-frames are mandatory.

Interface removal: `prepare` step removed.

  1. prepare()

  2. void setOnPreparedListener(OnPreparedListener listener)

  3. com.aliyun.iotx.linkvisual.media.video.listener.OnPreparedListener

-

After you set the data source, you no longer need to call `prepare()` before `start()`.

Command interfaces such as `setDataSource()`, `start()`, `stop()`, and `release()` now have return values.

-

Return value enumeration:

enum LVPlayerCode{
    /** Execution successful */
    LV_PLAYER_SUCCESS  = 0,
    /** Execution failed. General error. */
    LV_PLAYER_ERROR_FAILED  = -1,
    /** Invalid input parameter */
    LV_PLAYER_ERROR_INVALID_PARAMETER   = -2,
    /** Unsupported interface */
    LV_PLAYER_ERROR_UNSUPPORTED = -3,
};

You can check the return value to determine if the interface operation was successful.

New interface: Retrieve the width and height of the current stream.

-

  1. int getVideoWidth()

  2. int getVideoHeight()

-

Class name change: Decoder strategy and decoder type enumerations.

  1. com.aliyun.iotx.linkvisual.media.video.HardwareDecoderable.DecoderStrategy

  2. com.aliyun.iotx.linkvisual.media.video.HardwareDecoderable.DecoderType

  1. com.aliyun.iotx.linkvisual.media.player.bean.LVDecoderStrategy

  2. com.aliyun.iotx.linkvisual.media.player.bean.LVDecoderType

Update the class names.

Interface change: `setVolume` interface replaced with `mute` and `unmute` interfaces.

  1. void setVolume(float audioVolume)

  2. float getVolume()

  1. LVPlayerCode mute(boolean isMute)

  2. boolean isMute()

Individual in-app volume control is no longer supported. Volume is now controlled by the system.

New interface: Audio focus interface added.

-

  1. LVPlayerCode audioFocus()

  2. boolean isAudioFocus()

Starting from v2.0.0, the SDK no longer supports simultaneous playback of multiple audio streams. Only one audio stream can be played at a time. In multi-stream viewing scenarios, such as NVR multi-screen display, the user must call the `audioFocus()` method of the desired player to switch audio playback between players.

Interface removal: Audio playback stream channel setting interface removed.

void setAudioStreamType(final int streamType)

-

The live player always uses the `AudioManager.STREAM_MUSIC` channel and no longer supports switching.

Interface removal: Support for GLSurfaceView removed.

  1. void setSurfaceView(SurfaceView mSurfaceView)

  2. void clearSurfaceView()

-

Replace GLSurfaceView with TextureView. TextureView provides the following advantages over GLSurfaceView:

  1. Supports hardware acceleration and can be moved with the View without creating black bars.

  2. Supports digital zoom. You can use the `ZoomableTextureView` provided by the SDK.

  3. Supports multi-window playback.

Interface change: Video scaling mode setting interface parameter adjustment.

void setVideoScalingMode(int mVideoScalingMode)

LVPlayerCode setVideoScalingMode(LVVideoScalingMode videoScalingMode)

com.aliyun.iotx.linkvisual.media.player.bean.LVVideoScalingMode {
//Keep aspect ratio
LV_VIDEO_SCALING_MODE_FIT,
//Force fill
LV_VIDEO_SCALING_MODE_FILL;
}

Update the parameter name and class name.

Interface change: Record while playing.

  1. boolean startRecordingContent(File contentFile)

  2. boolean stopRecordingContent()

  3. long getCurrentRecordingContentDuration()

  1. LVPlayerCode startRecordingContent(String contentFilePath)

  2. LVPlayerCode stopRecordingContent()

  3. long getCurrentRecordingContentDurationInMs()

  1. The parameter type for starting recording is changed from `File` to `String`.

  2. The method name for retrieving the recording duration is adjusted.

Interface removal: Interface for setting display behavior when playback stops.

  1. void setPlayerStoppedDrawingMode(PlayerStoppedDrawingMode playerStoppedDrawingMode)

  2. PlayerStoppedDrawingMode getPlayerStoppedDrawingMode()

-

This feature is not supported in the current version but will be added in a future release.

Interface change: Get playback status interface.

int getPlayState()

  1. LVPlayerState getPlayerState()

  2. com.aliyun.iotx.linkvisual.media.player.bean.LVPlayerState

The player status is changed from an `int` to an enumeration for improved readability and maintenance.

Interface change: Get current stream connection type interface.

StreamConnectType getStreamConnectType()

  1. LVStreamConnectType getStreamConnectType()

  2. com.aliyun.iotx.linkvisual.media.player.bean.LVStreamConnectType

Update the class name.

Interface change: Get current playback frame rate/bitrate information interface.

PlayInfo getCurrentPlayInfo()

  1. LVPlayInfo getCurrentPlayInfo()

  2. com.aliyun.iotx.linkvisual.media.player.bean.LVPlayInfo

Update the class name.

Interface change: Set live player callback interface.

  1. void setOnRenderedFirstFrameListener(OnRenderedFirstFrameListener listener)

  2. void setOnErrorListener(OnErrorListener listener)

  3. void setOnPlayerStateChangedListener(OnPlayerStateChangedListener listener)

  4. void setOnVideoSizeChangedListener(OnVideoSizeChangedListener listener)

  5. void setOnVideoQualityListener(OnVideoQualityListener listener)

  6. void setOnSeiInfoListener(SeiInfoBuffer seiInfoBuffer, OnSeiInfoListener onSeiInfoListener)

LVPlayerCode setPlayerListener(ILVPlayerListener listener)

com.aliyun.iotx.linkvisual.media.player.listener.ILVPlayerListener {
    void onError(LVPlayerError error);
    void onPlayerStateChange(LVPlayerState state);
    void onRenderedFirstFrame(int elapsedTimeInMs);
    void onVideoSizeChanged(int width, int height);
    void onSeiInfoUpdate(byte[] buffer, int length, long timeStamp);    void onVideoJitterBufferEmpty();
}

Multiple listeners are merged into one.

Interface change: Set external rendering interface.

  1. void setUseExternalRender(boolean mUseExternalRender)

  2. void setOnExternalRenderListener

  3. boolean useExternalRender()

LVPlayerCode setUseExternalRender(boolean useExternalVideoRender, boolean useExternalAudioRender, ILVPlayerExternalRenderListener listener)

com.aliyun.iotx.linkvisual.media.player.listener.ILVPlayerExternalRenderListener {
    void onVideoFrameUpdate(int width, int height, long timestampInMs);
    void onAudioHeader(int audioBitPerSample, int audioSamplesPerSec, int audioChannel);
    boolean onAudioData(byte[] buffer, int offset, int length);
}

In v2.0.0 and later, audio PCM callbacks are supported in addition to video YUV data callbacks.

Interface change: Get one frame of YUV data interface.

Yuv420pFrame getYuvFrame()

Yuv420pFrame getYuv420pFrame()

Update the method name.

VOD player

Change details

1.x

2.x

Recommended change

Package and class name change

  1. com.aliyun.iotx.linkvisual.media.video.player.VodPlayer

  2. com.aliyun.iotx.linkvisual.media.video.player.HlsPlayer

com.aliyun.iotx.linkvisual.media.player.LVVodPlayer

Update the package and class names. In v2.0.0 and later, the SDK combines the VOD player for device recordings and the cloud storage player into a single player.

The `decryptIv` and `decryptKey` parameters in the encrypted VOD data source for device recordings are changed from Base64-decoded binary data to pre-decoded strings.

void setDataSource(String url, boolean isEncrypted, byte[] decryptIv, byte[] decryptKey)

LVPlayerCode setDataSource(String url, boolean isEncrypted, String decryptIvBase64, String decryptKeyBase64)

You no longer need to perform Base64 decoding. The SDK decodes the Base64 strings internally.

Interface name change: Set the playback address to the local recording file address of a specified recording name for an IPC device that is connected to IoT Platform.

  1. void setDataSourceByIPCRecordFileName(String iotId, String fileName)

  2. void setDataSourceByIPCRecordFileName(String iotId, String fileName, long seekToPositionInMs)

  1. LVPlayerCode setDataSourceByLocalRecordFileName(String iotId, String fileName)

  2. LVPlayerCode setDataSourceByLocalRecordFileName(String iotId, String fileName, long seekToPositionInMs)

Update the method name.

Interface removal: Set the playback address to the local recording file address of a specified recording name for an IPC device connected to IoT Platform.

void setDataSourceByIPCRecordFileName(String iotId, String fileName, boolean encrypted, int encryptType)

-

In v2.0.0 and later, encryption is mandatory. Therefore, the method that lets you disable encryption is removed.

Interface name change: Set the playback address to the local recording file address of a specified recording time range for an IPC device that is connected to IoT Platform.

  1. void setDataSourceByIPCRecordTime(String iotId, int beginTimeInS, int endTimeInS, long seekToPositionInMs)

  2. void setDataSourceByIPCRecordTime(String iotId, int beginTimeInS, int endTimeInS, long seekToPositionInMs, int recordType)

LVPlayerCode setDataSourceByLocalRecordTime(String iotId, int beginTimeInS, int endTimeInS, long seekToPositionInMs, int recordType)

Update the method name.

Interface removal: Set the playback address to the local recording file address of a specified recording time range for an IPC device connected to IoT Platform.

  1. void setDataSourceByIPCRecordTime(String iotId, int beginTimeInS, int endTimeInS, boolean encrypted, int encryptType, long seekToPositionInMs)

  2. void setDataSourceByIPCRecordTime(String iotId, int beginTimeInS, int endTimeInS, boolean encrypted, int encryptType, long seekToPositionInMs, int recordType)

-

In v2.0.0 and later, encryption is mandatory. Therefore, the method that lets you disable encryption is removed.

Interface name change: Set the playback address to the cloud recording file address of a specified recording name for an IPC device that is connected to IoT Platform.

  1. void setDataSourceByIPCRecordFileName(String iotId, String fileName)

  2. void setDataSourceByIPCRecordFileName(String iotId, String fileName, long seekToPositionInMs)

  1. LVPlayerCode setDataSourceByCloudRecordFileName(String iotId, String fileName)

  2. LVPlayerCode setDataSourceByCloudRecordFileName(String iotId, String fileName, long seekToPositionInMs)

Update the method name.

Interface removal: `prepare` step removed.

  1. prepare()

  2. void setOnPreparedListener(OnPreparedListener listener)

  3. com.aliyun.iotx.linkvisual.media.video.listener.OnPreparedListener

-

After you set the data source, you no longer need to call `prepare()` before `start()`.

Command interfaces such as `setDataSource()`, `start()`, `stop()`, and `release()` now have return values.

-

Return value enumeration:

enum LVPlayerCode{
    /** Execution successful */
    LV_PLAYER_SUCCESS  = 0,
    /** Execution failed. General error. */
    LV_PLAYER_ERROR_FAILED  = -1,
    /** Invalid input parameter */
    LV_PLAYER_ERROR_INVALID_PARAMETER   = -2,
    /** Unsupported interface */
    LV_PLAYER_ERROR_UNSUPPORTED = -3,
};

You can check the return value to determine if the interface operation was successful.

New interface: A separate method for resuming playback is added.

void start()

LVPlayerCode resume()

In SDK v2.0.0 and later, the `start()` method is no longer used to resume VOD playback.

Interface name change: Get VOD playback duration.

  1. long getDuration()

  2. long getCurrentPosition()

  1. long getDurationMs()

  2. long getCurrentPositionMs()

Update the method name.

New interface: Retrieve the width and height of the current stream.

-

  1. int getVideoWidth()

  2. int getVideoHeight()

-

Class name change: Decoder strategy and decoder type enumerations.

  1. com.aliyun.iotx.linkvisual.media.video.HardwareDecoderable.DecoderStrategy

  2. com.aliyun.iotx.linkvisual.media.video.HardwareDecoderable.DecoderType

  1. com.aliyun.iotx.linkvisual.media.player.bean.LVDecoderStrategy

  2. com.aliyun.iotx.linkvisual.media.player.bean.LVDecoderType

Update the class names.

Interface change: `setVolume` interface replaced with `mute` and `unmute` interfaces.

  1. void setVolume(float audioVolume)

  2. float getVolume()

  1. LVPlayerCode mute(boolean isMute)

  2. boolean isMute()

Individual in-app volume control is no longer supported. Volume is now controlled by the system.

New interface: Audio focus interface added.

-

  1. LVPlayerCode audioFocus()

  2. boolean isAudioFocus()

Starting from v2.0.0, the SDK no longer supports simultaneous playback of multiple audio streams. Only one audio stream can be played at a time. In multi-stream viewing scenarios, such as NVR multi-screen display, the user must call the `audioFocus()` method of the desired player to switch audio playback between players.

Interface removal: Audio playback stream channel setting interface removed.

void setAudioStreamType(final int streamType)

-

The VOD player always uses the `AudioManager.STREAM_MUSIC` channel and no longer supports switching.

Interface removal: Support for GLSurfaceView removed.

  1. void setSurfaceView(SurfaceView mSurfaceView)

  2. void clearSurfaceView()

-

Replace GLSurfaceView with TextureView. TextureView provides the following advantages over GLSurfaceView:

  1. Supports hardware acceleration and can be moved with the View without creating black bars.

  2. Supports digital zoom. You can use the `ZoomableTextureView` provided by the SDK.

  3. Supports multi-window playback.

Interface change: Video scaling mode setting interface parameter adjustment.

void setVideoScalingMode(int mVideoScalingMode)

LVPlayerCode setVideoScalingMode(LVVideoScalingMode videoScalingMode)

com.aliyun.iotx.linkvisual.media.player.bean.LVVideoScalingMode {
//Keep aspect ratio
LV_VIDEO_SCALING_MODE_FIT,
//Force fill
LV_VIDEO_SCALING_MODE_FILL;
}

Update the parameter name and class name.

Interface change: Record while playing.

  1. boolean startRecordingContent(File contentFile)

  2. boolean stopRecordingContent()

  3. long getCurrentRecordingContentDuration()

  1. LVPlayerCode startRecordingContent(String contentFilePath)

  2. LVPlayerCode stopRecordingContent()

  3. long getCurrentRecordingContentDurationInMs()

  1. The parameter type for starting recording is changed from `File` to `String`.

  2. The method name for retrieving the recording duration is adjusted.

Interface removal: Interface for setting display behavior when playback stops.

  1. void setPlayerStoppedDrawingMode(PlayerStoppedDrawingMode playerStoppedDrawingMode)

  2. PlayerStoppedDrawingMode getPlayerStoppedDrawingMode()

-

This feature is not supported in the current version but will be added in a future release.

Interface change: Get playback status interface.

int getPlayState()

  1. LVPlayerState getPlayerState()

  2. com.aliyun.iotx.linkvisual.media.player.bean.LVPlayerState

The player status is changed from an `int` to an enumeration for improved readability and maintenance.

Interface change: Get current stream connection type interface.

StreamConnectType getStreamConnectType()

  1. LVStreamConnectType getStreamConnectType()

  2. com.aliyun.iotx.linkvisual.media.player.bean.LVStreamConnectType

This is valid only for VOD playback of device recordings.

Interface change: Get current playback frame rate/bitrate information interface.

PlayInfo getCurrentPlayInfo()

  1. LVPlayInfo getCurrentPlayInfo()

  2. com.aliyun.iotx.linkvisual.media.player.bean.LVPlayInfo

Update the class name.

Interface change: Set VOD player callback interface.

  1. void setOnRenderedFirstFrameListener(OnRenderedFirstFrameListener listener)

  2. void setOnErrorListener(OnErrorListener listener)

  3. void setOnPlayerStateChangedListener(OnPlayerStateChangedListener listener)

  4. void setOnVideoSizeChangedListener(OnVideoSizeChangedListener listener)

  5. void setOnVideoQualityListener(OnVideoQualityListener listener)

  6. void setOnSeiInfoListener(SeiInfoBuffer seiInfoBuffer, OnSeiInfoListener onSeiInfoListener)

  7. void setOnCompletionListener(OnCompletionListener listener)

LVPlayerCode setPlayerListener(ILVPlayerListener listener)

com.aliyun.iotx.linkvisual.media.player.listener.ILVPlayerListener {
    void onError(LVPlayerError error);
    void onPlayerStateChange(LVPlayerState state);
    void onRenderedFirstFrame(int elapsedTimeInMs);
    void onVideoSizeChanged(int width, int height);
    void onSeiInfoUpdate(byte[] buffer, int length, long timeStamp);    void onVideoJitterBufferEmpty();
}

LVPlayerCode setVodCompletionListener(ILVVodPlayerCompletionListener listener)

com.aliyun.iotx.linkvisual.media.player.listener.ILVVodPlayerCompletionListener{
    void onCompletion();
}

Multiple listeners are merged into two.

Interface change: Set external rendering interface.

  1. void setUseExternalRender(boolean mUseExternalRender)

  2. void setOnExternalRenderListener

  3. boolean useExternalRender()

LVPlayerCode setUseExternalRender(boolean useExternalVideoRender, boolean useExternalAudioRender, ILVPlayerExternalRenderListener listener)

com.aliyun.iotx.linkvisual.media.player.listener.ILVPlayerExternalRenderListener {
    void onVideoFrameUpdate(int width, int height, long timestampInMs);
    void onAudioHeader(int audioBitPerSample, int audioSamplesPerSec, int audioChannel);
    boolean onAudioData(byte[] buffer, int offset, int length);
}

In v2.0.0 and later, audio PCM callbacks are supported in addition to video YUV data callbacks.

Interface change: Get one frame of YUV data interface.

Yuv420pFrame getYuvFrame()

Yuv420pFrame getYuv420pFrame()

Update the method name.

Voice intercom

Change details

1.x

2.x

Recommended change

Package and class name change

com.aliyun.iotx.linkvisual.media.audio.LiveIntercomV2

com.aliyun.iotx.linkvisual.media.liveintercom.LVLiveIntercom

Update the package and class names.

Interface change: Initialization interface.

LiveIntercomV2(Context context, final String iotId, final LiveIntercomMode liveIntercomMode, final AudioParams audioParams)

LVLiveIntercom(Context context, AudioParams audioParams)

Starting from SDK v2.0.0, the `iotId` and intercom mode are no longer passed in during the initialization phase. They are moved to the `start()` and `setLiveIntercomMode()` interfaces, respectively.

Command interfaces such as `start()`, `stop()`, and `release()` now have return values.

-

Return value enumeration:

LVLiveIntercomCode {
    //Execution successful
    LV_LIVE_INTERCOM_SUCCESS,
    //Execution failed. General error.
    LV_LIVE_INTERCOM_ERROR_FAILED,
    //Invalid input parameter
    LV_LIVE_INTERCOM_ERROR_INVALID_PARAMETER,
    //Unsupported interface
    LV_LIVE_INTERCOM_ERROR_UNSUPPORTED
}

You can check the return value to determine if the interface operation was successful.

New interface: New intercom mode added.

-

LVLiveIntercomCode setLiveIntercomMode(LVLiveIntercomMode liveIntercomMode)

Starting from SDK v2.0.0, the `DoubleTalkWithLive` mode is added: Both the app and the device capture and play audio simultaneously. The device must support AEC. Otherwise, this solution is not recommended. The audio from the device's live stream channel is used for playback. This requires an active live stream channel. You can call the `LVLivePlayer.audioFocus()` method to select the corresponding existing live stream channel before starting the intercom.

Interface change: Intercom with a specified device (by `iotId`).

void start()

LVLiveIntercomCode start(String iotId)

The `iotId` must be passed in.

Interface change: Intercom with a specified device (by URL).

void startWithExternalRequest(LiveIntercomRequest liveIntercomRequest)

LVLiveIntercomCode start(String url, String decryptIvBase64, String decryptKeyBase64)

Modify the interface name. Note that `decryptIvBase64` and `decryptKeyBase64` use Base64-encoded strings.

Interface change: Set intercom listener.

void setLiveIntercomV2Listener(LiveIntercomV2Listener listener)

LVLiveIntercomCode setLiveIntercomListener(ILVLiveIntercomListener listener)

ILVLiveIntercomListener {
    void onTalkReady();
    void onRecorderStart();
    void onRecorderEnd();
    void onRecorderVolume(int volume);
    void onError(LVLiveIntercomError error);
}

Modify the interface name.

Interface change: External voice changer implementation.

void setExternalVoiceChangeImpl(IVoiceChange voiceChangeImpl)

LVLiveIntercomCode setUseExternalVoiceChange(boolean useExternal, ILVLiveIntercomVoiceChangeListener listener)

ILVLiveIntercomVoiceChangeListener{
    boolean onAudioData(byte[] pcm, int length);    
}

Modify the interface name.

Interface change: Internal voice changer type setting.

void setVoiceChangeType(LiveIntercomVoiceType voiceType)

LVLiveIntercomCode setVoiceChangeType(LVLiveIntercomVoiceType liveIntercomVoiceType)

Modify the interface name.