Link Visual Video Media SDK

更新时间:
复制 MD 格式

The LinkVisual SDK for apps provides features such as audio and video playback and voice intercom.

Dependent SDK

Overview

API channel

Provides API channel capability

Initialization

For more information about initialization, see SDK initialization.

Pod integration

Add the following configuration to your Podfile and run the pod update command.

// 1. Add the source reference in Podfile
source 'https://github.com/aliyun/aliyun-specs.git'


// 2. Add library dependency
pod 'LinkVisualMedia', '2.7.5-ilop'

For more information about version releases, see LinkVisual SDK update history.

Project configuration

Change file extension from .m to .mm for C++ and Objective-C mixed compilation

Because part of the SDK is written in C++, you must perform mixed compilation with Objective-C. To ensure that the Clang compiler correctly identifies these files, change the file extension of any source file that references the SDK from .m to .mm. Otherwise, you may encounter an error similar to the following:

ios_error

Add -ObjC to your project's linker flags

Because the SDK static library uses categories, you must add this linker flag to prevent the "selector not recognized" compilation error. For more information, see https://developer.apple.com/library/archive/qa/qa1490/_index.html.

Swift support

In Swift projects, you can use a bridging header to call the LinkVisualMedia library. To do this, create a BridgingHeader file and add the following content.

//
// TestBridgingHeader.h
// swift-test
//
#define USE_SWIFT
#import "LinkVisualMedia/LVMedia.h"
#import "LinkVisualMedia/LVGlkView.h"
#import "LinkVisualMedia/LVLivePlayer.h"
#import "LinkVisualMedia/LVVodPlayer.h"
#import "LinkVisualMedia/LVLiveIntercom.h"
#import "LinkVisualMedia/LVAudioFilePlayer.h"
#import "LinkVisualMedia/LVAudioFileRecorder.h"
#import "LinkVisualMedia/LVOSSUploader.h"

API documentation

LinkVisual Media SDK documentation for iOS

Players

Video players are divided into three types based on their functionality.

  • Live player

    • Supports live playback from LinkVisual devices.

    • Features low playback latency.

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

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

    • Plays back local device recordings and lets you adjust the playback progress.

    • Provides P2P communication with devices.

  • VOD player for HLS cloud recordings

    • Plays back cloud recordings that are based on HTTP Live Streaming (HLS). This player supports MPEG-TS and fMP4 containers with AES-128 encryption.

Player feature comparison

Feature

Live player

VOD player (device recordings)

VOD player (HLS cloud recordings)

Video playback

Audio playback

Pause/resume

-

Playback reconnection

-

-

Seek to specific position

-

Total duration

-

Current playback progress

-

Player state change notification

Mute playback

Variable-speed playback

-

Frame-by-frame stepping

-

Set image scaling mode

Set display mode when playback stops

NVR multi-view playback

Digital zoom

Screenshot of the playback window

Save screenshot to file

Record while playing

Hardware decoding

Get stream information

Provide YUV data

Provide raw stream data

Provide SEI data

