Todos os produtos
Search
Central de documentação

ApsaraVideo VOD:Recursos avançados

Última atualização: Jun 30, 2026

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.

Importante

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

Nota

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).

Procedimento

  1. Crie um player.

    Crie uma instância de AliListPlayer.

    self.listPlayer = [[AliListPlayer alloc] init];
    [self.listPlayer setTraceID:@"xxxxxx"];  // The TraceID uniquely identifies a device or user. It is typically an IMEI or IDFA.
  2. Opcional:Defina os listeners.

    Os listeners são opcionais, mas recomendamos configurá-los para receber notificações de eventos sobre falhas de reprodução, atualizações de progresso, entre outros.

    O player suporta múltiplos listeners. Recomendamos definir pelo menos os listeners onPlayerEvent e onError.

    /**
     @brief Error callback.
     @param player The player pointer.
     @param errorModel The error description. For more information, see AVPErrorModel.
     */
    - (void)onError:(AliPlayer*)player errorModel:(AVPErrorModel *)errorModel {
        // Displays an error and stops the playback.
    }
    /**
     @brief Player event callback.
     @param player The player pointer.
     @param eventType The player event type. For more information, see AVPEventType.
     */
    -(void)onPlayerEvent:(AliPlayer*)player eventType:(AVPEventType)eventType {
        switch (eventType) {
            case AVPEventPrepareDone: {
                // The player is prepared.
            }
                break;
            case AVPEventAutoPlayStart:
                // Autoplay starts.
                break;
            case AVPEventFirstRenderedStart:
                // The first frame is rendered.
                break;
            case AVPEventCompletion:
                // Playback is complete.
                break;
            case AVPEventLoadingStart:
                // Buffering starts.
                break;
            case AVPEventLoadingEnd:
                // Buffering is complete.
                break;
            case AVPEventSeekEnd:
                // Seeking is complete.
                break;
            case AVPEventLoopingStart:
                // Looping starts.
                break;
            default:
                break;
        }
    }
    /**
     @brief Callback for the current playback position.
     @param player The player pointer.
     @param position The current playback position.
     */
    - (void)onCurrentPositionUpdate:(AliPlayer*)player position:(int64_t)position {
        // Update the progress bar.
    }
    /**
     @brief Callback for the buffered position.
     @param player The player pointer.
     @param position The current buffered position.
     */
    - (void)onBufferedPositionUpdate:(AliPlayer*)player position:(int64_t)position {
        // Update the buffer progress.
    }
    /**
     @brief Callback for track information.
     @param player The player pointer.
     @param info An array of track stream information. For more information, see AVPTrackInfo.
     */
    - (void)onTrackReady:(AliPlayer*)player info:(NSArray<AVPTrackInfo*>*)info {
        // Get information about multi-bitrate streams.
    }
    /**
     @brief Callback for displaying subtitles.
     @param player The player pointer.
     @param trackIndex The index of the subtitle stream.
     @param subtitleID The subtitle ID.
     @param subtitle The subtitle string.
     */
    - (void)onSubtitleShow:(AliPlayer*)player trackIndex:(int)trackIndex subtitleID:(long)subtitleID subtitle:(NSString *)subtitle {
        // Fired when a subtitle should be displayed.
    }
    /**
     @brief Callback for hiding subtitles.
     @param player The player pointer.
     @param trackIndex The index of the subtitle stream.
     @param subtitleID The subtitle ID.
     */
    - (void)onSubtitleHide:(AliPlayer*)player trackIndex:(int)trackIndex subtitleID:(long)subtitleID {
        // Fired when a subtitle should be hidden.
    }
    /**
     @brief Callback for taking a snapshot.
     @param player The player pointer.
     @param image The image.
     */
    - (void)onCaptureScreen:(AliPlayer *)player image:(UIImage *)image {
        // Preview and save the snapshot.
    }
    /**
     @brief Callback for track switching.
     @param player The player pointer.
     @param info The information about the new track. For more information, see AVPTrackInfo.
     */
    - (void)onTrackChanged:(AliPlayer*)player info:(AVPTrackInfo*)info {
        // Fired when the playback track changes, for example, after a bitrate switch.
    }
    //...
  3. Defina a contagem de pré-carregamento.

    Configure uma contagem de pré-carregamento adequada para reduzir efetivamente o TTTF. Exemplo:

    self.listPlayer.preloadCount = 2;
  4. Adicione ou remova fontes de reprodução.

    A reprodução em lista suporta dois tipos de fontes: VidSts e UrlSource. A reprodução UrlSource utiliza uma URL de reprodução, enquanto a reprodução VidSts usa o VideoId de um ativo de mídia no ApsaraVideo VOD.

    • URL: O endereço de reprodução pode ser de um serviço de terceiros ou do ApsaraVideo VOD.

      Recomendamos integrar o SDK server-side do ApsaraVideo VOD para obter endereços de reprodução, pois isso simplifica o processo ao lidar automaticamente com a assinatura de URLs. Para ver um exemplo de chamada de operação de API, consulte Developer Portal.

    • Vid: O VideoId. Você pode obter o VideoId após carregar o arquivo de mídia. Encontre-o no console do ApsaraVideo VOD em Media Asset Library > Audio/Video ou chamando uma API server-side como Pesquisar informações de mídia.

    // Add a VidSts playback source.
    [self.listPlayer addVidSource:videoId uid:UUIDString];
    // Add a UrlSource playback source.
    [self.listPlayer addUrlSource:URL uid:UUIDString];
    // Remove a source.
    [self.listPlayer removeSource:UUIDString];
    Nota
    • O uid é um identificador exclusivo para cada vídeo. O player trata vídeos com o mesmo uid como idênticos. Se encontrar mistura de streams, verifique se não atribuiu o mesmo uid a vídeos diferentes. O uid não tem requisitos de formato e pode ser qualquer string.

  5. Defina a view de exibição.

    Se uma fonte de reprodução contiver vídeo, defina uma view no player para exibir os quadros de vídeo.

    self.listPlayer.playerView = self.simplePlayScrollView.playView;
  6. Reproduza uma fonte.

    Após adicionar as fontes de reprodução, chame moveTo para iniciar a reprodução de uma fonte específica.

    // Use this API for UrlSource playback.
    - (BOOL) moveTo:(NSString*)uid;
    // For VidSts playback. You must pass the components of a temporary STS credential: the AccessKey ID, AccessKey Secret, and STS token. For more information on obtaining these, see 'Create a RAM role and grant temporary access permissions by using STS'.
    - (BOOL) moveTo:(NSString*)uid accId:(NSString*)accId accKey:(NSString*)accKey token:(NSString*)token region:(NSString*)region;
  7. Reproduza o vídeo anterior ou seguinte.

    Depois de chamar moveTo para reproduzir uma fonte de vídeo, as operações moveToPrev e moveToNext usam a fonte de vídeo da chamada moveTo como âncora para reproduzir os vídeos anterior e seguinte. Veja um exemplo abaixo:

    Nota

    Alternar fontes de vídeo na mesma view com métodos como moveTo ou moveToNext pode causar cintilação na tela ou deixá-la preta momentaneamente. Para evitar isso, defina o campo clearShowWhenStop de PlayerConfig como false ao inicializar listPlayer e, em seguida, chame setConfig para aplicar a alteração.

    UrlSource

    // Move to the next video.
    - (BOOL) moveToNext;
    // Move to the previous video.
    - (BOOL) moveToPrev;

    VidSts

    // Move to the next video.
    - (BOOL) moveToNext:(NSString*)accId accKey:(NSString*)accKey token:(NSString*)token region:(NSString*)region;
    // Move to the previous video.
    - (BOOL) moveToPre:(NSString*)accId accKey:(NSString*)accKey token:(NSString*)token region:(NSString*)region;
