Este tópico descreve como usar os recursos avançados do ApsaraVideo Player SDK para iOS. Para obter um guia completo de todos os recursos, consulte a API.
Para testar o demo, baixe-o e siga as instruções em Executar o demo para compilá-lo e executá-lo.
Verificação de recursos avançados
Alguns recursos do player exigem uma licença da Professional Edition. Para mais informações, consulte Recursos. Para obter uma licença, veja Obter uma licença.
Defina o listener na inicialização do aplicativo ou antes de chamar qualquer API do player:
void premiumVeryfyCallback(AVPPremiumBizType biztype, bool isValid, NSString* errorMsg) {
NSLog(@"onPremiumLicenseVerifyCallback: %d, isValid: %d, errorMsg: %@", biztype, isValid, errorMsg);
}
[AliPrivateService setOnPremiumLicenseVerifyCallback:premiumVeryfyCallback];
Neste exemplo, AVPPremiumBizType é uma enumeração de recurso avançado. Ao utilizar um recurso avançado, o player verifica a licença e retorna o resultado por meio deste callback. Se isValid for falso, errorMsg conterá o motivo da falha.
Reprodução
Reprodução em lista
O Player SDK para iOS oferece um recurso abrangente de reprodução em lista para cenários de vídeos curtos. Ele utiliza técnicas como pré-carregamento para reduzir significativamente o Tempo até o Primeiro Quadro (TTTF).
Para uma experiência aprimorada de reprodução em lista, considere usar nossa solução para dramas curtos. Para detalhes, consulte Desenvolvimento client-side para dramas curtos.
Reproduzir vídeos com canal alfa
Visão geral
O ApsaraVideo Player SDK suporta renderização de canal alfa para criar efeitos dinâmicos, como presentes animados. Em uma sala de transmissão ao vivo, você pode reproduzir esses efeitos animados sobre o conteúdo principal para melhorar significativamente a experiência do usuário.
Limitações
A renderização de canal alfa é suportada no SDK all-in-one versão 6.8.0 ou posterior, ou no ApsaraVideo Player SDK versão 6.9.0 ou posterior.
Benefícios
Usar vídeos MP4 com canal alfa para efeitos animados oferece melhor qualidade de animação, tamanho de arquivo menor, maior compatibilidade e maior eficiência de desenvolvimento.
Melhor qualidade de animação: Vídeos MP4 preservam os detalhes e cores originais da animação com mais precisão do que outros formatos, como APNG ou IXD.
Tamanho de arquivo menor: Arquivos MP4 podem ser compactados de forma mais eficaz do que outros formatos como APNG ou IXD, o que melhora a velocidade de carregamento e reduz o consumo de largura de banda de rede.
Maior compatibilidade: Como formato de vídeo universal, o MP4 é amplamente suportado na maioria dos dispositivos e navegadores.
Maior eficiência de desenvolvimento: A implementação é simples e não exige que os desenvolvedores criem lógicas complexas de análise ou renderização. Isso permite que eles se concentrem em outros recursos.
Código de exemplo
Renderização Metal
O Alibaba Cloud Player SDK para iOS suporta renderização de vídeo usando o framework Metal.
Atualmente, a renderização Metal suporta apenas cor de fundo, modo de escala e Picture-in-Picture (PiP).
Parâmetro
/**
@brief Specifies the video render type. Valid values: 0 (default renderer) and 1 (mixed renderer). Default: 0.
*/
@property(nonatomic, assign) int videoRenderType;
Exemplo
AVPConfig *config = [self.player getConfig];
// Enable Metal rendering.
config.videoRenderType = 1;
[self.player setConfig:config];
[self.player prepare];
Legendas externas
Para um exemplo de código detalhado, consulte o módulo ExternalSubtitle no projeto API-Example. Este projeto de exemplo em Objective-C demonstra como integrar os recursos principais do ApsaraVideo Player SDK para iOS.
O ApsaraVideo Player SDK para iOS suporta a adição e alternância de legendas externas nos formatos SRT, SSA, ASS e VTT.
O exemplo a seguir mostra como implementar este recurso.
-
Crie uma view para exibir legendas.
Crie uma view baseada no formato da legenda.
// Initialize a custom subTitleLabel. UILabel *subTitleLabel = [[UILabel alloc] initWithFrame:frame]; // Add the subtitle label to a custom superView. [superView addSubview:subTitleLabel]; -
Configure os listeners relacionados às legendas.
// Called when an external subtitle track is added. - (void)onSubtitleExtAdded:(AliPlayer*)player trackIndex:(int)trackIndex URL:(NSString *)URL {} // Callback for the subtitle header. - (void)onSubtitleHeader:(AliPlayer *)player trackIndex:(int)trackIndex Header:(NSString *)header{} // Called when a subtitle is displayed. - (void)onSubtitleShow:(AliPlayer*)player trackIndex:(int)trackIndex subtitleID:(long)subtitleID subtitle:(NSString *)subtitle { subTitleLabel.text =subtitle; subTitleLabel.tag =subtitleID; } // Called when a subtitle is hidden. - (void)onSubtitleHide:(AliPlayer*)player trackIndex:(int)trackIndex subtitleID:(long)subtitleID{ [subTitleLabel removeFromSuperview]; } -
Adicione uma faixa de legenda.
[self.player addExtSubtitle:URL]; -
Alterne entre faixas de legenda.
[self.player selectExtSubtitle:trackIndex enable:YES];
Legendas externas (renderização personalizada)
Utilizando AliVttSubtitleView e AliVttRenderImpl, este recurso oferece suporte total a legendas externas WebVTT e permite personalizar estilos como fonte, cor e tamanho.
Casos de uso:
Você deseja personalizar os estilos das legendas WebVTT, como fonte, cor e tamanho.
Sua integração utiliza o Alibaba Cloud Player SDK v7.11.0 ou posterior e AliVttSubtitleView.
Suporta legendas multilíngues (como árabe, chinês, japonês e coreano) e corresponde automaticamente às fontes apropriadas.
Pré-requisitos:
Você adicionou os arquivos de fonte necessários (.ttf) ao seu projeto Xcode.
Você configurou um listener de legenda para receber conteúdo WebVTT.
As fontes necessárias foram carregadas chamando o método loadFontFromBundle.
Personalizar estilos de legenda
-
Crie uma classe de implementação de renderização personalizada que herde de AliVttRenderImpl.
// CustomFontVttRenderImpl.h @interface CustomFontVttRenderImpl : AliVttRenderImpl @end // CustomFontVttRenderImpl.m @implementation CustomFontVttRenderImpl // Optional: Override the font generation logic. - (UIFont *)customizeFont:(UIFont *)originalFont contentAttribute:(VttContentAttribute *)contentAttribute contentText:(NSString *)text { // Example: Automatically select a font based on the content. if ([self containsArabicCharacters:text]) { return [UIFont fontWithName:@"NotoSansArabic-Regular" size:originalFont.pointSize]; } if ([self containsCJKCharacters:text]) { return [UIFont fontWithName:@"NotoSansCJKsc-Regular" size:originalFont.pointSize]; } return originalFont; } // Optional: Force a specific color. - (void)applyColorStyle:(NSMutableDictionary *)attrs contentAttribute:(VttContentAttribute *)contentAttribute { // Force the color to red. attrs[NSForegroundColorAttributeName] = [UIColor redColor]; } // Optional: Enlarge the font. - (void)applyFontStyle:(NSMutableDictionary *)attrs contentAttribute:(VttContentAttribute *)contentAttribute context:(RenderContext *)context { CGFloat originalSize = contentAttribute.fontSizePx / context.contentsScale; CGFloat newSize = originalSize * 2.0; // Enlarge by 2x. UIFont *font = [self generateFontWithName:contentAttribute.fontName fontSize:newSize isBold:contentAttribute.mBold isItalic:contentAttribute.mItalic]; attrs[NSFontAttributeName] = font; } // Helper: Detect Arabic characters. - (BOOL)containsArabicCharacters:(NSString *)text { for (NSUInteger i = 0; i < text.length; i++) { unichar c = [text characterAtIndex:i]; if ((c >= 0x0600 && c <= 0x06FF) || (c >= 0x0750 && c <= 0x077F)) { return YES; } } return NO; } // Helper: Detect CJK characters. - (BOOL)containsCJKCharacters:(NSString *)text { for (NSUInteger i = 0; i < text.length; i++) { unichar c = [text characterAtIndex:i]; if ((c >= 0x4E00 && c <= 0x9FFF) || // Chinese (c >= 0x3040 && c <= 0x309F) || // Japanese Hiragana (c >= 0xAC00 && c <= 0xD7AF)) { // Korean return YES; } } return NO; } @end -
(Opcional) Carregue dinamicamente uma fonte personalizada.
- (void)loadCustomFontFromBundle:(NSString *)fontName { NSString *path = [[NSBundle mainBundle] pathForResource:fontName ofType:@"ttf"]; if (path) { NSData *fontData = [NSData dataWithContentsOfFile:path]; CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)fontData); CGFontRef fontRef = CGFontCreateWithDataProvider(provider); if (CTFontManagerRegisterGraphicsFont(fontRef, NULL)) { NSLog(@"Font registered successfully: %@", fontName); } else { NSLog(@"Font registration failed: %@", fontName); } CGFontRelease(fontRef); CGDataProviderRelease(provider); } } -
Inicialize a view de legenda e vincule o renderizador personalizado.
// Create the subtitle view. AliVttSubtitleView *subtitleView = [[AliVttSubtitleView alloc] init]; // Set the custom renderer factory. [subtitleView setRenderImplFactory:^AliVttRenderImpl*() { CustomFontVttRenderImpl *impl = [[CustomFontVttRenderImpl alloc] init]; // Optional: Preload a font. [impl loadCustomFontFromBundle:@"LongCang-Regular"]; return impl; }]; // Attach to the player. [player setExternalSubtitleView:subtitleView]; -
Trate os callbacks de legenda do player.
Implemente os seguintes métodos no seu AVPDelegate:
// Subtitle header (contains style and region definitions). - (void)onSubtitleHeader:(AliPlayer *)player trackIndex:(int)trackIndex Header:(NSString *)header { [self.subtitleView setVttHeader:player trackIndex:trackIndex Header:header]; } // Show the subtitle. - (void)onSubtitleShow:(AliPlayer *)player trackIndex:(int)trackIndex subtitleID:(long)subtitleID subtitle:(NSString *)subtitle { [self.subtitleView show:player trackIndex:trackIndex subtitleID:subtitleID subtitle:subtitle]; } // Hide the subtitle. - (void)onSubtitleHide:(AliPlayer *)player trackIndex:(int)trackIndex subtitleID:(long)subtitleID { [self.subtitleView hide:player trackIndex:trackIndex subtitleID:subtitleID]; } // Subtitle track added successfully. Use this callback to enable the track. - (void)onSubtitleExtAdded:(AliPlayer *)player trackIndex:(int)trackIndex URL:(NSString *)URL { [player selectExtSubtitle:trackIndex enable:YES]; }
Reprodução apenas de áudio
Para ativar a reprodução apenas de áudio, desative a faixa de vídeo. Configure o PlayerConfig antes de chamar prepare.
AVPConfig *config = [self.player getConfig];
config.disableVideo = YES;
[self.player setConfig:config];
Alternância de decodificador
O player SDK para iOS suporta decodificação de hardware para H.264 e H.265. Este recurso é ativado por padrão e controlado pela propriedade enableHardwareDecoder. Se a decodificação de hardware falhar ao inicializar, o player alternará automaticamente para a decodificação de software para garantir a continuidade da reprodução.
// Enable hardware decoding (enabled by default).
self.player.enableHardwareDecoder = YES;
Quando o player alterna automaticamente da decodificação de hardware para a de software, ele aciona o callback onPlayerEvent, conforme mostrado no exemplo a seguir:
-(void)onPlayerEvent:(AliPlayer*)player eventWithString:(AVPEventWithString)eventWithString description:(NSString *)description {
if (eventWithString == EVENT_SWITCH_TO_SOFTWARE_DECODER) {
// Switched to software decoding.
}
}
Reprodução adaptativa H.265
Se o modelo do dispositivo estiver na lista de bloqueios H.265 baseada em nuvem ou se a decodificação de hardware H.265 falhar, um fallback adaptativo será acionado. Se um stream de backup H.264 estiver configurado, o player o reproduzirá automaticamente. Caso contrário, o player recorrerá à decodificação de software H.265.
Este recurso está disponível apenas após ativar o serviço de decodificação adaptativa nativa da nuvem. Você precisará enviar um formulário Yida para solicitar uma licença.
O serviço de decodificação adaptativa nativa da nuvem fornece duas capacidades principais: 1. Entrega dinâmica de dados de compatibilidade de decodificação de hardware a partir da nuvem. 2. Fallback adaptativo de streams H.265 para H.264.
O SDK ainda pode alternar automaticamente para decodificação de software se a decodificação de hardware falhar, mesmo sem este serviço de valor agregado.
O exemplo a seguir mostra como definir um stream de backup:
// The application layer should maintain a dictionary to map original URLs to their backup URLs.
NSString* getBackupUrlCallback(AVPBizScene scene, AVPCodecType codecType, NSString* oriurl){
NSMutableDictionary *globalMap = [AliPlayerViewController getGlobalBackupUrlMap];
NSString *backupUrl = globalMap[oriurl];
return backupUrl;
}
[AliPlayerGlobalSettings setAdaptiveDecoderGetBackupURLCallback:getBackupUrlCallback];
Streaming de taxa de bits adaptativa
Você pode gerar streams adaptativos de múltiplas taxas de bits usando um grupo de modelos de empacotamento e transcodificação de vídeo no ApsaraVideo VOD. Para mais informações, consulte Configurar streaming de taxa de bits adaptativa para ApsaraVideo VOD.
-
Para reproduzir streams adaptativos do ApsaraVideo VOD com o método de reprodução VidAuth, defina a lista de definições como
AUTO. Caso contrário, o player selecionará um stream de baixa definição por padrão. Para mais informações sobre a ordem de reprodução padrão para definições, consulte Se um vídeo for transcodificado em várias definições, qual definição o ApsaraVideo Player SDK reproduz por padrão? O exemplo a seguir mostra como fazer isso:AVPVidAuthSource *authSource = [[AVPVidAuthSource alloc] init]; authSource.definitions = @"AUTO";
O ApsaraVideo Player SDK para iOS suporta streams adaptativos de múltiplas taxas de bits. Após o método prepare ser concluído com sucesso, você pode chamar o método getMediaInfo para obter o TrackInfo de cada stream.
AVPMediaInfo *info = [self.player getMediaInfo];
NSArray<AVPTrackInfo*>* tracks = info.tracks;
Durante a reprodução, você pode alternar streams chamando o método selectTrack do player. Para ativar o streaming de taxa de bits adaptativa, passe SELECT_AVPTRACK_TYPE_VIDEO_AUTO.
// Switch to a specific stream.
[self.player selectTrack:track.trackIndex];
// Enable adaptive bitrate streaming.
[self.player selectTrack:SELECT_AVPTRACK_TYPE_VIDEO_AUTO];
O callback onTrackChanged confirma a troca de stream.
- (void)onTrackChanged:(AliPlayer*)player info:(AVPTrackInfo*)info {
if (info.trackType == AVPTRACK_TYPE_VIDEO) {
// The video track has changed.
}
// etc
}
Opcional: Antes de chamar o método selectTrack para ativar o streaming de taxa de bits adaptativa, você pode limitar a definição do vídeo para evitar que o player alterne para uma taxa de bits inesperadamente alta. Aplique esta configuração antes de chamar o método prepare ou o método moveTo para reprodução em lista.
AVPConfig *config = [self.player getConfig];
config.maxAllowedAbrVideoPixelNumber = 921600; // Set the maximum pixel count for ABR to 921600 (1280 * 720). This ensures that the player only switches to definitions with a pixel count less than or equal to this value.
[self.player setConfig:config];
Snapshot
O Player SDK para iOS fornece um recurso para tirar um snapshot do vídeo atual. Este recurso é implementado pela API snapShot. Ele captura os dados brutos e os retorna como um bitmap. O callback é onCaptureScreen. Veja um exemplo abaixo:
// Snapshot callback
- (void)onCaptureScreen:(AliPlayer *)player image:(UIImage *)image {
// Process the snapshot.
}
// Take a snapshot of the current frame.
[self.player snapShot];
O snapshot exclui a interface do usuário.
Prévia
O ApsaraVideo Player SDK para iOS suporta um recurso de prévia quando configurado com o ApsaraVideo VOD. O SDK suporta reprodução tanto com VidSts quanto com VidAuth. VidAuth é o método recomendado. Para mais informações, consulte Prévia de vídeos.
Após configurar o recurso de prévia, use o método setPreviewTime da interface VidPlayerConfigGen para definir a duração da prévia para o player. O exemplo a seguir mostra a reprodução VidSts:
AVPVidStsSource *source = [[AVPVidStsSource alloc] init];
....
VidPlayerConfigGenerator* vp = [[VidPlayerConfigGenerator alloc] init];
[vp setPreviewTime:20]; // 20-second preview
source.playConfig = [vp generatePlayerConfig]; // Apply the configuration to the playback source.
...
Ao definir uma duração de prévia e usar o iOS player SDK para reproduzir um vídeo, o servidor retorna apenas o conteúdo de vídeo referente ao período de prévia, e não o conteúdo completo do vídeo.
Você pode usar a classe VidPlayerConfigGenerator para definir parâmetros de solicitação server-side. Para mais informações, consulte Descrições dos parâmetros de solicitação.
Definir Referer
O Player SDK para iOS permite definir o Referer para implementar controle de acesso. Este recurso funciona com a lista de bloqueios e a lista de permissões de Referer que você configura no console do ApsaraVideo VOD. Você pode definir o Referer no objeto AVPConfig, conforme mostrado no exemplo a seguir:
// Get the configuration.
AVPConfig *config = [self.player getConfig];
// Set the Referer.
config.referer = referer;
....// Other settings.
// Apply the configuration to the player.
[self.player setConfig:config];
User-Agent
O iOS player SDK fornece AVPConfig para definir um User-Agent personalizado, que o player então inclui em todas as solicitações de rede subsequentes. O exemplo a seguir mostra como fazer isso:
// Get the current configuration.
AVPConfig *config = [self.player getConfig];
// Set the User-Agent.
config.userAgent = userAgent;
//... other settings
// Apply the configuration to the player.
[self.player setConfig:config];
Configurar contagem de tentativas de rede e timeout
Para configurar o timeout de rede e o número de novas tentativas para o iOS player SDK, use o objeto AVPConfig. Por exemplo:
// Get the configuration.
AVPConfig *config = [self.player getConfig];
// Set the network timeout in milliseconds.
config.networkTimeout = 5000;
// Set the maximum number of retries. The retry interval is determined by networkTimeout. A value of 0 disables retries, allowing the application to implement its own retry policy. The default is 2.
config.networkRetryCount = 2;
//... Other settings
// Apply the configuration to the player.
[self.player setConfig:config];
Se
networkRetryCountfor maior que 0, o player tentará novamente aténetworkRetryCountvezes quando ocorrer um problema de rede durante o carregamento. O intervalo entre tentativas é determinado pornetworkTimeout.Se o player falhar ao carregar após todas as tentativas, o callback
onErrorserá acionado, e AVPErrorModel.code será ERROR_LOADING_TIMEOUT.Se
networkRetryCountfor 0, um timeout de rede acionará o callbackonPlayerEventcom o parâmetroeventWithStringdefinido comoEVENT_PLAYER_NETWORK_RETRY. Você pode então chamar o métodoreloaddo player para tentar novamente a solicitação de rede ou executar outras ações.
Controle de cache e latência
O controle de cache é crucial para o desempenho do player. Uma configuração adequada pode melhorar a velocidade de inicialização e reduzir travamentos. O Player SDK para iOS fornece interfaces para configurar definições de cache e latência no objeto AVPConfig:
// Retrieve the configuration.
AVPConfig *config = [self.player getConfig];
// The maximum latency in milliseconds. Note: This parameter is for live streaming only. If latency becomes high, the Player SDK synchronizes frames to keep it within this limit.
config.maxDelayTime = 5000;
// The maximum duration (in milliseconds) of data that the player can buffer.
config.maxBufferDuration = 50000;
// The high buffer duration in milliseconds. When network conditions are poor, the player stops loading data once the buffer reaches this duration.
config.highBufferDuration = 3000;
// The startup buffer duration in milliseconds. A smaller value results in a faster startup speed but may cause stuttering shortly after playback starts.
config.startBufferDuration = 500;
// Other settings.
// Apply the configuration to the player.
[self.player setConfig:config];
As durações de buffer devem satisfazer esta relação: startBufferDuration ≤ highBufferDuration ≤ maxBufferDuration.
Se a duração máxima do buffer (maxBufferDuration) exceder 5 minutos, o sistema impõe um limite de 5 minutos para evitar exceções de memória devido a um buffer excessivamente grande.
Definir cabeçalho HTTP
Use o objeto AVPConfig para adicionar cabeçalhos HTTP às solicitações do player:
// Get the configuration.
AVPConfig *config = [self.player getConfig];
// Define the headers.
NSMutableArray *httpHeaders = [[NSMutableArray alloc] init];
// For example, set the Host header when you use HTTPDNS.
[httpHeaders addObject:@"Host:example.com"];
// Set the headers.
config.httpHeaders = httpHeaders;
....// Other settings.
// Apply the configuration to the player.
[self.player setConfig:config];
Picture-in-picture
Consulte o módulo PictureInPicture no projeto API-Example para exemplos de código detalhados. Este projeto de exemplo em Objective-C demonstra como integrar os recursos principais do Alibaba Cloud Player SDK para iOS.
Picture in picture (PiP) requer iOS 15 ou posterior e ApsaraVideo Player SDK para iOS 5.4.9.0 ou posterior.
Versões do ApsaraVideo Player SDK para iOS anteriores à 5.5.2.0 fornecem apenas métodos para ativar ou desativar o PiP e exibir a janela PiP quando o aplicativo entra em segundo plano. A partir da versão 5.5.2.0, você também pode definir um delegate PiP externo para personalizar o comportamento do PiP.
Para usar o PiP, certifique-se de que ele esteja ativado nas configurações do seu dispositivo (Settings > General > Picture in Picture).
Ativar PiP
Depois de ativar o picture-in-picture, o vídeo continua sendo reproduzido em uma pequena janela quando o aplicativo entra em segundo plano. Quando o aplicativo retorna ao primeiro plano, o vídeo volta para sua view original. Para ativar o picture-in-picture, chame setPictureInPictureEnable depois que o player entrar no estado AVPEventPrepareDone. O exemplo a seguir mostra como fazer isso:
- (void)onPlayerEvent:(AliPlayer *)player eventType:(AVPEventType)eventType {
switch (eventType) {
case AVPEventPrepareDone:
{
[self.player setPictureInPictureEnable:YES];
}
break;
default:
break;
}
}
Chamar o método stop do player não fecha automaticamente a janela picture-in-picture. Portanto, você deve desativar o picture-in-picture chamando setPictureInPictureEnable antes de chamar stop.
Definir o delegate PiP
Os exemplos de código a seguir demonstram interações comuns entre as janelas Picture-in-Picture (PiP) e do player. Eles cobrem a exibição de controles de reprodução como pausa, play, avanço rápido e retrocesso, além da implementação da lógica de replay. Para uma referência completa dos métodos do delegate, consulte o arquivo de cabeçalho AliPlayerPictureInPictureDelegate.h, localizado em AliyunPlayer.framework dentro da pasta SDK do demo do player SDK.
-
Defina o delegate Picture-in-Picture.
/** * @brief Sets the delegate for Picture-in-Picture events. */ -(void) setPictureinPictureDelegate:(id<AliPlayerPictureInPictureDelegate>)delegate; // Set the Picture-in-Picture delegate. [self.player setPictureinPictureDelegate:self]; -
Adicione propriedades e implemente os métodos do delegate.
-
Adicione propriedades ao seu view controller para gerenciar o estado do player e da janela Picture-in-Picture.
#import "YourUIViewController.h" #import <AliyunPlayer/AliyunPlayer.h> @interface YourUIViewController () <AVPDelegate, AliPlayerPictureInPictureDelegate> // The player instance. @property (nonatomic, strong) AliPlayer *player; // The container view for the player. @property (nonatomic, strong) UIView *playerView; // Tracks whether the Picture-in-Picture window is paused. @property (nonatomic, assign) BOOL isPipPaused; // Tracks the current playback status of the player, updated by the onPlayerStatusChanged:oldStatus:newStatus: callback. @property (nonatomic, assign) AVPStatus currentPlayerStatus; // A weak reference to the picture-in-picture controller. This is set in the pictureInPictureControllerWillStartPictureInPicture: callback and should be set to nil before the view controller is deallocated. Using a weak reference is recommended. @property (nonatomic, weak) AVPictureInPictureController *pipController; // Tracks playback progress, updated by the 'position' parameter in the playback progress callback. @property (nonatomic, assign) int64_t currentPosition; @endNotaA propriedade
pipControllerdeve ser declarada com um atributoweakouassignpara evitar ciclos de retenção. Se você usarassign, defina manualmente a propriedade comonilno momento apropriado. -
No seu método delegate
onPlayerStatusChanged:, notifique o controlador picture-in-picture para atualizar seu estado.- (void)onPlayerStatusChanged:(AliPlayer*)player oldStatus:(AVPStatus)oldStatus newStatus:(AVPStatus)newStatus { self.currentPlayerStatus = newStatus; if (_pipController) { [self.pipController invalidatePlaybackState]; } } -
No seu método delegate
onPlayerEvent:, atualize o estado do Picture-in-Picture em resposta aos eventos de reprodução.- (void)onPlayerEvent:(AliPlayer*)player eventType:(AVPEventType)eventType { if (eventType == AVPEventCompletion) { if (_pipController) { self.isPipPaused = YES; // When playback finishes, set the PiP state to paused. [self.pipController invalidatePlaybackState]; } } else if (eventType == AVPEventSeekEnd) { // The seek operation is complete. if (_pipController) { [self.pipController invalidatePlaybackState]; } } } -
Implemente os métodos do delegate.
-
Implemente o callback para quando o Picture-in-Picture estiver prestes a começar.
/** @brief Tells the delegate that Picture-in-Picture is about to start. @param pictureInPictureController The picture-in-picture controller. */ - (void)pictureInPictureControllerWillStartPictureInPicture:(AVPictureInPictureController *)pictureInPictureController { if (!_pipController) { self.pipController = pictureInPictureController; } self.isPipPaused = !(self.currentPlayerStatus == AVPStatusStarted); [pictureInPictureController invalidatePlaybackState]; } -
Implemente o callback para quando o Picture-in-Picture estiver prestes a parar.
/** @brief Tells the delegate that Picture-in-Picture is about to stop. @param pictureInPictureController The picture-in-picture controller. */ - (void)pictureInPictureControllerWillStopPictureInPicture:(AVPictureInPictureController *)pictureInPictureController { self.isPipPaused = NO; [pictureInPictureController invalidatePlaybackState]; } -
Implemente o callback para restaurar a UI antes que o Picture-in-Picture pare.
/** @brief Tells the delegate to restore the user interface before Picture-in-Picture stops. @param pictureInPictureController The picture-in-picture controller. @param completionHandler A completion handler to call with YES to allow the system to complete the restoration. */ - (void)pictureInPictureController:(AVPictureInPictureController *)pictureInPictureController restoreUserInterfaceForPictureInPictureStopWithCompletionHandler:(void (^)(BOOL restored))completionHandler { if (_pipController) { _pipController = nil; } completionHandler(YES); } -
Implemente o callback que fornece o intervalo de tempo reproduzível.
/** @brief Asks the delegate for the current playable time range. @param pictureInPictureController The picture-in-picture controller. @return The current playable time range. */ - (CMTimeRange)pictureInPictureControllerTimeRangeForPlayback:(nonnull AVPictureInPictureController *)pictureInPictureController layerTime:(CMTime)layerTime{ Float64 current64 = CMTimeGetSeconds(layerTime); Float64 start; Float64 end; if (currentPosition <= self.player.duration) { double curPostion = self.currentPosition / 1000.0; double duration = self.player.duration / 1000.0; double interval = duration - curPostion; start = current64 - curPostion; end = current64 + interval; CMTime t1 = CMTimeMakeWithSeconds(start, layerTime.timescale); CMTime t2 = CMTimeMakeWithSeconds(end, layerTime.timescale); return CMTimeRangeFromTimeToTime(t1, t2); } else { return CMTimeRangeMake(kCMTimeNegativeInfinity, kCMTimePositiveInfinity); } } -
Implemente o callback que informa se a reprodução está pausada.
/** @brief Asks the delegate whether playback is currently paused. @param pictureInPictureController The picture-in-picture controller. @return A Boolean value indicating whether playback is paused. */ - (BOOL)pictureInPictureControllerIsPlaybackPaused:(nonnull AVPictureInPictureController *)pictureInPictureController{ return self.isPipPaused; }NotaEste callback é invocado antes do início do Picture-in-Picture. Ele deve retornar
falseneste ponto para que a janela PiP seja iniciada. Retornartrueimpede o início do Picture-in-Picture. -
Implemente o callback para lidar com as ações de avançar e retroceder a partir dos controles do Picture-in-Picture.
/** @brief Tells the delegate that the user has requested to skip forward or backward. @param pictureInPictureController The picture-in-picture controller. @param skipInterval The time interval to skip. @param completionHandler A completion handler that you must call after the seek operation is complete. */ - (void)pictureInPictureController:(nonnull AVPictureInPictureController *)pictureInPictureController skipByInterval:(CMTime)skipInterval completionHandler:(nonnull void (^)(void))completionHandler { int64_t skipTime = skipInterval.value / skipInterval.timescale; int64_t skipPosition = self.currentPosition + skipTime * 1000; if (skipPosition < 0) { skipPosition = 0; } else if (skipPosition > self.player.duration) { skipPosition = self.player.duration; } [self.player seekToTime:skipPosition seekMode:AVP_SEEKMODE_INACCURATE]; [pictureInPictureController invalidatePlaybackState]; } -
Implemente o callback para lidar com as ações de play e pause a partir dos controles do Picture-in-Picture.
/** @brief Tells the delegate that the user has toggled the play/pause button. @param pictureInPictureController The picture-in-picture controller. @param playing A Boolean value indicating whether playback should start. */ - (void)pictureInPictureController:(nonnull AVPictureInPictureController *)pictureInPictureController setPlaying:(BOOL)playing { if (!playing){ [self.player pause]; self.isPipPaused = YES; } else { // Tip: If you want the play button to restart the video after playback completes, add the following block. if (self.currentPlayerStatus == AVPStatusCompletion) { [self.player seekToTime:0 seekMode:AVP_SEEKMODE_ACCURATE]; } [self.player start]; self.isPipPaused = NO; } [pictureInPictureController invalidatePlaybackState]; }
-
-
Picture-in-picture no aplicativo
O Picture-in-picture é externo ao aplicativo por padrão. Para implementar o picture-in-picture dentro do aplicativo, primeiro chame a seguinte interface para verificar se o picture-in-picture está ativo:
/**
@brief Tells the delegate whether picture-in-picture is enabled.
@param pictureInPictureController The picture-in-picture controller reporting its state.
@param isEnable `YES` if picture-in-picture is enabled; `NO` otherwise.
*/
- (void)pictureInPictureControllerIsPictureInPictureEnable:(nullable AVPictureInPictureController *)pictureInPictureController isEnable:(BOOL)isEnable;
Para desativar a inicialização automática e mudar para a ativação manual enquanto o picture-in-picture está em execução, use o seguinte código de exemplo:
- (void) pictureInPictureControllerIsPictureInPictureEnable:(nullable AVPictureInPictureController *) pictureInPictureController isEnable:(BOOL) isEnable
{
if (isEnable && pictureInPictureController) {
_pipController = pictureInPictureController;
// Disable pip auto-start.
if (@available(iOS 15.0, *)) {
_pipController.canStartPictureInPictureAutomaticallyFromInline = false;
}
} else {
_pipController = NULL;
}
}
- (void) switchPip:(bool) enable {
if (_pipController == nil) {
return;
}
if (enable) {
// Start pip.
[_pipController startPictureInPicture];
} else {
// Stop pip.
[_pipController stopPictureInPicture];
}
}
Fallback RTS ao vivo
Para exemplos de código detalhados, consulte o módulo RtsLiveStream em API-Example. Este projeto de exemplo em Objective-C mostra como integrar os recursos principais do Alibaba Cloud Player SDK para iOS.
Para mais informações, consulte Reprodução ao vivo RTS.
Alternar canais de áudio
Use a propriedade outputAudioChannel para definir o canal de áudio de saída. Se a fonte de entrada for um canal estéreo, você pode alternar a saída para o canal de áudio esquerdo ou direito. Esta configuração não tem efeito se a fonte de entrada for um canal mono.
A configuração do canal de áudio de saída afeta tanto a renderização de áudio quanto o callback de dados PCM.
// Set the output audio channel using an AVPOutputAudioChannel enumeration value.
// AVP_AUDIO_CHANNEL_NONE: Plays the original audio channels from the input source. This is the default value.
// AVP_AUDIO_CHANNEL_LEFT: Plays only the left audio channel.
// AVP_AUDIO_CHANNEL_RIGHT: Plays only the right audio channel.
self.player.outputAudioChannel = AVP_AUDIO_CHANNEL_NONE;
Definir a cor de fundo do vídeo
O Player SDK para iOS permite definir a cor de fundo da view de renderização.
Exemplo de API
/**
@brief
@param color the color
*/
/****
@brief Sets the video background color.
@param color The background color.
*/
-(void) setVideoBackgroundColor:(UIColor *)color;
Uso
// The parameter is an 8-digit hexadecimal value in ARGB format (alpha, red, green, blue).
// For example, 0x0000ff00 represents green.
[self.player setVideoBackgroundColor:0x0000ff00]
Especificar um domínio de reprodução com VidAuth
Use o método VidAuth para especificar campos, como o domínio de reprodução, associados a um ID de vídeo (vid). Para obter uma lista de campos suportados, consulte Parâmetros de solicitação GetPlayInfo.
Exemplo de API
/**
@brief Play a video by using the video ID and playback credential (PlayAuth). For more information, see: https://www.alibabacloud.com/help/en/vod/user-guide/use-playback-credentials-to-play-videos
@param source An AVPVidAuthSource object.
@see AVPVidAuthSource
*/
- (void)setAuthSource:(AVPVidAuthSource*)source;
Uso
Use o método addVidPlayerConfigByStringValue da interface VidPlayerConfigGenerator para adicionar o campo playDomain.
VidPlayerConfigGenerator* gen = [[VidPlayerConfigGenerator alloc]init];
// Add the playDomain field. For a list of supported fields, see:
// https://www.alibabacloud.com/help/en/vod/developer-reference/api-vod-2017-03-21-getplayinfo
[gen addVidPlayerConfigByStringValue:@"playDomain" value: @"com.example.xxx"];
[source setPlayConfig:[gen generatePlayerConfig]];
[self.player setAuthSource:source]:
Decodificação em segundo plano
Desde a versão 6.12.0, o player SDK suporta decodificação em segundo plano. Ativar este recurso permite que o player continue a decodificar e reproduzir streams de vídeo, além de acionar callbacks enquanto o aplicativo é executado em segundo plano. O exemplo a seguir mostra como ativar este recurso:
// Set to 1 to enable background decoding or 0 to disable it. Default: 0.
[self.player setOption:ALLOW_DECODE_BACKGROUND valueInt:1];
Plugin de decodificação H.266
H.266, também conhecido como Versatile Video Coding (VVC), é um padrão de codificação de vídeo de próxima geração que oferece a mesma qualidade visual com uma taxa de bits significativamente menor. Para otimizar o desempenho e controlar o tamanho do SDK principal, o decodificador H.266 é fornecido como um plugin separado que você pode integrar sob demanda.
Pré-requisitos
Player SDK ou all-in-one SDK V7.6.0 ou posterior.
Você possui uma licença da Professional Edition. Para mais informações, consulte Obter uma licença.
O plugin de decodificação H.266 para o Player SDK suporta apenas vídeos H.266 transcodificados pela Transcodificação Alibaba Cloud.
Integrar o plugin
Ativar o plugin
A partir do Player SDK para iOS v7.7.0, o plugin é ativado por padrão e não requer ativação manual.
[AliPlayerGlobalSettings enableCodecPlugin:@"vvc" valid:true];
Códigos de erro
Para códigos de erro do plugin de decodificação H.266, consulte FAQ do ApsaraVideo Player SDK.
Atualizar automaticamente a fonte
Ative a atualização automática de fonte para evitar interrupções na reprodução devido à expiração da autenticação. Quando uma fonte expira, o player aciona um callback para obter uma nova, garantindo uma reprodução contínua e suave.
Pré-requisitos
O player ou SDK integrado deve ser da versão 7.9.0 ou posterior.
Use uma fonte VidAuth para reprodução ou tenha a assinatura de URL configurada.
Fonte VidAuth
Exemplo de API
/**
@brief Sets the callback for VidAuth source expiration notifications.
This callback is triggered when the player detects that the current VidAuth source has expired. A VidAuth source expires if its PlayAuth or playback URL has expired.
You can refresh the VidAuth source in this callback and pass the new object via the `callback` parameter to ensure smooth playback.
@param callback The callback block triggered when the VidAuth source expires.
Use this callback to update the player with a valid `VidAuth` object.
*/
-(void)setOnVidAuthExpiredCallback:(void (^)(id expiredSource, id<AVPSourceRefreshCallback> callback))callback;
Componentes principais
Uso
Você pode obter um PlayAuth chamando a operação GetVideoPlayAuth. Recomendamos integrar o SDK server-side para VOD para obter credenciais, o que evita a necessidade de assinar URLs manualmente. Para mais informações, consulte OpenAPI Portal.
[self.player setOnVidAuthExpiredCallback:^(id expiredSource, id<AVPSourceRefreshCallback> callback) {
// Get the AVPVidAuthSource object.
if ([expiredSource isKindOfClass:[AVPVidAuthSource class]]) {
AVPVidAuthSource *vidAuth = (AVPVidAuthSource *)expiredSource;
// ------------------- Start of user implementation -------------------
// Call your custom function to retrieve a new PlayAuth from your app server.
// clinetGetPlayAuthFunction is a sample function name. Replace it with your actual implementation.
[self clinetGetPlayAuthFunction:vidAuth.vid success:^(NSString* newPlayAuth){
// 1. In the success callback, after retrieving the new credential:
[vidAuth setPlayAuth:newPlayAuth];
// 2. Pass the updated source object back to the player via the SDK's callback.
[callback onSuccess:vidAuth];
} failure:^(NSString* errorMsg) {
// In the failure callback.
// errorMsg contains details about the error.
[callback onError:errorMsg];
}];
// ------------------- End of user implementation -------------------
}
}];
Fonte URL
Exemplo de API
/**
@brief Sets the callback for URL source expiration notifications.
This callback is triggered when the player detects that the current URL source has expired.
You can refresh the URL source in this callback and return the new URL source via the `callback` parameter to ensure continuous playback.
@note For more information about how to configure URL signing, see the Alibaba Cloud documentation:
https://www.alibabacloud.com/help/en/vod/user-guide/configure-url-signing
@param callback The callback block triggered when the URL source expires.
You can use this callback to provide a valid `URLSource` object to update the player.
*/
-(void)setOnURLSourceExpiredCallback:(void (^)(id expiredSource, id<AVPSourceRefreshCallback> callback))callback;
Componentes principais
Uso
[self.player setOnURLSourceExpiredCallback:^(id expiredSource, id<AVPSourceRefreshCallback> callback) {
// Get the AVPUrlSource object.
if ([expiredSource isKindOfClass:[AVPUrlSource class]]) {
AVPUrlSource *expiredUrlSource = (AVPUrlSource *)expiredSource;
NSString *expiredUrl = [expiredUrlSource.playerUrl absoluteString];
// Check if the URL contains "auth_key".
if (![expiredUrl containsString:@"auth_key="]) {
return;
}
// 1. Extract the original URL from the expired URL.
NSRange authKeyQuestionRange = [expiredUrl rangeOfString:@"?auth_key="];
NSRange authKeyAmpersandRange = [expiredUrl rangeOfString:@"&auth_key="];
NSInteger authKeyIndex = NSNotFound;
if (authKeyQuestionRange.location != NSNotFound) {
authKeyIndex = authKeyQuestionRange.location;
} else if (authKeyAmpersandRange.location != NSNotFound) {
authKeyIndex = authKeyAmpersandRange.location;
}
NSString *originalUrl = nil;
if (authKeyIndex != NSNotFound) {
originalUrl = [expiredUrl substringToIndex:authKeyIndex];
} else {
// If "auth_key" is not found, assume the entire URL is the original URL.
originalUrl = expiredUrl;
}
// 2. Prepare new authentication parameters: the authKey and the expiration time.
// Use the authKey class member if it is valid.
NSString *key = (self.authKey.length > 0) ? self.authKey : @"";
if (!NOT_EMPTY(key)) {
[callback onError:@"REFRESH_ERROR:key fail"];
return;
}
// Use the validTime class member if it is valid; otherwise, use a default value.
NSTimeInterval validTime = (self.validTime > 0) ? self.validTime : 3600; // Default: 3600 seconds.
NSTimeInterval newExpireTime = [[NSDate date] timeIntervalSince1970] + validTime;
// 3. Generate a new signed URL with CdnAuthUtil (Method A).
NSString *newAuthUrl = [CdnAuthUtil aAuthWithUri:originalUrl key:key exp:newExpireTime];
AVPUrlSource *resultSource = [[AVPUrlSource alloc] urlWithString:newAuthUrl];
// 4. Handle the callback.
if (newAuthUrl) {
[callback onSuccess:resultSource];
} else {
[callback onError:@"REFRESH_ERROR:refresh fail"];
}
}
}];
Funções auxiliares
O exemplo a seguir usa o método de autenticação A.
Melhoria de áudio
O ApsaraVideo Player SDK para iOS fornece um plugin de melhoria de áudio para aprimorar a experiência de reprodução de áudio. Ele inclui três recursos principais: normalização de volume, melhoria de diálogo e som surround.
Recursos
-
Normalização de volume: Ajusta automaticamente todo o conteúdo de áudio para um nível de volume consistente, melhorando a reprodução de vídeos com volume original excessivamente baixo ou alto.
Canais suportados: mono, estéreo, 5,1 e 7,1.
Taxas de amostragem suportadas: 16 kHz, 44,1 kHz e 48 kHz.
-
Melhoria de diálogo: Enfatiza inteligentemente os diálogos, tornando as vozes em cenas ruidosas mais claras sem alterar o timbre original.
Canais suportados: estéreo.
Taxas de amostragem suportadas: 44,1 kHz e 48 kHz.
-
Som surround: Aplica renderização de surround virtual a áudio multicanal e estéreo, proporcionando uma experiência imersiva em fones de ouvido ou dispositivos padrão. Inclui dois modos: 3DSurround e MegaBass.
Canais suportados: mono, estéreo, 5,1 e 7,1.
Taxas de amostragem suportadas: 44,1 kHz e 48 kHz.
Pré-requisitos
O ApsaraVideo Player SDK para iOS ou o all-in-one SDK deve ser v7.13.0 ou posterior.
Você deve ter uma Licença da Professional Edition. Para mais informações, consulte Obter uma licença para ApsaraVideo Player SDK.
O recurso de melhoria de áudio suporta as seguintes fontes de áudio:
Stream VOD: Requer transcodificação de mídia no ApsaraVideo VOD.
Stream ao vivo: Qualquer fonte é suportada.
Integrar plugin
Integração CocoaPods
Adicione a dependência do plugin ao seu Podfile:
Para a versão mais recente do ApsaraVideo Player SDK para iOS, consulte Notas de lançamento do ApsaraVideo Player SDK para iOS.
// x.x.x must match the version of the player SDK.
pod 'AliPlayerSDK_iOS_AUDIO_ENHANCE_FILTER', 'x.x.x'
Integração local
Baixe a versão mais recente do ApsaraVideo Player SDK para iOS. Adicione o arquivo audioEnhanceFilter.framework em Frameworks, Libraries, and Embedded Content, defina Embed como Embed & Sign e configure os Framework Search Paths. Para mais informações, consulte Integração local.
API
setFilterValid
Controla o interruptor principal do recurso de melhoria de áudio. O nome target do filtro de melhoria de áudio é audioEnhance. Desativar este recurso também desativa todos os seus sub-recursos. Por padrão, este recurso está desativado.
[player setFilterValid:@"audioEnhance" valid:YES]; // Enable
[player setFilterValid:@"audioEnhance" valid:NO]; // Disable
setFilterConfig
Defina o objeto FilterConfig antes de chamar o método prepare. A configuração entra em vigor quando a reprodução começa.
AVPFilterConfig *filterConfig = [[AVPFilterConfig alloc] init];
AVPFilter *filterItem = [[AVPFilter alloc] initWithTarget:@"audioEnhance"];
AVPFilterOptions *opts = [[AVPFilterOptions alloc] init];
// Surround sound
[opts setOptions:@"enable_surround" value:@YES];
[opts setOptions:@"surround_effect_type" value:@"3DSurround"]; // The type must be set when you first enable surround sound.
// Dialogue enhancement
[opts setOptions:@"enable_dialoguenhance" value:@YES];
[opts setOptions:@"dialoguenhance_voice" value:@(1.0)]; // Range: 1.0 to 10.0. The voice level must be set when you first enable dialogue enhancement.
// Volume normalization
[opts setOptions:@"enable_normalizer" value:@YES];
[filterItem setOptions:opts];
[filterConfig addFilter:filterItem];
[player setFilterConfig:filterConfig];
|
Parâmetro |
Tipo |
Descrição |
|
|
Boolean |
Especifica se deve ativar o recurso de som surround. |
|
|
String |
O modo de som surround. Valores válidos: |
|
|
Boolean |
Especifica se deve ativar o recurso de melhoria de diálogo. |
|
|
Float |
A intensidade da melhoria de diálogo. Intervalo: 1,0 a 10,0. |
|
|
Boolean |
Especifica se deve ativar o recurso de normalização de volume. |
updateFilterConfig
Chame este método para ajustar parâmetros dinamicamente após o player estar preparado ou enquanto estiver reproduzindo.
Chamar updateFilterConfig antes do método prepare não tem efeito. Use o método setFilterConfig para a configuração inicial.
AVPFilterOptions *opts = [[AVPFilterOptions alloc] init];
[opts setOptions:@"enable_surround" value:@YES];
[opts setOptions:@"surround_effect_type" value:@"3DSurround"]; // The type can only be set when enabling surround sound for the first time. It is ignored on subsequent calls because the filter is already initialized.
[player updateFilterConfig:@"audioEnhance" options:opts];
O tipo de som surround ("3DSurround" ou "MegaBass") e a força da melhoria de diálogo (dialoguenhance_voice) devem ser configurados com a propriedade enable quando ativados pela primeira vez. Caso contrário, eles serão inicializados com seus valores padrão ("3DSurround" para som surround e 1,0 para força da melhoria de diálogo) e não poderão ser alterados durante a reprodução.
Desempenho
Definir uma cena do player
Definir uma cena do player aplica automaticamente os parâmetros ideais para esse cenário, como configurações de buffer e alternância de recursos. Parâmetros personalizados definidos com o método setConfig substituem os padrões da cena.
Após definir uma cena do player, você pode chamar o método
getConfigpara visualizar a configuração efetiva.
Exemplo de API
/**
@brief Sets the player scene.
@param scene The player scene.
@see AVPScene
*/
-(void) setPlayerScene:(AVPScene)scene;
Cenas do player
typedef enum _AVPScene {
/**
* No specific scene is set.
*/
SceneNone,
/**
* Long video scene, suitable for videos over 30 minutes.
*/
SceneLong,
/**
* Medium video scene, suitable for videos between 5 and 30 minutes.
*/
SceneMedium,
/**
* Short video scene, suitable for videos up to 5 minutes.
*/
SceneShort,
/**
* Live streaming scene.
*/
SceneLive,
/**
* RTS live scene.
*/
SceneRTSLive
} AVPScene;
Uso
// Set the short video scene.
[self.player setPlayerScene:SceneShort];
// Set the medium video scene.
[self.player setPlayerScene:SceneMedium];
// Set the long video scene.
[self.player setPlayerScene:SceneLong];
// Set the live streaming scene.
[self.player setPlayerScene:SceneLive];
Pré-renderização
O Alibaba Cloud Player SDK para iOS pode renderizar o primeiro quadro de um vídeo antes do início da reprodução, o que pode melhorar a velocidade de inicialização.
Este recurso está desativado por padrão.
Você deve definir a
Viewdo player antes de chamarPreparepara garantir que o quadro seja renderizado naViewassim que estiver pronto.Ativar este recurso afeta a ordem em que os eventos de sucesso de preparação e renderização do primeiro quadro são acionados. Quando este recurso está desativado, o evento de sucesso de preparação é acionado antes do evento de renderização do primeiro quadro. Quando este recurso está ativado, o evento de renderização do primeiro quadro pode ser acionado antes do evento de sucesso de preparação, dependendo da velocidade de decodificação e renderização. Isso não afeta a reprodução.
O exemplo a seguir mostra como ativar este recurso:
[self.player setOption:ALLOW_PRE_RENDER valueInt:1];
Cache local
Para exemplos de código detalhados, consulte o módulo PreloadUrl no projeto API-Example. Este projeto de exemplo, escrito em Objective-C, demonstra como integrar os recursos principais do Alibaba Cloud Player SDK para iOS.
O Alibaba Cloud Player SDK para iOS fornece um recurso de cache local. Este recurso melhora a velocidade de inicialização e a velocidade de busca, reduz travamentos e economiza tráfego de rede durante reproduções repetidas.
Ativar cache local
O recurso de cache local está desativado por padrão. Para usar este recurso, você deve ativá-lo com o método enableLocalCache da classe AliPlayerGlobalSettings. O exemplo a seguir mostra como fazer isso.
/**
* Enables the local cache. When enabled, content is cached to local files.
* @param enable A boolean value that specifies whether to enable the local cache. true: enabled, false: disabled. Default value: false.
* @param maxBufferMemoryKB This parameter is deprecated in v5.4.7.1 and later and has no effect.
* @param localCacheDir The directory for local cache files. You must specify an absolute path.
*/
[AliPlayerGlobalSettings enableLocalCache:true maxBufferMemoryKB:1024 localCacheDir:@""];
/**
@brief Configures the automatic cleanup of local cache files.
@param expireMin This parameter is deprecated in v5.4.7.1 and later and has no effect.
@param maxCapacityMB The maximum cache size in MB. Default value: 20 GB. During cleanup, if the total cache size exceeds this limit, the oldest cache items are deleted one by one until the total size is within the limit.
@param freeStorageMB The minimum free disk space in MB. Default value: 0. During cleanup, if the available disk space is less than this value, cache files are deleted one by one until the free space is equal to or greater than this value, or until all cached files are deleted.
*/
[AliPlayerGlobalSettings setCacheFileClearConfig:0 maxCapacityMB:0 freeStorageMB:0];
/**
* A callback to get the hash value of a URL. This value is used as the unique ID for the URL. You must ensure that each URL has a unique hash value.
*/
// You must implement this function and pass its pointer to setCacheUrlHashCallback.
static NSString *CaheUrlHashHandle(NSString *url) {
return @"xxx";
}
[AliPlayerGlobalSettings setCacheUrlHashCallback:&CaheUrlHashHandle];
-
Se as URLs de reprodução de vídeo incluírem parâmetros de autenticação, os parâmetros mudam entre o armazenamento em cache e a reprodução. Para melhorar a taxa de acerto de cache para a mesma URL sob diferentes autenticações, remova os parâmetros de autenticação antes de calcular o valor hash (por exemplo, MD5) via
setCacheUrlHashCallback. Por exemplo, para uma URL comohttp://****.mp4?aaa, calcule o hash usandohttp://****.mp4. No entanto, para vídeos m3u8 criptografados, se você remover parâmetros de autenticação das keyURLs antes de fazer o hash, vídeos diferentes podem atingir a mesma chave, causando falha na reprodução. Solução: No callbacksetCacheUrlHashCallback, verifique o domínio e remova os parâmetros de autenticação apenas para domínios de reprodução (http(s)://xxxxx.m3u8?aaaa), não para domínios keyURL (http(s)://yyyyy?bbbb). Use curl para obter a playlist M3U8 do vídeo HLS criptografado, onde playURL é o endereço M3U8 e keyURL é o endereço da chave de descriptografia AES-128. Exemplo de saída do terminal:# playURL: M3U8 playlist request C:\Users\futan>curl "https://videxxxv.cc/a003xxx2a-hd-encrypt-stream.m3u8?MtsHlsUriToken=uheAz07oi-jlo9CeIU6LxxxAr4a3WtzrJXnCn4ClS44dTYHCQGmXBlo7TyuPLE0a&auth_key=17xxxrmonwFHJ" #EXTM3U #EXT-X-VERSION:3 #EXT-X-ALLOW-CACHE:YES #EXT-X-TARGETDURATION:10 #EXT-X-MEDIA-SEQUENCE:0 # keyURL: AES-128 encryption key address #EXT-X-KEY:METHOD=AES-128,URI="https://apxxx.cc/decrypt?Ciphertext=NWNiNDQyN2MtNjV1ZS00ZWIwLTk0YTAtNTJhOWIyZWV1OTY2MzdoRTJ6TjVxcXkweFY2xxxNCt4OGNFRGNReHRG&MtsHlsUriToken=uheAz07oi-jlo9CeIU6LxxxAr4a3WtzrJXnCn4ClS44dTYHCQGmXBlo7TyuPLE0a" #EXTINF:10.000000, e9012989ecd8e987eb7349d84d3b06d8-hd-encrypt-stream-00001.ts?auth_key=1706560316-65b7xxx39f1d6c77 #EXTINF:10.000000, e9012989ecd8e987eb7349d84d3b06d8-hd-encrypt-stream-00002.ts?auth_key=1706560316-65b7xxxe8eca2faf #EXTINF:10.000000, e9012989ecd8e987eb7349d84d3b06d8-hd-encrypt-stream-00003.ts?auth_key=1706560316-65b7xxx50c6981b3 #EXTINF:10.000000, e9012989ecd8e987eb7349d84d3b06d8-hd-encrypt-stream-00004.ts?auth_key=1706560316-65b7xxxf7228c594 #EXTINF:10.000000, e9012989ecd8e987eb7349d84d3b06d8-hd-encrypt-stream-00005.ts?auth_key=1706560316-65b7xxx6dc68c35d -
Se um servidor servir o mesmo arquivo de mídia via HTTP e HTTPS, você pode melhorar a taxa de acerto de cache removendo ou normalizando o protocolo antes de calcular o valor hash. Por exemplo:
Se as URLs de reprodução forem
https://****.mp4ehttp://****.mp4, use****.mp4para calcular o valor hash.Se a URL de reprodução for
https://****.mp4, você pode usar consistentementehttp://****.mp4para calcular o valor hash.
-
Para Alibaba Cloud Player SDK v5.5.4.0 e posterior, se você reproduzir um stream HLS com uma URL que contém parâmetros de autenticação, poderá definir o campo
AVPConfig.enableStrictAuthModepara selecionar um modo de autenticação. O valor padrão é false para versões mais antigas e true para v7.13.0 e posterior.Autenticação não estrita (
false): As informações de autenticação são armazenadas em cache junto com o conteúdo de mídia. Se apenas parte da mídia foi armazenada em cache anteriormente, o player usa as informações de autenticação em cache para solicitar a parte não armazenada. Se a autenticação da URL tiver um curto período de validade ou se a reprodução for retomada após uma longa pausa, a autenticação pode expirar. Para lidar com isso, você precisa implementar o recurso de atualização automática de fonte.Autenticação estrita (
true): As informações de autenticação não são armazenadas em cache. A autenticação ocorre no início de cada sessão de reprodução. Isso pode causar falha na reprodução se não houver conexão de rede.
Ativar ou desativar cache para uma URL
Se você quiser desativar o recurso de cache local para uma única URL, poderá configurá-lo no player config. O exemplo a seguir ilustra isso:
// Get the configuration.
AVPConfig *config = [self.player getConfig];
// Specifies whether to enable local caching for the playback URL. Default value: true.
// To enable local caching for this URL, both this setting and the global setting in AliPlayerGlobalSettings must be enabled.
// If this is set to false, local caching is disabled for this URL.
config.enableLocalCache = false;
....// Other settings
// Apply the configuration to the player.
[self.player setConfig:config];
Usar o caminho de cache padrão
Para usar o caminho de cache padrão, ative o cache local sem especificar um diretório em AliPlayerGlobalSettings.
[AliPlayerGlobalSettings enableLocalCache:true];
Cache grande
Armazenar dados de vídeo em buffer na memória pode melhorar o desempenho da reprodução e a experiência de visualização. No entanto, um buffer grande pode consumir uma quantidade significativa de memória. O recurso de cache grande armazena dados de vídeo em um arquivo, o que reduz o uso de memória e melhora o desempenho do player.
O recurso de cache grande é ativado automaticamente quando o cache local está ativado e mMaxBufferDuration está definido com um valor maior que 50.000 ms. Para usar este recurso, siga estas etapas:
-
Ative o cache local global.
Você deve ativar manualmente este recurso usando o método
enableLocalCacheemAliPlayerGlobalSettings. Para um exemplo de código, consulte Ativar cache local em Cache local. -
Ative o cache local para a URL.
Para um exemplo de código, consulte Ativar ou desativar cache para uma URL em Cache local.
-
Ative o cache grande.
[AliPlayerGlobalSettings enableBufferToLocalCache:true];
Pré-carregamento
O Alibaba Cloud Player SDK para iOS fornece um recurso de pré-carregamento, que é um aprimoramento do cache local. O pré-carregamento baixa uma parte de um vídeo para o cache antes do início da reprodução, melhorando a velocidade de inicialização.
O pré-carregamento tem as seguintes limitações:
Suporta apenas arquivos de mídia únicos, como MP4, MP3, FLV e HLS.
Por padrão, o Alibaba Cloud Player SDK para iOS agenda automaticamente recursos de rede para pré-carregamento para minimizar interferências no vídeo atualmente em reprodução. A solicitação de pré-carregamento é enviada somente depois que o buffer do vídeo atualmente em reprodução atinge um limiar específico. Para desativar esse comportamento e gerenciar solicitações de pré-carregamento em tempo real, chame o seguinte método:
[AliPlayerGlobalSettings enableNetworkBalance:false];
Ative o recurso de cache local conforme descrito em Cache local.
-
Defina a fonte de dados.
VidAuth (recomendado)
AVPVidAuthSource* vidAuthSource = [[AVPVidAuthSource alloc] init]; [vidAuthSource setVid:@"your_video_id"]; // Required. The video ID. [vidAuthSource setPlayAuth:@"<yourPlayAuth>"]; // Required. The playback credential. You must call the GetVideoPlayAuth operation of ApsaraVideo for VOD to generate the credential. [vidAuthSource setRegion:@"your_region"]; // This parameter is deprecated in SDK v5.5.5.0 and later. The player automatically parses the region. For earlier versions, this parameter is required and defaults to cn-shanghai. [vidAuthSource setQuality:@"AUTO"]; // "AUTO" enables adaptive bitrate streaming.VidSts
AVPVidStsSource* vidStsSource = [[AVPVidStsSource alloc] init]; [vidStsSource setVid: @""]; // Required. The video ID. [vidStsSource setRegion:@""]; // Required. The region where ApsaraVideo VOD is activated. Default value: cn-shanghai. [vidStsSource setSecurityToken: @"<yourSecurityToken>"]; // Required. The STS security token. You must call the AssumeRole API operation of STS to obtain the token. [vidStsSource setAccessKeySecret: @"<yourAccessKeySecret>"]; // Required. The AccessKey secret of the temporary STS AccessKey pair. You must call the AssumeRole API operation of STS to obtain the AccessKey secret. [vidStsSource setAccessKeyId: @"<yourAccessKeyId>"]; // Required. The AccessKey ID of the temporary STS AccessKey pair. You must call the AssumeRole API operation of STS to obtain the AccessKey ID. [vidStsSource setQuality:@""]; // "AUTO" specifies adaptive bitrate streaming.UrlSource
NSString* url = @"your_playback_url"; // Required. The playback URL. It can be a third-party VOD URL or a playback URL from ApsaraVideo for VOD. AVPUrlSource* urlSource = [[AVPUrlSource alloc]urlWithString:url]; -
Defina os parâmetros da tarefa.
NotaEsses parâmetros aplicam-se apenas a vídeos de múltiplas taxas de bits. Você precisa definir apenas um entre
setDefaultBandWidth,setDefaultResolutionesetDefaultQuality.AVPPreloadConfig *config = [[AVPPreloadConfig alloc]init]; // Set the preload bitrate for a multi-bitrate stream. [config setDefaultBandWidth:400000]; // Set the preload resolution for a multi-bitrate stream. [config setDefaultResolution:640 * 480]; // Set the preload quality for a multi-bitrate stream. [config setDefaultQuality:@"FD"]; // Set the preload duration. [config setDuration:1000]; -
Adicione um listener de tarefa.
-
Construa a tarefa, adicione-a à instância
MediaLoaderV2e inicie o pré-carregamento.VidAuth (recomendado)
// Build the preload task. AVPPreloadTask* mPreloadTask = [[AVPPreloadTask alloc]initWithVidAuthSource:vidAuthSource preloadConfig:config]; // Get the MediaLoaderV2 instance. AliMediaLoaderV2* vodMedialoader = [AliMediaLoaderV2 shareInstance]; // Add the task and start preloading. NSString* taskId = [vodMedialoader addTask:mPreloadTask listener:self];VidSts
// Build the preload task. AVPPreloadTask* mPreloadTask = [[AVPPreloadTask alloc]initWithVidStsSource:vidStsSource preloadConfig:config]; // Get the MediaLoaderV2 instance. AliMediaLoaderV2* vodMedialoader = [[AliMediaLoaderV2 alloc]init]; // Add the task and start preloading. NSString* taskId = [vodMedialoader addTask:mPreloadTask listener:self];UrlSource
// Build the preload task. AVPPreloadTask* mPreloadTask = [[AVPPreloadTask alloc]initWithUrlSource:urlSource preloadConfig:config]; // Get the MediaLoaderV2 instance. AliMediaLoaderV2* vodMedialoader = [[AliMediaLoaderV2 alloc]init]; // Add the task and start preloading. NSString* taskId = [vodMedialoader addTask:mPreloadTask listener:self]; -
Opcional: Gerencie tarefas.
[vodMedialoader cancelTask:taskId];// Cancel the preload task with the specified ID. [vodMedialoader pauseTask:taskId];// Pause the preload task with the specified ID. [vodMedialoader resumeTask:taskId];// Resume the preload task with the specified ID. -
Opcional: Exclua arquivos carregados.
Para economizar espaço, você pode excluir arquivos em cache. Como o Alibaba Cloud Player SDK para iOS não fornece uma interface de exclusão, você deve excluir manualmente os arquivos do diretório de cache dentro do seu aplicativo.
Pré-carregamento dinâmico
A estratégia de pré-carregamento dinâmico permite controlar o cache para o vídeo atual e o número de vídeos a serem pré-carregados. Isso ajuda a equilibrar a experiência de reprodução com o custo.
Pré-carregamento de vídeos HLS de múltiplas taxas de bits
Em um cenário listPlayer com vídeos HLS de múltiplas taxas de bits, você pode pré-carregar um stream que corresponda à qualidade de reprodução atual e escolher um modo de pré-carregamento adequado às suas necessidades de negócios.
Velocidade de download
Você pode obter a velocidade de download do vídeo atualmente em reprodução a partir do parâmetro speed no callback onCurrentDownloadSpeed. O exemplo a seguir mostra como fazer isso.
- (void)onCurrentDownloadSpeed:(AliPlayer *)player speed:(int64_t)speed{
intspeed_=speed;
}
Recursos de rede
HTTPDNS
O HTTPDNS resolve nomes de domínio via HTTP para servidores específicos, reduzindo riscos de sequestro de DNS e fornecendo resolução mais rápida e estável.
O ApsaraVideo Player SDK fornece HTTPDNS aprimorado para domínios Alibaba Cloud CDN, suportando agendamento preciso de CDN e resolução em tempo real.
Exemplo de HTTPDNS aprimorado
O HTTPDNS aprimorado fornece serviços apenas para domínios Alibaba Cloud CDN. Certifique-se de que seu domínio seja um domínio Alibaba Cloud CDN e esteja configurado corretamente. Para adicionar domínios CDN no VOD, consulte Adicionar domínio acelerado. Alibaba Cloud CDN.
// Enable enhanced HTTPDNS.
[AliPlayerGlobalSettings enableEnhancedHttpDns:YES];
// Optional. Add a domain name for HTTPDNS pre-resolution.
[[AliDomainProcessor shareInstance] addPreResolveDomain:@"player.***alicdn.com"];
HTTP/2
A partir da v5.5.0.0, o Alibaba Cloud Player SDK para iOS ativa o HTTP/2 por padrão.
O Alibaba Cloud Player SDK para iOS suporta HTTP/2, que usa multiplexação para evitar bloqueio de cabeça de linha e melhorar o desempenho da reprodução. Exemplo:
[AliPlayerGlobalSettings setUseHttp2:true];
HTTP/3
O IETF padronizou o QUIC em 2022. O Alibaba Cloud Player SDK para iOS suporta apenas IETF QUIC h3-v1 e não suporta Google QUIC.
Se uma conexão HTTP/3 expirar ou falhar, o player voltará automaticamente para HTTP/2.
O Alibaba Cloud Player SDK para iOS suporta HTTP/3. Para usar este recurso, você deve enviar um formulário de solicitação para ativar o HTTP/3 para o seu nome de domínio. Isso permite reproduzir vídeos armazenados no ApsaraVideo VOD e acelerados por esse nome de domínio via HTTP/3. Você pode então configurar o player para solicitar conteúdo via HTTP/3, melhorando o desempenho em condições de rede fracas. Exemplo:
// Get the current configuration.
AVPConfig *config = [self.player getConfig];
// Enable HTTP/3 requests.
config.enableHttp3 = YES;
//... other settings
// Apply the configuration to the current player instance.
[self.player setConfig:config];
Pré-conexão TCP
Para solicitações de reprodução de vídeo HTTP (não HTTPS), pré-estabelecer uma conexão TCP melhora significativamente a experiência do usuário, reduzindo o tempo de conexão, garantindo reprodução imediata e contínua e otimizando o uso de recursos de rede e do sistema. Exemplo:
// The domain format is host[:port]. The port is optional. Use semicolons (;) to separate multiple domain names.
// Global setting.
// This is an absolute setting. Each time you call this method, the new string replaces the previous one. An empty string disables pre-connection.
[AliPlayerGlobalSettings setOption:SET_PRE_CONNECT_DOMAIN value: @"domain1;domain2"];
Plugins pagos
Download de vídeo
Para um exemplo de código detalhado, consulte o módulo Video Download and Offline Playback (Download) em API-Example. Este projeto de exemplo em Objective-C demonstra como integrar os recursos principais do ApsaraVideo Player SDK para iOS.
O ApsaraVideo Player SDK para iOS permite baixar conteúdo do ApsaraVideo VOD para reprodução offline. O SDK oferece dois modos de download: download padrão e download seguro.
Download padrão: Os dados de vídeo baixados não são criptografados pela Alibaba Cloud e podem ser reproduzidos usando players de terceiros.
Download seguro: Os dados de vídeo baixados são criptografados pela Alibaba Cloud. Eles não podem ser reproduzidos por players de terceiros e só podem ser reproduzidos usando o ApsaraVideo Player.
Uso
O recurso de download de vídeo está disponível apenas para fontes VidSts e VidAuth.
Para usar o recurso de download de vídeo, você deve ativar e configurar o modo de download no console do ApsaraVideo VOD. Para mais informações, consulte download offline.
O recurso de download de vídeo suporta downloads retomáveis.
Procedimento
-
Opcional: Configure o arquivo de chave para download seguro. Esta etapa é necessária apenas para download seguro.
NotaCertifique-se de que as informações no arquivo de chave configurado correspondam às informações do seu aplicativo. Caso contrário, o download do vídeo falhará.
Se você usar o modo de download seguro, deverá configurar o ApsaraVideo Player SDK com o arquivo de chave gerado no console do ApsaraVideo VOD. Este arquivo é usado para descriptografia e verificação durante o download e a reprodução do vídeo. Para instruções sobre como gerar o arquivo de chave, consulte Ativar download seguro.
Execute esta configuração apenas uma vez no seu aplicativo, conforme mostrado no exemplo a seguir:
NSString *encrptyFilePath = [[NSBundle mainBundle] pathForResource:@"encryptedApp" ofType:@"dat"]; [AliPrivateService initKey:encrptyFilePath]; -
Crie e configure o downloader.
O código a seguir fornece um exemplo:
AliMediaDownloader *downloader = [[AliMediaDownloader alloc] init]; [downloader setSaveDirectory:self.downLoadPath]; [downloader setDelegate:self]; -
Defina os listeners de eventos.
O downloader suporta múltiplos listeners de eventos. O código a seguir fornece um exemplo:
-(void)onPrepared:(AliMediaDownloader *)downloader mediaInfo:(AVPMediaInfo *)info { // A download item is successfully prepared. } -(void)onError:(AliMediaDownloader *)downloader errorModel:(AVPErrorModel *)errorModel { // An error occurred during download. } -(void)onDownloadingProgress:(AliMediaDownloader *)downloader percentage:(int)percent { // Download progress percentage. } -(void)onProcessingProgress:(AliMediaDownloader *)downloader percentage:(int)percent { // Processing progress percentage. } -(void)onCompletion:(AliMediaDownloader *)downloader { // The download is successful. } -
Prepare a fonte de download.
Chame o método
preparepara preparar a fonte de download. Fontes VidSts e VidAuth são suportadas. O código a seguir fornece um exemplo:-
VidSts
// Create a VidSts source. AVPVidStsSource* stsSource = [[AVPVidStsSource alloc] init]; stsSource.region = @"your_region"; // Your ApsaraVideo VOD service region. Default value: cn-shanghai. stsSource.vid = @"your_video_id"; // The video ID. stsSource.securityToken = @"<yourSecurityToken>"; // The STS security token. To get this token, call the STS AssumeRole operation. stsSource.accessKeySecret = @"<yourAccessKeySecret>"; // The AccessKey secret of the temporary STS credential. To get this secret, call the STS AssumeRole operation. stsSource.accessKeyId = @"<yourAccessKeyId>"; // The AccessKey ID of the temporary STS credential. To get this ID, call the STS AssumeRole operation. // If you have enabled parameter pass-through for HLS encryption in the ApsaraVideo VOD console // and the default parameter name is MtsHlsUriToken, you must set the config and pass it to the VidSts source. // If this feature is not enabled, you can skip the following code. VidPlayerConfigGenerator* vp = [[VidPlayerConfigGenerator alloc] init]; [vp setHlsUriToken:yourMtsHlsUriToken]; stsSource.playConfig = [vp generatePlayerConfig]; // Prepare the download source. [downloader prepareWithVid:stsSource]; -
VidAuth
// Create a VidAuth source. AVPVidAuthSource *authSource = [[AVPVidAuthSource alloc] init]; authSource.vid = @"your_video_id"; // The video ID. authSource.playAuth = @"<yourPlayAuth>"; // The playback credential. To get this credential, call the ApsaraVideo VOD GetVideoPlayAuth operation. authSource.region = @"your_region"; // Deprecated in ApsaraVideo Player SDK V5.5.5.0 and later because the player automatically parses the region. // Required for earlier versions. // Your ApsaraVideo VOD service region. Default value: cn-shanghai. // If you have enabled parameter pass-through for HLS encryption in the ApsaraVideo VOD console // and the default parameter name is MtsHlsUriToken, you must set the config and pass it to the VidAuth source. // If this feature is not enabled, you can skip the following code. VidPlayerConfigGenerator* vp = [[VidPlayerConfigGenerator alloc] init]; [vp setHlsUriToken:yourMtsHlsUriToken]; authSource.playConfig = [vp generatePlayerConfig]; // Prepare the download source. [downloader prepareWithVid:authSource];
NotaSe você ativar a passagem de parâmetros para criptografia HLS no console do ApsaraVideo VOD e o nome do parâmetro padrão for MtsHlsUriToken, deverá definir o valor MtsHlsUriToken na fonte de download conforme mostrado no código acima. Para mais informações, consulte passagem de parâmetros para criptografia HLS.
-
-
Selecione uma faixa de vídeo após a preparação da fonte.
Após a preparação da fonte de download, o método
onPreparedé chamado. O parâmetromediaInfodo callback contém informações sobre cada faixa de vídeo disponível, como qualidade de vídeo. Selecione uma faixa para baixar. O código a seguir fornece um exemplo:-(void)onPrepared:(AliMediaDownloader *)downloader mediaInfo:(AVPMediaInfo *)info { NSArray<AVPTrackInfo*>* tracks = info.tracks; // For example, to download the first track: [downloader selectTrack:[tracks objectAtIndex:0].trackIndex]; } -
Atualize a fonte de download e inicie o download.
Para evitar que as credenciais VidSts e VidAuth expirem, recomendamos atualizar as informações da fonte antes de iniciar o download. O código a seguir fornece um exemplo:
// Update the download source. [downloader updateWithVid:vidSource] // Start the download. [downloader start]; -
Libere o downloader após a conclusão ou falha do download.
Chame o método
destroypara liberar o downloader.[self.downloader destroy]; self.downloader = nil;
Reprodução criptografada
O ApsaraVideo VOD suporta criptografia padrão HLS, criptografia proprietária da Alibaba Cloud e criptografia DRM. Vídeo ao vivo suporta apenas criptografia DRM. Para mais informações, consulte Reprodução criptografada.
Reprodução RTS nativa
O iOS player SDK integra o Native RTS SDK para permitir streaming ao vivo de baixa latência. Para mais informações, consulte Implementar pull de stream baseado em RTS no iOS.