Player usage examples:

  • Live player

    // Create player instance
    self.player = [[LVLivePlayer alloc] init];
    // Set required delegates
    self.player.livePlayerDelegate = self;
    ...
    #pragma mark LVLivePlayerDelegate
    - (void) onLivePlayerError:(LVLivePlayer *_Nonnull)player error:(NSError *_Nonnull)error{
      [self appendInfoText:[NSString stringWithFormat:@"Playback error: %@\n", error]];
    }
    
    - (void) onLivePlayerStateChange:(LVLivePlayer *_Nonnull)player playerState:(LVPlayerState)state{
      [self appendInfoText:[NSString stringWithFormat:@"State changed: %d\n", state]];
    }
    
    - (void) onLivePlayerRenderedFirstFrame:(LVLivePlayer *_Nonnull)player elapsedTimeInMs:(NSInteger)elapsedTimeInMs{
      [self appendInfoText:[NSString stringWithFormat:@"First frame rendered in: %ldms\n", (long)elapsedTimeInMs]];
      [self appendInfoText:[self.player getStatisticsInfo]];
    }
    
    - (void) onLivePlayerVideoSizeChanged:(LVLivePlayer *_Nonnull)player width:(NSInteger)width height:(NSInteger)height{
      [self appendInfoText:[NSString stringWithFormat:@"Video size changed: w=%ld h=%ld\n", (long)width, (long)height]];
    }
    
    // Deprecated, will be removed
    - (void) onLivePlayerSeiInfoUpdate:(LVLivePlayer *_Nonnull)player sei:(NSData*_Nonnull)data timeStamp:(NSInteger)timeStamp{
        [self appendInfoText:[NSString stringWithFormat:@"Private SEI: %lu %ld %@", (unsigned long)data.length, timeStamp,[data description]]];
    }
    - (void) onLivePlayerStandardSeiInfoUpdate:(LVLivePlayer *_Nonnull)player sei:(NSData*_Nonnull)data timeStamp:(NSInteger)timeStamp{
        [self appendInfoText:[NSString stringWithFormat:@"Standard SEI: %lu %ld %@", (unsigned long)data.length, timeStamp,[data description]]];
    }
    
    - (void) onLivePlayerVideoJitterBufferEmpty:(LVLivePlayer *_Nonnull)player{
    }
    ...
    // Create LVGlkView with zoom capability inside scrollview
    self.lvGlkView = [[LVGlkView alloc] initWithFrame:CGRectMake(0,0,self.scrollView.frame.size.width, self.scrollView.frame.size.height)];;
    [self.scrollView addSubview:self.lvGlkView];
    [self.lvGlkView mas_makeConstraints:^(MASConstraintMaker *make) {
      make.centerX.equalTo(@(0));
      make.centerY.equalTo(@(0));
      make.height.equalTo(self.scrollView.mas_height);
      make.width.equalTo(self.scrollView.mas_width);
    }];
    // Set rendering view for player, no rotation applied
    [self.player setWindow:self.lvGlkView videoRotationMode:LV_MEDIA_VIDEO_ROTATE_90_CLOCKWISE];
    
    ...
    // Set data source using device IotId
    [self.player setLiveDataSource:iotId streamType:LV_STREAM_TYPE_MAJOR];
    // Set automatic reconnection attempts
    [self.player setReconnectCount:3];
    // Set decoder strategy to prefer hardware decoding
    [self.player setDecoderStrategy:LV_DECODER_STRATEGY_HARDWARE_FIRST];
    // Set video scaling mode to maintain aspect ratio
    [self.player setVideoScalingMode:LV_MEDIA_VIDEO_SCALING_MODE_FIT];
    // Keep last frame displayed when playback stops
    [self.player setPlayerStoppedDrawingMode:LV_PLAYER_STOPPED_DRAWING_MODE_ALWAYS_KEEP_LAST_FRAME];
    ...
    // Start playback
    [self.player start];
    ...
    // Stop playback
    [self.player stop];
  • VOD player for device recordings

    // Create player instance
    self.player = [[LVVodPlayer alloc] init];
    // Set required delegates
    self.player.vodPlayerDelegate = self;
    ...
    #pragma mark LVVodPlayerDelegate
    - (void) onVodPlayerError:(LVVodPlayer *_Nonnull)player error:(NSError *_Nonnull)error{
      [self appendInfoText:[NSString stringWithFormat:@"Playback error: %@\n", error]];
    }
    
    - (void) onVodPlayerStateChange:(LVVodPlayer *_Nonnull)player playerState:(LVPlayerState)state{
      [self appendInfoText:[NSString stringWithFormat:@"State changed: %d\n", state]];
    }
    
    - (void) onVodPlayerRenderedFirstFrame:(LVVodPlayer *_Nonnull)player elapsedTimeInMs:(NSInteger)elapsedTimeInMs{
      [self appendInfoText:[NSString stringWithFormat:@"First frame rendered in: %ldms\n", (long)elapsedTimeInMs]];
      [self appendInfoText:[self.player getStatisticsInfo]];
    }
    
    - (void) onVodPlayerVideoSizeChanged:(LVVodPlayer *_Nonnull)player width:(NSInteger)width height:(NSInteger)height{
      [self appendInfoText:[NSString stringWithFormat:@"Video size changed: w=%ld h=%ld\n", (long)width, (long)height]];
    }
    // Deprecated, will be removed
    - (void) onVodPlayerSeiInfoUpdate:(LVVodPlayer *_Nonnull)player sei:(NSData*_Nonnull)data timeStamp:(NSInteger)timeStamp{
        [self appendInfoText:[NSString stringWithFormat:@"Private SEI: %lu %ld %@", (unsigned long)data.length, timeStamp,[data description]]];
    }
    - (void) onVodPlayerStandardSeiInfoUpdate:(LVVodPlayer *_Nonnull)player sei:(NSData*_Nonnull)data timeStamp:(NSInteger)timeStamp{
        [self appendInfoText:[NSString stringWithFormat:@"Standard SEI: %lu %ld %@", (unsigned long)data.length, timeStamp,[data description]]];
    }
    
    - (void) onVodPlayerVideoJitterBufferEmpty:(LVLivePlayer *_Nonnull)player{
    }
    
    - (void)onVodPlayerCompletion:(LVVodPlayer * _Nonnull)player {
      [self appendInfoText:@"Playback completed"];
    }
    ...
    // Create LVGlkView with zoom capability inside scrollview
    self.lvGlkView = [[LVGlkView alloc] initWithFrame:CGRectMake(0,0,self.scrollView.frame.size.width, self.scrollView.frame.size.height)];;
    [self.scrollView addSubview:self.lvGlkView];
    [self.glkView mas_makeConstraints:^(MASConstraintMaker *make) {
      make.centerX.equalTo(@(0));
      make.centerY.equalTo(@(0));
      make.height.equalTo(self.scrollView.mas_height);
      make.width.equalTo(self.scrollView.mas_width);
    }];
    // Set rendering view for player
    [self.player setWindow:self.lvGlkView];
    
    ...
    // Set data source: both methods work
    // 1. By device filename, seek to 20 seconds
    [self.player setDataSourceByLocalRecordFileName:iotId fileName:@"fileNamexxxxxxxx" seekToPositionInMs:20000];
    // 2. By device time range (2022-08-29 17:54:14 to 2022-08-30 02:47:34), seek to 20 seconds, all recording types
    [self.player setDataSourceByLocalRecordTime:iotId beginTimeInS:1661766854 endTimeInS:1661798854 seekToPositionInMs:20000 recordType:99];
    // Set decoder strategy to prefer hardware decoding
    [self.player setDecoderStrategy:LV_DECODER_STRATEGY_HARDWARE_FIRST];
    // Set video scaling mode to maintain aspect ratio
    [self.player setVideoScalingMode:LV_MEDIA_VIDEO_SCALING_MODE_FIT];
    ...
    // Start playback
    [self.player start];
    ...
    // Pause
    [self.player pause];
    ...
    // Resume
    [self.player resume];
    ...
    // Stop playback
    [self.player stop];
  • VOD player for HLS cloud storage

    // Create player instance
    self.player = [[LVVodPlayer alloc] init];
    // Set required delegates
    self.player.vodPlayerDelegate = self;
    ...
    #pragma mark LVVodPlayerDelegate
    - (void) onVodPlayerError:(LVVodPlayer *_Nonnull)player error:(NSError *_Nonnull)error{
      [self appendInfoText:[NSString stringWithFormat:@"Playback error: %@\n", error]];
    }
    
    - (void) onVodPlayerStateChange:(LVVodPlayer *_Nonnull)player playerState:(LVPlayerState)state{
      [self appendInfoText:[NSString stringWithFormat:@"State changed: %d\n", state]];
    }
    
    - (void) onVodPlayerRenderedFirstFrame:(LVVodPlayer *_Nonnull)player elapsedTimeInMs:(NSInteger)elapsedTimeInMs{
      [self appendInfoText:[NSString stringWithFormat:@"First frame rendered in: %ldms\n", (long)elapsedTimeInMs]];
      [self appendInfoText:[self.player getStatisticsInfo]];
    }
    
    - (void) onVodPlayerVideoSizeChanged:(LVVodPlayer *_Nonnull)player width:(NSInteger)width height:(NSInteger)height{
      [self appendInfoText:[NSString stringWithFormat:@"Video size changed: w=%ld h=%ld\n", (long)width, (long)height]];
    }
    // Deprecated, will be removed
    - (void) onVodPlayerSeiInfoUpdate:(LVVodPlayer *_Nonnull)player sei:(NSData*_Nonnull)data timeStamp:(NSInteger)timeStamp{
        [self appendInfoText:[NSString stringWithFormat:@"Private SEI: %lu %ld %@", (unsigned long)data.length, timeStamp,[data description]]];
    }
    - (void) onVodPlayerStandardSeiInfoUpdate:(LVVodPlayer *_Nonnull)player sei:(NSData*_Nonnull)data timeStamp:(NSInteger)timeStamp{
        [self appendInfoText:[NSString stringWithFormat:@"Standard SEI: %lu %ld %@", (unsigned long)data.length, timeStamp,[data description]]];
    }
    
    - (void) onVodPlayerVideoJitterBufferEmpty:(LVLivePlayer *_Nonnull)player{
    }
    
    - (void)onVodPlayerCompletion:(LVVodPlayer * _Nonnull)player {
      [self appendInfoText:@"Playback completed"];
    }
    ...
    // Create LVGlkView with zoom capability inside scrollview
    self.lvGlkView = [[LVGlkView alloc] initWithFrame:CGRectMake(0,0,self.scrollView.frame.size.width, self.scrollView.frame.size.height)];;
    [self.scrollView addSubview:self.lvGlkView];
    [self.glkView mas_makeConstraints:^(MASConstraintMaker *make) {
      make.centerX.equalTo(@(0));
      make.centerY.equalTo(@(0));
      make.height.equalTo(self.scrollView.mas_height);
      make.width.equalTo(self.scrollView.mas_width);
    }];
    // Set rendering view for player
    [self.player setWindow:self.lvGlkView];
    
    ...
    // Set data source: cloud storage filename, seek to 20 seconds
    [self.player setDataSourceByCloudRecordFileName:iotId fileName:@"fileNamexxxxxxxx" seekToPositionInMs:20000];
    // Set decoder strategy to prefer hardware decoding
    [self.player setDecoderStrategy:LV_DECODER_STRATEGY_HARDWARE_FIRST];
    // Set video scaling mode to maintain aspect ratio
    [self.player setVideoScalingMode:LV_MEDIA_VIDEO_SCALING_MODE_FIT];
    ...
    // Start playback
    [self.player start];
    ...
    // Pause
    [self.player pause];
    ...
    // Resume
    [self.player resume];
    ...
    // Stop playback
    [self.player stop];