Nota

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.

  1. 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.

  2. 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.

  3. Maior compatibilidade: Como formato de vídeo universal, o MP4 é amplamente suportado na maioria dos dispositivos e navegadores.

  4. 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

Uma nova API permite definir o modo alfa, que especifica a posição do canal alfa no ativo de vídeo: superior, inferior, esquerda ou direita. O valor padrão é none.

Nota
  • A posição do canal alfa no ativo deve corresponder à configuração alphaRenderMode.

  • A proporção da view do player deve corresponder à da saída final, e não à do ativo de origem inteiro.

/**
 @brief Alpha rendering mode. Supports alpha at the right, left, top, or bottom. The default value is none.
 @see AVPAlphaRenderMode
 */
@property(nonatomic) AVPAlphaRenderMode alphaRenderMode;
//--------------View usage-------------
// For the player's view, set a clear background color.
@property (weak, nonatomic) IBOutlet UIView *mediaPlayerView;
[self.aliplayerview setBackgroundColor:UIColor.clearColor];

//-----------AliPlayer usage-----------
// Set the alpha mode.
[self.player setAlphaRenderMode:AVP_RENDERMODE_ALPHA_AT_LEFT];
// Set the asset that matches the alpha mode.
AVPUrlSource *source = [[AVPUrlSource alloc] urlWithString:@"https://alivc-player.oss-cn-shanghai.aliyuncs.com/video/business_needs_sample/alpha_channel/alpha_left.mp4"];
[self.player setUrlSource:source];