Player states

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

State change events are triggered by playback errors or when you manually stop playback.

播放器状态图

  • IDLE: The player has no content to play.

  • BUFFERING: The player is buffering and cannot play from the current position. This state occurs when playback starts, after a seekTo() operation, or because of poor network conditions during VOD playback.

  • READY: The player is actively playing content. This state is triggered after the first frame is rendered or after a seekTo() operation completes buffering. For VOD players, when the end of the file is reached, the onVodPlayerCompletion method of the LVVodPlayerDelegate is triggered, and the player automatically switches to the ENDED state.

  • ENDED: Playback has finished. This state is triggered by playback errors, after you call the stop() method, or when the end of the playback is reached.

Player error codes

Primary Error Code

Error subcode

Description

Solution

LV_PLAYER_ERROR_CODE_SOURCE

LV_PLAYER_ERROR_SUB_CODE_SOURCE_STREAM_CONNECT

Failed to connect to data source

This usually occurs due to network issues. Ensure your network connection is stable and retry.

LV_PLAYER_ERROR_SUB_CODE_SOURCE_INVALID_PARAMETER

Invalid data source parameters

Verify your configuration parameters are valid and retry.

LV_PLAYER_ERROR_SUB_CODE_SOURCE_QUERY_URL_FAILED

Failed to request playback URL

Check the msg field in the error message to identify and fix the issue.

LV_PLAYER_ERROR_CODE_RENDER

LV_PLAYER_ERROR_SUB_CODE_RENDER_DECODE

Decoding error

If decoding fails consistently, save the stream data for analysis. When log level is set to Debug, raw stream data is automatically saved to the app's tmp directory.

LV_PLAYER_ERROR_CODE_UNEXPECTED

LV_PLAYER_ERROR_SUB_CODE_UNEXPECTED_PULL_STREAM_TIMEOUT

No stream received for over 8 seconds or connection unexpectedly dropped

Check for the following issues and then retry: 1. The device is not ingesting a stream. 2. The network for the application or device is abnormal.

LV_PLAYER_ERROR_SUB_CODE_UNEXPECTED_PLAY_DURATION_EXCEED

Continuous playback duration exceeded limit

To prevent unnecessary bandwidth consumption from unattended playback, consider upgrading your traffic package if you need extended viewing sessions.

Voice intercom

This feature provides end-to-end simplex or duplex real-time intercom between your app and Internet Protocol Camera (IPC) devices.

  • Simplex: The app captures and sends audio to the device for playback. The app remains silent during audio capture.

  • Full-duplex: The app and the device simultaneously capture and play audio. The device must support Acoustic Echo Cancellation (AEC). Do not use this mode if the device does not support AEC.

  • Half-duplex: The app and the device handle audio capture and playback, but not simultaneously. This mode works like a walkie-talkie, where the app controls the start and stop of recording multiple times during a session. AEC support is not required on the device.

Supported audio formats:

Type

Sample rate

Encoding

Decoding

G711A

8Khz/16Khz

G711U

8Khz/16Khz

AAC_LC

8Khz/16Khz

Voice intercom usage:

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

        // Create voice intercom instance
      LVMediaAudioHeader header;
      header.audioBitPerSample = 16;
      header.audioChannel = 1;
      header.audioSamplesPerSec = 8000;
      header.audioEncType = LV_MEDIA_AUDIO_ENC_G711A;
      self.liveIntercom = [LVLiveIntercom create:header];
  2. Register delegates and handle voice intercom callbacks.

    You must handle events such as intercom ready, recording start and end, and volume changes for UI display.

    For information about possible errors during intercom setup and operation, see the voice intercom error list.

    self.liveIntercom.liveIntercomDelegate = self;
    self.liveIntercom.liveIntercomVoiceChangeDelegate = self;
    
    #pragma mark - LiveIntercomDelgate
    - (void) onLiveIntercomTalkReady:(LVLiveIntercom *_Nonnull)liveIntercom{
      [self appendInfoText:@"Ready to speak\n"];
    }
    
    - (void) onLiveIntercomRecorderStart:(LVLiveIntercom *_Nonnull)liveIntercom{
      [self appendInfoText:@"Recorder started\n"];
    }
    
    - (void) onLiveIntercomRecorderEnd:(LVLiveIntercom *_Nonnull)liveIntercom{
      [self appendInfoText:@"Recorder stopped\n"];
    }
    
    - (void) onLiveIntercomRecorderVolume:(LVLiveIntercom *_Nonnull)liveIntercom volume:(NSInteger)volume{
      [self appendInfoText:[NSString stringWithFormat:@"Volume changed: %ld\n", volume]];
    }
    
    - (void) onLiveIntercomError:(LVLiveIntercom *_Nonnull)liveIntercom error:(NSError *_Nonnull)error{
      [self appendInfoText:[NSString stringWithFormat:@"Intercom error: %@:\n", error]];
    }
  3. Set the gain level.

    You can set the microphone gain level on the app side. You can choose from six levels: -1 (None), 0 (Mild), 1 (Medium), 2 (High), 3 (Aggressive), 4 (Very Aggressive), and 5 (Max). The default value is None. You can adjust the gain level based on the device performance.

    [self.liveIntercom setGainLevel:-1];
  4. Set the intercom mode.

    You can choose from five modes:

    • Simplex: The app captures and sends audio to the device for playback. The app remains silent during audio capture.

    • Full-duplex (standalone): The app and the device simultaneously capture and play audio. The device must support AEC. The audio plays through the device's intercom channel and works independently without requiring a live stream.

    • Full-duplex (with live stream): The app and the device simultaneously capture and play audio. The device must support AEC. The audio plays through the device's live stream channel, which requires an active live stream. Before you start the intercom, call LVLivePlayer.audioFocus() to select the corresponding live stream.

    • Half-duplex (standalone): The app and the device handle audio capture and playback, but not simultaneously, similar to a walkie-talkie. The app controls the start and stop of recording multiple times during a session. The audio plays through the device's intercom channel and works independently without requiring a live stream. This mode requires device SDK v2.3.3 or later. Older versions fall back to the full-duplex mode.

    • Half-duplex (with live stream): The app and the device handle audio capture and playback, but not simultaneously, similar to a walkie-talkie. The app controls the start and stop of recording multiple times during a session. The audio plays through the device's live stream channel, which requires an active live stream. Before you start the intercom, call LVLivePlayer.audioFocus() to select the corresponding live stream. This mode requires device SDK v2.3.3 or later. Older versions fall back to the full-duplex mode.

    // Set standalone duplex mode
    [self.liveIntercom setLiveIntercomMode:LV_LIVE_INTERCOM_MODE_DOUBLE_TALK];
  5. Start the intercom.

    When the intercom starts, it requests audio focus and switches to call mode. In call mode, audio is routed to a Bluetooth or wired headset if one is connected.

    // Start intercom
    [self.liveIntercom start:iotId];
  6. Switch the talk/listen state (half-duplex only).

    After you start a half-duplex intercom, you must manually switch states to control audio capture and playback.

    // App stops playback, captures audio to send to device; device stops capturing and plays app's audio
    [self.liveIntercom listen:YES];
    ...
    // App resumes playback; device stops playback and resumes audio capture
    [self.liveIntercom listen:NO];
  7. Stop the intercom.

    After the intercom is stopped, audio focus is released and the normal mode is restored. Acoustic echo cancellation is enabled by default during the intercom.

    // Stop intercom
    [self.liveIntercom stop];

Voice intercom error codes

Fault enumeration

Description

Solution

LV_LIVE_INTERCOM_ERROR_START_REQUEST_FAILED

Failed to initiate voice intercom request. See subCode for details.

Check and fix the following issues, then retry:

  • Check for network failures.

  • Indicates whether the device is offline.

  • Check if the server is experiencing issues.

LV_LIVE_INTERCOM_ERROR_CONNECT_STREAM_FAILED

Failed to establish voice intercom stream channel

Check and fix the following issues, then retry:

  • Check for network failures.

  • Check whether the device timed out because it did not respond within 5 seconds.

LV_LIVE_INTERCOM_ERROR_SEND_STREAM_DATA_FAILED

Failed to send audio data

Network environment is unstable. Switch to a better network and retry.

LV_LIVE_INTERCOM_ERROR_RECEIVE_STREAM_DATA_FAILED

Failed to receive audio data

Network environment is unstable. Switch to a better network and retry.

LV_LIVE_INTERCOM_ERROR_INIT_AUDIO_RECORDER_FAILED

Audio recorder initialization failed

Check and fix the following issues, then retry:

  • Verify microphone permission is granted.

  • Check if another app is using the microphone. Terminate other apps and retry.

LV_LIVE_INTERCOM_ERROR_START_AUDIO_RECORDER_FAILED

Audio recorder startup failed

Check if another app is using the microphone. Terminate other apps and retry.

LV_LIVE_INTERCOM_ERROR_READ_AUDIO_RECORDER_FAILED

Audio recorder data read error

Audio recorder malfunction. Restart the device (e.g., reboot phone).

LV_LIVE_INTERCOM_ERROR_INIT_AUDIO_TRACK_FAILED

Audio player creation failed

Audio player malfunction. Restart the device (e.g., reboot phone).

Audio file recording, playback, and upload

This feature provides the capabilities to record audio files, play local or network audio files, and upload audio files.

The following audio formats are supported for recording and playback:

File type

Sample rate

Codec

AMR

8Khz (recording and playback)/16Khz (playback only)

amr

WAV

8Khz/16Khz

PCM

G711

Audio file recording, playback, and upload usage:

  • Audio file recording

    // Create audio file recorder
    self.audioFileRecorder = [[LVAudioFileRecorder alloc] init];
    
    // Set recording delegate
    self.audioFileRecorder.audioFileRecorderDelegate = self;
    
    #pragma mark - LVAudioFileRecorderDelegate
    - (void) onAudioFileRecorderError:(LVAudioFileRecorder *_Nonnull)recorder error:(NSError *_Nonnull)error{
      [self ims_showHUDWithMessage:[NSString stringWithFormat:@"AMR recording failed: %@", error]];
    }
    
    - (void) onAudioFileRecorderRecordStart:(LVAudioFileRecorder *_Nonnull)recorder{
      [self ims_showHUDWithMessage:@"AMR recording started"];
    }
    
    - (void) onAudioFileRecorderRecordEnd:(LVAudioFileRecorder *_Nonnull)recorder{
      [self ims_showHUDWithMessage:@"AMR recording finished"];
    }
    
    ...
    // Set recording parameters and start recording
    LVMediaAudioHeader header;
    header.audioBitPerSample = 16;
    header.audioChannel = 1;
    header.audioSamplesPerSec = 8000;
    header.audioEncType = LV_MEDIA_AUDIO_ENC_AMRNB;
    NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"test.amr"];
    [self.audioFileRecorder startRecorder:&header filePath:filePath];
    
    ...
    // Stop recording
    [self.audioFileRecorder stopRecorder];
  • Audio file playback

    // Create audio file player
    self.audioFilePlayer = [[LVAudioFilePlayer alloc] init];
    
    // Set playback delegate
    self.audioFilePlayer.audioFileplayerDelegate = self;
    
    #pragma mark - LVAudioFilePlayerDelegate
    - (void) onAudioFilePlayerCompletion:(LVAudioFilePlayer *_Nonnull)player{
      [self ims_showHUDWithMessage:@"AMR file playback completed"];
    }
    
    ...
    // Play local file
    NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"test.amr"];
    [self.audioFilePlayer startPlay:LV_AUDIO_FILE_TYPE_AMR filePath:filePath];
    
    // Play network file
    NSString *tmpPath = @"https://lv-demo.oss-cn-hangzhou.aliyuncs.com/test.amr";
    [self.audioFilePlayer startPlay:LV_AUDIO_FILE_TYPE_AMR filePath:tmpPath];
    
    // Stop playback
    [self.audioFilePlayer stopPlay];
  • File upload

    // Create file uploader
    self.ossUploader = [[LVOSSUploader alloc] init];
    
    // Set upload delegate
    self.ossUploader.OSSUploaderDelegate = self;
    
    #pragma mark - LVOSSUploaderDelegate
    - (void)
    onOSSUploaderError:(LVOSSUploader *_Nonnull)ossUploader sessionId:(NSString *_Nonnull)sessionId fileName:(NSString *_Nonnull)fileName error:(NSError*_Nonnull)error{
      [self ims_showHUDWithMessage:[NSString stringWithFormat:@"AMR file upload failed: %@", error]];
    }
    
    -(void) onOSSUploaderProgress:(LVOSSUploader *_Nonnull)ossUploader uploadBytes:(NSInteger)uploadBytes totalBytes:(NSInteger)totalBytes{
    }
    
    -(void) onOSSUploaderCompletion:(LVOSSUploader *_Nonnull)ossUploader sessionId:(NSString *_Nonnull)sessionId fileName:(NSString *_Nonnull)fileName{
      [self ims_showHUDWithMessage:@"AMR upload completed"];
    }
    
    - (void) onAudioFileRecorderRecordVolume:(LVAudioFileRecorder *_Nonnull)recorder volume:(NSInteger)volume{
    }
    
    ...
    // Start upload
    NSString *tmpPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"test.amr"];
    [self.ossUploader upload:tmpPath
           fileName:@"test.amr"
           sessionId:@"123456"
           uploadUrl:@"https://vision-customer-daily.oss-cn-hangzhou.aliyuncs.com/test.amr"];
                        