// Optional: If you encounter visual artifacts after playback completes, you can clear the screen.
#pragma mark -- AVPDelegate
- (void)onPlayerEvent:(AliPlayer *)player eventType:(AVPEventType)eventType {
    switch (eventType) {
        case AVPEventCompletion:
        {
            [player clearScreen];
        }
            break;
        //...
    }
}

[self.player setAutoPlay: YES];
[self.player prepare];

Renderização Metal

O Alibaba Cloud Player SDK para iOS suporta renderização de vídeo usando o framework Metal.

Nota

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

Nota

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.

  1. 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];
  2. 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];
    }
  3. Adicione uma faixa de legenda.

    [self.player addExtSubtitle:URL];
  4. 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.

Nota

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.

Importante

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

  1. 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
  2. (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);
        }
    }
  3. 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];
  4. 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.

Nota
  • 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

Nota

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];
Nota

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.

Nota

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];
Nota
  • Se networkRetryCount for maior que 0, o player tentará novamente até networkRetryCount vezes quando ocorrer um problema de rede durante o carregamento. O intervalo entre tentativas é determinado por networkTimeout.

  • Se o player falhar ao carregar após todas as tentativas, o callback onError será acionado, e AVPErrorModel.code será ERROR_LOADING_TIMEOUT.

  • Se networkRetryCount for 0, um timeout de rede acionará o callback onPlayerEvent com o parâmetro eventWithString definido como EVENT_PLAYER_NETWORK_RETRY. Você pode então chamar o método reload do 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];
Importante
  • 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

Nota

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.

Nota
  • 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;
    }
}
Nota

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.

  1. 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];
  2. Adicione propriedades e implemente os métodos do delegate.

    1. 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;
      
      @end
      Nota

      A propriedade pipController deve ser declarada com um atributo weak ou assign para evitar ciclos de retenção. Se você usar assign, defina manualmente a propriedade como nil no momento apropriado.

    2. 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];
         }
      }
    3. 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];
          }
        }
      }
    4. 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;
        }
        Nota

        Este callback é invocado antes do início do Picture-in-Picture. Ele deve retornar false neste ponto para que a janela PiP seja iniciada. Retornar true impede 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

Nota

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.

Nota

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

  1. Player SDK ou all-in-one SDK V7.6.0 ou posterior.

  2. Você possui uma licença da Professional Edition. Para mais informações, consulte Obter uma licença.

  3. 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

Player SDK

CocoaPods (recomendado)

Adicione a dependência do plugin ao seu Podfile:

Nota

Para a versão mais recente, consulte o Histórico de Lançamentos do iOS SDK.

// Replace x.x.x with the version of your Player SDK.
pod 'AliPlayerSDK_iOS_VVC_CODEC_PLUGIN', 'x.x.x'

Integração local

Baixe a versão mais recente do Player SDK para iOS, adicione o arquivo vvcCodecPlugin.framework em Frameworks, Libraries, and Embedded Content, defina Embed como Embed & Sign e configure os Framework Search Paths. Para detalhes, consulte Integração local.

all-in-one SDK

CocoaPods (recomendado)