Audio file error codes

Enumerated faults

Description

Solution

LV_AUDIO_FILE_ERROR_CREATE_FILE_FAILED

File creation failed

Verify the file can be created and written to.

LV_AUDIO_FILE_ERROR_INIT_AUDIO_RECORDER_FAILED

Audio recorder initialization failed

Check and fix the following issues, then retry:

  • Check whether the recording permission is granted.

  • Check if another app is using the microphone. Terminate other apps and retry.

LV_AUDIO_FILE_ERROR_START_AUDIO_RECORDER_FAILED

Audio recorder startup failed

Check if another app is using the microphone. Terminate other apps and retry.

LV_AUDIO_FILE_ERROR_READ_AUDIO_RECORDER_FAILED

Audio recorder data read error

Audio recorder malfunction. Restart the device (e.g., reboot phone). This is rare.

LV_AUDIO_FILE_ERROR_READ_FILE_FAILED

File read failed

Verify the file exists and can be read.

LV_AUDIO_FILE_ERROR_INIT_AUDIO_TRACK_FAILED

Audio player creation failed

Audio player malfunction. Restart the app or device. This is rare.

Migration guide from 1.x SDK to 2.x

The iOS Media SDK v2.0.0 introduced significant changes to interfaces, methods, and classes. If you are using a version earlier than 2.0.0-ilop, you can use the methods that are provided in this guide to upgrade to v2.0.0-ilop.

Note

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

Key changes

Key change

1.x

2.x

Separate players and voice intercom

All player and intercom features were in IMSLinkVisualPlayerViewController

Split by functionality:

  • Live Streaming: LVLivePlayer

  • Video on Demand: LVVodPlayer

  • Voice intercom: LVLiveIntercom

Decouple players from ViewController

All player and intercom features were encapsulated in IMSLinkVisualPlayerViewController

No ViewController provided. Use LVGlkView interface instead.

Extract common gateway API requests

Encapsulated within SDK

Removed from SDK and provided as source code.

API changes (use text search to locate)

Global components

Change detail

1.x

2.x

Recommended Changes

New global LVMedia component

-

LVMedia

Update package and class names.

New API: Pre-connect for live streams

-

(LVPlayerCode) preConnectByIotId:(NSString *_Nonnull)iotId streamType:(LVStreamType)streamType;

Starting from 2.0.0, iOS supports live stream pre-connection.

New API: Set log level

-

(void) setLogLevel:(IMSLinkVisualMediaLogLevel)level;

Global log level setting API.

Live player

Change detail

1.x

2.x

Recommended changes

Package and class name changes

IMSLinkVisualPlayerViewController

LVLivePlayer

Update package and class names.

Player no longer provides ViewController

IMSLinkVisualPlayerViewController encapsulated GLKView for rendering

Player decoupled from rendering View

Create LVGlkView in your VC and call (LVPlayerCode) setWindow:(LVGlkView *_Nullable)view in viewDidAppear to assign it to the player.

New API: Set encrypted RTMP live stream URL

-

(LVPlayerCode) setDataSource:(NSString *_Nonnull)url

-

For encrypted live stream data source, decryptIv and decryptKey changed from Base64-decoded binary data to pre-decoder strings

(BOOL)setDataSource_Live:(NSString *_Nullable)rtmpPathneedEncrypt:(BOOL)needEncryptiv:(NSData *_Nullable)ivkey:(NSData *_Nullable)key;

(LVPlayerCode) setDataSource:(NSString *_Nonnull)url isEncrypted:(BOOL)isEncrypted decryptIvBase64:(NSString *_Nullable)decryptIvBase64 decryptKeyBase64:(NSString *_Nullable)decryptKeyBase64;

Remove Base64 decoding. The SDK handles Base64 string decoding internally.

API rename: Set IPC device live stream data source connected via IoT Platform

(BOOL)setDataSource:(NSString*_Nullable)iotIdstreamType:(IMSLinkVisualPlayerLiveStreamType)streamTypecacheDurationInMs:(int)cacheDurationInMs;

  1. (LVPlayerCode) setLiveDataSource:(NSString *_Nonnull)iotId streamType:(LVStreamType)streamType;

  2. (LVPlayerCode) setLiveDataSource:(NSString *_Nonnull)iotId streamType:(LVStreamType)streamType cacheDuration:(NSInteger)cacheDuration;

Updated API name.

API removed: IPC device live stream data source connected via IoT Platform

(BOOL)setDataSource:(NSString*_Nullable)iotIdstreamType:(IMSLinkVisualPlayerLiveStreamType)streamTypeneedForceIFrame:(BOOL)needForceIFrame __attribute__ ((deprecated));

-

Starting from 2.0.0, encryption and forced I-frame are mandatory.

Command APIs like setDataSource()/start()/stop() now return values

-

Return value enum:

enum LVPlayerCode{
    /** Success */
    LV_PLAYER_SUCCESS  = 0,
    /** General failure */
    LV_PLAYER_ERROR_FAILED  = -1,
    /** Invalid input parameter */
    LV_PLAYER_ERROR_INVALID_PARAMETER   = -2,
    /** Unsupported API */
    LV_PLAYER_ERROR_UNSUPPORTED = -3,
};

Check return values to determine if API operations succeeded.

New API: Get current stream width and height

-

  1. (NSInteger) getVideoWidth;

  2. (NSInteger) getVideoHeight;

-

Class and method name changes: Set decoder strategy and get decoder type

  1. (IMSLinkVisualPlayerDecodeMode)getDecoderStrategy;

  2. (BOOL)setDecoderStrategy:(IMSLinkVisualPlayerDecodeMode)decodeMode

  1. (LVPlayerCode) setDecoderStrategy:(LVDecoderStrategy)decoderStrategy;

  2. (LVDecoderType) getDecoderType;

Update class and method names.

API removed: P2P global initialization and release

  1. (void)initP2P;

  2. (void)deallocP2P;

-

No action needed.

API removed: Device P2P pre-connection

(void)preCreateP2P:(NSString*_Nonnull)iotId;

-

Starting from 2.0.0, use LVMedia's global preConnect API for pre-connection.

API removed: Stop all players

(void)stopAllPlayer;

-

Starting from 2.0.0, stop individual players directly. This API has alternatives and is no longer needed.

Property removed: Activate audio manager

activeAudioManager;

-

Starting from 2.0.0, since intercom and players are separated, recording permission is only triggered when using specific features. This property is obsolete.

API change: Audio focus

(void)activePlayer;

  1. (LVPlayerCode) audioFocus;

  2. (BOOL)isAudioFocus;

Starting from 2.0.0, the SDK supports at most one audio stream at a time. In multi-view scenarios (e.g., NVR multi-screen), call audioFocus() on the desired player to switch audio playback.

API rename: Set player buffer

  1. (void)setDisplayBuffer;

  2. (NSInteger)bufferCount;

  1. (LVPlayerCode) setBufferedFrameCount;

  2. (NSInteger)frameCount;

API renamed.

API rename: Set maximum jitter buffer duration

  1. (void)setMaxJitterBufferSizeInMs;

  2. (NSInteger)jitterBufferSizeInMs;

  1. (LVPlayerCode) setMaxJitterBufferSizeInMs;

  2. (NSInteger)jitterBufferSizeInMs;

API renamed.

API removed: Disable voice intercom in VC

(instancetype_Nonnull)initDisableIntercom;

-

Starting from 2.0.0, players and intercom are functionally separated and no longer coupled. This API is obsolete.

API rename: Screenshot

(UIImage * __nullable)videoSnapshot;

(UIImage *_Nullable) snapShot;

API renamed.

New API: Save screenshot to file

-

  1. (LVPlayerCode) snapShotToFile;

  2. (NSString *_Nonnull)jpegFilePath;

-

API rename: Record while playing

  1. (BOOL)startRecordVideoWithfilePath:(NSString *_Nullable)filePath;

  2. (BOOL)stopRecordVideo;

  3. (NSTimeInterval)getRecordMP4Duratio;

  1. (LVPlayerCode) startRecordingContent:(NSString *_Nonnull)contentFilePath;

  2. (LVPlayerCode) stopRecordingContent;

  3. (NSInteger) getCurrentRecordingContentDurationInMs;

API renamed.

Property Removed: Disable automatic resume when switching to the background.

cancelForeground

-

Starting from 2.0.0, since no ViewController is provided, background/foreground handling logic is removed. Handle this in your own ViewController as needed.

Property change: Frame rate/bitrate

  1. frameRate

  2. bitRate

(LVPlayInfo) getCurrentPlayInfo;

You can change the property to an interface.

Property change: Connection type

connectType

(LVStreamConnectType) getStreamConnectType;

Convert the property to an interface.

API change: Log level setting

(void)setLogLevel:(IMSLinkVisualMediaLogLevel)logLevel decodeLog:(bool)bShow;

[LVMedia getInstance] (void) setLogLevel:(IMSLinkVisualMediaLogLevel)level;

Starting from 2.0.0, use LVMedia's global setLogLevel API to set log level.

Property change: Mute

mute

  1. (LVPlayerCode) mute:(BOOL)isMute;

  2. (BOOL) isMute;

This has been changed from a property to an interface.

Property change: Set video scaling mode parameter adjustment

contentMode

(LVPlayerCode) setVideoScalingMode:(LVMediaVideoScalingMode)videoScalingMode;

LVVideoScalingMode{
// Maintain aspect ratio
LV_VIDEO_SCALING_MODE_FIT,
// Force fill
LV_VIDEO_SCALING_MODE_FILL;
}

Changed a property to an interface and modified the parameter and class names.

Property change: Player state

playerState

(LVPlayerState) getPlayerState;

As of version 2.0.0, the property is an interface and the iOS state machine has been updated. For more information, see the state diagram.

Delegate change: IMSLinkVisualDelegate

IMSLinkVisualDelegate

  1. LVLivePlayerDelegate

  2. LVLivePlayerExternalRenderDelegate

  1. Removed linkVisualConnect;

  2. linkVisualReady and linkVisualStop replaced by LVLivePlayerDelegate's onLivePlayerStateChange;

  3. linkVisual:withFrame replaced by LVLivePlayerExternalRenderDelegate's onLivePlayerVideoFrameUpdate;

  4. linkVisualResolutionChange replaced by LVLivePlayerDelegate's onLivePlayerVideoSizeChanged;

  5. linkVisual:frameRate bitRate removed; call APIs directly to get these values;

  6. linkVisualVideoJitterBufferEmpty replaced by LVLivePlayerDelegate's onLivePlayerVideoJitterBufferEmpty.

Property change: Set internal/external rendering mode

lvDisplayMode

(LVPlayerCode) setUseExternalRender;(BOOL)useExternalVideoRender useExternalAudioRender: (BOOL)useExternalAudioRender;

This property is now an interface that supports external video rendering and external audio playback.

New API: Get YUV frame data

-

  1. (LVPlayerCode) lockAndGetYuv420pFrame:(LVYuv420pFrame *_Nonnull)yuv420pFrame;

  2. (LVPlayerCode) unlockYuv420pFrame;

Custom rendering no longer returns data in callbacks. Retrieve data in the rendering thread instead.

Video-on-demand player

Change detail

1.x

2.x

Suggested Modifications

Package and class name changes

IMSLinkVisualPlayerViewController

LVVodPlayer

Update package and class names.

Player no longer provides ViewController

IMSLinkVisualPlayerViewController encapsulated GLKView for rendering

Player decoupled from rendering View

Create LVGlkView in your VC and call (LVPlayerCode) setWindow:(LVGlkView *_Nullable)view in viewDidAppear to assign it to the player.

New API: Set RTMP VOD and HLS VOD URLs as data source

-

(LVPlayerCode) setDataSource:(NSString *_Nonnull)url

-

For an encrypted live data source, the values of decryptIv and decryptKey have been changed from Base64-decoded binary data to Base64-encoded strings.

(BOOL)setDataSource_Vod:(NSString *_Nullable)rtmpPathneedEncrypt:(BOOL)needEncryptiv:(NSData *_Nullable)ivkey:(NSData *_Nullable)key;

(LVPlayerCode) setDataSource:(NSString *_Nonnull)url isEncrypted:(BOOL)isEncrypted decryptIvBase64:(NSString *_Nullable)decryptIvBase64 decryptKeyBase64:(NSString *_Nullable)decryptKeyBase64;

Remove Base64 decoding. The SDK handles Base64 string decoding internally.