Adicione a dependência do plugin ao seu Podfile:

// Replace x.x.x with the version of your all-in-one SDK.
pod 'AliVCSDK_Standard/AliPlayerSDK_iOS_VVC_CODEC', 'x.x.x'

Integração local

Baixe a versão mais recente do pacote all-in-one SDK para iOS. Descompacte o pacote e adicione o arquivo plugins/vvcCodecPlugin.framework em Frameworks, Libraries, and Embedded Content no seu projeto, defina Embed como Embed & Sign e configure os Framework Search Paths. Para detalhes, consulte Integração local.

Ativar o plugin

Nota

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

  1. O player ou SDK integrado deve ser da versão 7.9.0 ou posterior.

  2. 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

/**
 @protocol AVPSourceRefreshCallback
 @brief A protocol for handling the results of a source refresh, which you must implement.

 This protocol notifies your application when the player requests a source refresh, such as when a resource
 has expired or needs to be updated. The methods in this protocol are called to provide the refresh results,
 including success or failure.

 @note This protocol applies to URL sources, VidAuth sources, and similar scenarios that require refresh logic.
 */
@protocol AVPSourceRefreshCallback <NSObject>

/**
 @brief Called by the player when the refresh operation succeeds.
 
 @param newSource The new source object containing the updated information.

 This method indicates that the refresh operation has been successfully completed. You must pass
 the updated `newSource` back to the player so that it can load the new resource.
 */
- (void)onSuccess:(id)newSource;

/**
 @brief Called by the player when the refresh operation fails.
 
 @param errorMsg A string describing the reason for the failure.

 This method indicates that the refresh operation has failed. You can use `errorMsg` to capture failure
 details and handle the error accordingly.
 */
- (void)onError:(NSString *)errorMsg;

@end

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

/**
 @protocol AVPSourceRefreshCallback
 @brief A protocol for handling the results of a source refresh, which you must implement.

 This protocol notifies your application when the player requests a source refresh, such as when a resource
 has expired or needs to be updated. The methods in this protocol are called to provide the refresh results,
 including success or failure.

 @note This protocol applies to URL sources, VidAuth sources, and similar scenarios that require refresh logic.
 */
@protocol AVPSourceRefreshCallback <NSObject>

/**
 @brief Called by the player when the refresh operation succeeds.
 
 @param newSource The new source object containing the updated information.

 This method indicates that the refresh operation has been successfully completed. You must pass
 the updated `newSource` back to the player so that it can load the new resource.
 */
- (void)onSuccess:(id)newSource;

/**
 @brief Called by the player when the refresh operation fails.
 
 @param errorMsg A string describing the reason for the failure.

 This method indicates that the refresh operation has failed. You can use `errorMsg` to capture failure
 details and handle the error accordingly.
 */
- (void)onError:(NSString *)errorMsg;

@end

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.

#import "CdnAuthUtil.h"
#import <CommonCrypto/CommonDigest.h>

@implementation CdnAuthUtil

#pragma mark - Auth Method A
+ (NSString *)aAuthWithUri:(NSString *)uri key:(NSString *)key exp:(NSTimeInterval)exp {
    NSDictionary *components = [self matchUri:uri];
    if (!components) return nil;

    NSString *scheme = components[@"scheme"];
    NSString *host = components[@"host"];
    NSString *path = components[@"path"];
    NSString *args = components[@"args"];

    NSString *rand = @"0";
    NSString *uid = @"0";

    NSString *sstring = [NSString stringWithFormat:@"%@-%lld-%@-%@-%@", path, (long long)exp, rand, uid, key];
    NSString *hashvalue = [self md5sum:sstring];
    NSString *authKey = [NSString stringWithFormat:@"%lld-%@-%@-%@", (long long)exp, rand, uid, hashvalue];

    if (args.length > 0) {
        return [NSString stringWithFormat:@"%@%@%@%@&auth_key=%@", scheme, host, path, args, authKey];
    } else {
        return [NSString stringWithFormat:@"%@%@%@%@?auth_key=%@", scheme, host, path, args, authKey];
    }
}