API rename: Set IPC device recording VOD data source connected via IoT Platform

  1. (BOOL)setDataSource:(NSString*_Nullable)iotId vodFileName:(NSString*_Nullable)vodFileName;

  2. (BOOL)setDataSource:(NSString*_Nullable)iotId vodFileName:(NSString*_Nullable)vodFileName seekTime:(NSInteger)seekTime;

  3. (BOOL)setDataSource:(NSString*_Nullable)iotId vodStartTime:(NSInteger)vodStartTime vodEndTime:(NSInteger)vodEndTime seekTime:(NSInteger)seekTime;

  4. (BOOL)setDataSource:(NSString*_Nullable)iotId vodStartTime:(NSInteger)vodStartTime vodEndTime:(NSInteger)vodEndTime seekTime:(NSInteger)seekTime recordType:(NSInteger)recordType;

  1. (LVPlayerCode) setDataSourceByLocalRecordFileName:(NSString *_Nonnull)iotId fileName:(NSString *_Nonnull)fileName;

  2. (LVPlayerCode) setDataSourceByLocalRecordFileName:(NSString *_Nonnull)iotId fileName:(NSString *_Nonnull)fileName seekToPositionInMs:(NSInteger)seekToPositionInMs;

  3. (LVPlayerCode) setDataSourceByLocalRecordTime:(NSString *_Nonnull)iotId beginTimeInS:(NSInteger)beginTimeInS endTimeInS:(NSInteger)endTimeInS seekToPositionInMs:(NSInteger)seekToPositionInMs recordType:(NSInteger)recordType;

Updated API names.

API removed: IPC device recording VOD data source connected via IoT Platform

  1. (BOOL)setNoEncryptDataSource:(NSString*_Nullable)iotId vodFileName:(NSString*_Nullable)vodFileName;

  2. (BOOL)setNoEncryptDataSource:(NSString*_Nullable)iotId vodStartTime:(NSInteger)vodStartTime vodEndTime:(NSInteger)vodEndTime seekTime:(NSInteger)seekTime;

-

Starting from 2.0.0, encryption and forced I-frame are mandatory.

API rename: Set IPC device cloud storage VOD data source connected via IoT Platform

  1. (BOOL)setDataSource:(NSString*_Nullable)iotId hlsFileName:(NSString*_Nullable)hlsFileName seekTime:(NSTimeInterval)seekTime;

  2. (BOOL)setDataSource_HLS:(NSString *_Nullable)hlsPath seekTime:(NSTimeInterval)seekTime;

  1. (LVPlayerCode) setDataSourceByCloudRecordFileName:(NSString *_Nonnull)iotId fileName:(NSString *_Nonnull)fileName;

  2. (LVPlayerCode) setDataSourceByCloudRecordFileName:(NSString *_Nonnull)iotId fileName:(NSString *_Nonnull)fileName seekToPositionInMs:(NSInteger)seekToPositionInMs;

Updated API names.

Command APIs like setDataSource()/start()/stop() now return values

-

Return value enum:

enum LVPlayerCode{
    /** Success */
    LV_PLAYER_SUCCESS  = 0,
    /** General failure */
    LV_PLAYER_ERROR_FAILED  = -1,
    /** Invalid input parameter */
    LV_PLAYER_ERROR_INVALID_PARAMETER   = -2,
    /** Unsupported API */
    LV_PLAYER_ERROR_UNSUPPORTED = -3,
};

Check return values to determine if API operations succeeded.

API rename: Resume playback

restore

resume

Updated API name.

API rename: Frame-by-frame playback

nextFrame

playFrameByFrame

Updated API name.

API rename: Seek to specific time

seekToDuration

seekTo

Updated API name.

New API: Get current stream width and height

-

  1. (NSInteger) getVideoWidth;

  2. (NSInteger) getVideoHeight;

-

Class and method name changes: Set decoder strategy and get decoder type

  1. (IMSLinkVisualPlayerDecodeMode)getDecoderStrategy;

  2. (BOOL)setDecoderStrategy:(IMSLinkVisualPlayerDecodeMode)decodeMode

  1. (LVPlayerCode) setDecoderStrategy:(LVDecoderStrategy)decoderStrategy;

  2. (LVDecoderType) getDecoderType;

Update class and method names.

API removed: P2P global initialization and release

  1. (void)initP2P;

  2. (void)deallocP2P;

-

No action needed.

API removed: Device P2P pre-connection

(void)preCreateP2P:(NSString*_Nonnull)iotId;

-

Starting from 2.0.0, use LVMedia's global preConnect API for pre-connection.

API removed: Stop all players

(void)stopAllPlayer;

-

Starting from 2.0.0, stop individual players directly. This API has alternatives and is no longer needed.

Property removed: Activate audio manager

activeAudioManager;

-

Starting from 2.0.0, since intercom and players are separated, recording permission is only triggered when using specific features. This property is obsolete.

API change: Audio focus

(void)activePlayer;

  1. (LVPlayerCode) audioFocus;

  2. (BOOL)isAudioFocus;

Starting from 2.0.0, the SDK supports at most one audio stream at a time. In multi-view scenarios (e.g., NVR multi-screen), call audioFocus() on the desired player to switch audio playback.

API removed: Set player buffer

  1. (void)setDisplayBuffer;

  2. (NSInteger)bufferCount;

-

This API is only supported in live players. Removed from VOD players.

API removed: Set maximum jitter buffer duration

  1. (void)setMaxJitterBufferSizeInMs;

  2. (NSInteger)jitterBufferSizeInMs;

-

This API is only supported in live players. Removed from VOD players.

API removed: Disable voice intercom in VC

(instancetype_Nonnull)initDisableIntercom;

-

Starting from 2.0.0, players and intercom are functionally separated and no longer coupled. This API is obsolete.

API rename: Screenshot

(UIImage * __nullable)videoSnapshot;

(UIImage *_Nullable) snapShot;

API renamed.

New API: Save screenshot to file

-

  1. (LVPlayerCode) snapShotToFile;

  2. (NSString *_Nonnull)jpegFilePath;

-

API rename: Record while playing

  1. (BOOL)startRecordVideoWithfilePath:(NSString *_Nullable)filePath;

  2. (BOOL)stopRecordVideo;

  3. (NSTimeInterval)getRecordMP4Duratio;

  1. (LVPlayerCode) startRecordingContent:(NSString *_Nonnull)contentFilePath;

  2. (LVPlayerCode) stopRecordingContent;

  3. (NSInteger) getCurrentRecordingContentDurationInMs;

API renamed.

Attribute removed: Automatic resume on background switch

cancelForeground

-

Starting from 2.0.0, since no ViewController is provided, background/foreground handling logic is removed. Handle this in your own ViewController as needed.

Property change: Frame rate/bitrate

  1. frameRate

  2. bitRate

(LVPlayInfo) getCurrentPlayInfo;