#pragma mark - Private Helper: MD5
+ (NSString *)md5sum:(NSString *)src {
    const char *cStr = [src UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(cStr, (unsigned int)strlen(cStr), result);

    NSMutableString *hexString = [NSMutableString string];
    for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        [hexString appendFormat:@"%02x", result[i]];
    }
    return hexString.copy;
}

#pragma mark - Private Helper: Regex Match
+ (NSDictionary *)matchUri:(NSString *)uri {
    NSError *error = nil;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^(https?://)?([^/?]+)(/[^?]*)?(\\?.*)?$"
                                  options:0
                                  error:&error];
    if (error) {
        NSLog(@"Regex error: %@", error.localizedDescription);
        return nil;
    }

    NSTextCheckingResult *match = [regex firstMatchInString:uri
                                   options:0
                                   range:NSMakeRange(0, uri.length)];
    if (!match) return nil;

    __block NSString *scheme = nil, *host = nil, *path = nil, *args = nil;

    void (^setStringFromRange)(NSInteger, NSString**) = ^(NSInteger idx, NSString **outStr) {
        NSRange range = [match rangeAtIndex:idx];
        if (range.location != NSNotFound && range.length > 0) {
            *outStr = [uri substringWithRange:range];
        } else {
            *outStr = nil;
        }
    };

    setStringFromRange(1, &scheme);
    setStringFromRange(2, &host);
    setStringFromRange(3, &path);
    setStringFromRange(4, &args);

    // Handle default values.
    if (!scheme) scheme = @"http://";
    if (!path) path = @"/";

    return @{
        @"scheme": scheme,
        @"host": host,
        @"path": path,
        @"args": args ?: @""
        };
}
@end

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

  1. O ApsaraVideo Player SDK para iOS ou o all-in-one SDK deve ser v7.13.0 ou posterior.

  2. Você deve ter uma Licença da Professional Edition. Para mais informações, consulte Obter uma licença para ApsaraVideo Player SDK.

Importante

O recurso de melhoria de áudio suporta as seguintes fontes de áudio:

Integrar plugin

Integração CocoaPods

Adicione a dependência do plugin ao seu Podfile:

Nota

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

enable_surround

Boolean

Especifica se deve ativar o recurso de som surround.

surround_effect_type

String

O modo de som surround. Valores válidos: "3DSurround" e "MegaBass".

enable_dialoguenhance

Boolean

Especifica se deve ativar o recurso de melhoria de diálogo.

dialoguenhance_voice

Float

A intensidade da melhoria de diálogo. Intervalo: 1,0 a 10,0.

enable_normalizer

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.

Nota

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];
Importante

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.

Nota
  • Após definir uma cena do player, você pode chamar o método getConfig para 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.

Nota
  1. Este recurso está desativado por padrão.

  2. Você deve definir a View do player antes de chamar Prepare para garantir que o quadro seja renderizado na View assim que estiver pronto.

  3. 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

Nota

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];
Nota
  • 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 como http://****.mp4?aaa, calcule o hash usando http://****.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 callback setCacheUrlHashCallback, 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://****.mp4 e http://****.mp4, use ****.mp4 para calcular o valor hash.

    • Se a URL de reprodução for https://****.mp4, você pode usar consistentemente http://****.mp4 para 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.enableStrictAuthMode para 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:

  1. Ative o cache local global.

    Você deve ativar manualmente este recurso usando o método enableLocalCache em AliPlayerGlobalSettings. Para um exemplo de código, consulte Ativar cache local em Cache local.

  2. Ative o cache local para a URL.

    Para um exemplo de código, consulte Ativar ou desativar cache para uma URL em Cache local.

  3. 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.