You can change the property to an interface.

Property change: Connection type

connectType

(LVStreamConnectType) getStreamConnectType;

You can change the property to an interface.

API change: Log level setting

(void)setLogLevel:(IMSLinkVisualMediaLogLevel)logLevel decodeLog:(bool)bShow;

[LVMedia getInstance] (void) setLogLevel:(IMSLinkVisualMediaLogLevel)level;

Starting from 2.0.0, use LVMedia's global setLogLevel API to set log level.

Property change: Mute

mute

  1. (LVPlayerCode) mute:(BOOL)isMute;

  2. (BOOL) isMute;

This has been changed from a property to an interface.

Property change: Playback speed

playSpeed

(LVPlayerCode) setPlaybackSpeed:(float)speed;

The property was converted to an interface.

Property change: Total duration and current position

  1. duration

  2. currentDuration

  1. (NSInteger) getDurationMs;

  2. (NSInteger) getCurrentPositionMs;

The property was changed to an interface.

Property change: Set video scaling mode parameter adjustment

contentMode

(LVPlayerCode) setVideoScalingMode:(LVMediaVideoScalingMode)videoScalingMode;

LVVideoScalingMode{
// Maintain aspect ratio
LV_VIDEO_SCALING_MODE_FIT,
// Force fill
LV_VIDEO_SCALING_MODE_FILL;
}

Changed a property to an interface and renamed parameters and classes.

Property change: Player state

playerState

(LVPlayerState) getPlayerState;

Starting with version 2.0.0, the property has been changed to an interface and the state machine for iOS has been adjusted. For more information, see the state diagram.

Delegate change: IMSLinkVisualDelegate

IMSLinkVisualDelegate

  1. LVVodPlayerDelegate

  2. LVVodPlayerExternalRenderDelegate

  1. Removed linkVisualConnect;

  2. linkVisualReady, linkVisualStop, and linkVisualReplaySeekReady replaced by LVVodPlayerDelegate's onLivePlayerStateChange;

  3. linkVisual:withFrame replaced by LVVodPlayerExternalRenderDelegate's onVodPlayerVideoFrameUpdate;

  4. linkVisualResolutionChange replaced by LVVodPlayerDelegate's onVodPlayerVideoSizeChanged;

  5. linkVisual:frameRate bitRate removed; call APIs directly to get these values;

  6. linkVisualVideoJitterBufferEmpty replaced by LVVodPlayerDelegate's onVodPlayerVideoJitterBufferEmpty;

  7. Removed linkVisualRestore and linkVisualPause;

  8. linkVisualPlayEnd replaced by LVVodPlayerDelegate's onVodPlayerCompletion;

  9. linkVisualReplay:currentTime removed; call APIs directly to get this value.

Property change: Set internal/external rendering mode

lvDisplayMode

(LVPlayerCode) setUseExternalRender;(BOOL)useExternalVideoRender useExternalAudioRender: (BOOL)useExternalAudioRender;

The property is now an interface and supports external audio playback in addition to external video rendering.

New API: Get YUV frame data

-

  1. (LVPlayerCode) lockAndGetYuv420pFrame:(LVYuv420pFrame *_Nonnull)yuv420pFrame;

  2. (LVPlayerCode) unlockYuv420pFrame;

Custom rendering no longer returns data in callbacks. Retrieve data in the rendering thread instead.

Voice intercom

Change detail

1.x

2.x

Suggested Changes

Package and class name changes

IMSLinkVisualPlayerViewController

LVLiveIntercom

Update package and class names.

API change: Initialization

intercomEncodeParams

(id_Nonnull)create:(LVMediaAudioHeader)lvMediaAudioHeader;

Starting from SDK 2.0.0, audio parameters must be provided when creating the intercom instance.

API change:

  1. Intercom with specific device (by iotId)

  2. Intercom with specific device (by URL)

(void)startIntercom:(IMSLinkVisualIntercomAudioMode)mode;

  1. (LVLiveIntercomCode) start:(NSString *_Nonnull)url decryptIvBase64:(NSString *_Nonnull)decryptIvBase64 decryptKeyBase64:(NSString *_Nonnull)decryptKeyBase64;

  2. (LVLiveIntercomCode) start:(NSString *_Nonnull)iotId;

Starting from SDK 2.0.0, intercom mode is set using a separate API.

New API: Set intercom mode

-

(LVLiveIntercomCode) setLiveIntercomMode:(LVLiveIntercomMode)liveIntercomMode;

Starting from SDK 2.0.0, DoubleTalkWithLive mode is added: Both app and device simultaneously capture and play audio. The device must support AEC. Audio plays through the device's live stream channel, requiring an active live stream. Use LVLivePlayer.audioFocus() before starting intercom to select the corresponding live stream.

Command APIs like start()/stop() now return values

-

Return value enum:

enum LVPlayerCode{
    /** Success */
    LV_PLAYER_SUCCESS  = 0,
    /** General failure */
    LV_PLAYER_ERROR_FAILED  = -1,
    /** Invalid input parameter */
    LV_PLAYER_ERROR_INVALID_PARAMETER   = -2,
    /** Unsupported API */
    LV_PLAYER_ERROR_UNSUPPORTED = -3,
};

Check return values to determine if API operations succeeded.

New API: Mute

-

  1. (LVLiveIntercomCode) mute:(BOOL)isMute;

  2. (BOOL) isMute;

-

Property change: Gain and voice change

  1. gainLevel

  2. voiceChangeType

  1. (LVLiveIntercomCode) setGainLevel:(NSInteger)gainLevel;

  2. (LVLiveIntercomCode) setVoiceChangeType:(LVLiveIntercomVoiceType)liveIntercomVoiceType;

Properties changed to methods.

API removed: Send recorded audio data to device

(void)sendAudioData:(NSData *_Nullable)data;

-

Starting from 2.0.0, the SDK handles data transmission internally. This API is obsolete.

API change: Set intercom listener

intercomDelegate

LVLiveIntercomDelegate

  1. Removed linkVisualIntercomConnect;

  2. linkVisualIntercomReady replaced by onLiveIntercomTalkReady;

  3. Removed linkVisualIntercom:audioParams;

  4. Removed linkVisualIntercom:audioData;

  5. Removed linkVisualIntercom:recordData; use LVLiveIntercomVoiceChangeDelegate instead;

  6. linkVisualIntercomStop replaced by onLiveIntercomRecorderEnd;

  7. Added onLiveIntercomRecorderStart;

  8. linkVisualIntercom:errorOccurred replaced by onLiveIntercomError.

API change: External voice change implementation

Process audio before calling sendAudioData

  1. (LVLiveIntercomCode) setUseExternalVoiceChange:(BOOL)useExternal;

  2. LVLiveIntercomVoiceChangeDelegate

Enable external voice change and implement onLiveIntercomAudioData in the external intercom voice change delegate.