Nota

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];
  1. Ative o recurso de cache local conforme descrito em Cache local.

  2. 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];
  3. Defina os parâmetros da tarefa.

    Nota

    Esses parâmetros aplicam-se apenas a vídeos de múltiplas taxas de bits. Você precisa definir apenas um entre setDefaultBandWidth, setDefaultResolution e setDefaultQuality.

    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];
  4. Adicione um listener de tarefa.

    Exemplo de código

    @interface YourViewController () <OnPreloadListener>
    
    @property(nonatomic,strong) AliMediaLoaderV2* vodMedialoader; // The preloader.
    @property(nonatomic,strong) AVPVidAuthSource* vidSource; // The VidAuth data source.
    @property(nonatomic,strong) AVPUrlSource* urlSource; // The UrlSource data source.
    @property(nonatomic,strong) AVPVidStsSource* vidStsSource; // The VidSts data source.
    
    @end
    
    @implementation YourViewController
    
    - (void)onCompleted:(NSString *)taskId urlOrVid:(NSString *)urlOrVid {
        NSLog(@"Current task (%@) completed: %@", taskId,urlOrVid);
    }
    
    - (void)onError:(NSString *)taskId urlOrVid:(NSString *)urlOrVid errorModel:(AVPErrorModel *)errorModel {
        NSLog(@"An error occurred: %@", urlOrVid);
    }
    
    - (void)onCanceled:(NSString *)taskId urlOrVid:(NSString *)urlOrVid {
        NSLog(@"Task canceled: %@", urlOrVid);
    }
    
    @end
  5. Construa a tarefa, adicione-a à instância MediaLoaderV2 e 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];
  6. 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.
  7. 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.

Exemplo de código

// Enable the recommended configuration and dynamic preloading.
[self.listPlayer setScene:AVP_SHORT_VIDEO];

// Configure the base preload duration.
// Set the preload duration to 1,000 ms.
AVPPreloadConfig *config = [[AVPPreloadConfig alloc] init];
config.preloadDuration = 1000;
[self.listPlayer updatePreloadConfig:config];

// Configure the number of items to preload. This supports preloading in both directions.
// 1 is the number of previous items to preload, and 3 is the number of next items to preload.
[self.listPlayer setPreloadCount:1 nextCount:3];

// Configure the decreasing offset for dynamic preloading.
[self.listPlayer enableStrategy:AVP_STRATEGY_DYNAMIC_PRELOAD enable:true];
[self.listPlayer setStrategyParam:AVP_STRATEGY_DYNAMIC_PRELOAD strategyParam:@"{\"algorithm\": \"sub\",\"offset\": \"200\"}"];

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.

Modes de pré-carregamento suportados

typedef enum AVPMultiBitratesMode : NSUInteger {
    /**
     * Default configuration. Plays and preloads the default bitrate.
     */
    AVPMultiBitratesMode_Default = 0,
    /**
     * Prioritizes a fast time to first frame. The player starts by playing the bitrate that has finished preloading.
     */
    AVPMultiBitratesMode_FCPrio = 1,
    /**
     * Balances a fast time to first frame with smooth playback. The player attempts to play the same bitrate before and after a `moveToNext` call.
     */
    AVPMultiBitratesMode_FC_AND_SMOOTH = 2,
    /**
     * Prioritizes smooth playback. The player attempts to start the next video at the same bitrate as the previous one.
     */
    AVPMultiBitratesMode_SmoothPrio = 3,
} AVPMultiBitratesMode;

Código de integração

// Select the multi-bitrate loading mode.
[self.listPlayer->SetMultiBitratesMode(preLoadMode)];

// Optional: Select the startup bitrate.
[self.listPlayer setDefaultBandWidth:defaultBandWidth];

// Optional: In the onPlayerEvent callback for AVPEventPrepareDone, select the adaptive bitrate (ABR) mode.
-(void)onPlayerEvent:(AliPlayer*)player eventType:(AVPEventType)eventType {
    switch (eventType) {
        case AVPEventPrepareDone: {
            [self.listPlayer selectTrack:-1];
        }
            break;
        case AVPEventFirstRenderedStart: {
        }
            break;
        default:
            break;
    }
}

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

Nota

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

Nota
  • 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

Nota

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

  1. Opcional: Configure o arquivo de chave para download seguro. Esta etapa é necessária apenas para download seguro.

    Nota

    Certifique-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];
  2. 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];
  3. 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.
    }
  4. Prepare a fonte de download.

    Chame o método prepare para 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];
    Nota

    Se 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.

  5. 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âmetro mediaInfo do 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];
    }
  6. 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];
  7. Libere o downloader após a conclusão ou falha do download.

    Chame o método destroy para 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.

Referências