Observação, para a pergunta abaixo: Todos os ativos são locais no dispositivo - nenhum streaming de rede está ocorrendo. Os vídeos contêm faixas de áudio.
Estou trabalhando em um aplicativo iOS que requer a reprodução de arquivos de vídeo com atraso mínimo para iniciar o videoclipe em questão. Infelizmente, não sabemos qual será o próximo videoclipe até que realmente precisemos iniciá-lo. Especificamente: Quando um videoclipe está sendo reproduzido, saberemos qual é o próximo conjunto de (aproximadamente) 10 videoclipes, mas não sabemos qual exatamente, até que chegue a hora de reproduzir "imediatamente" o próximo clipe.
O que fiz para ver os atrasos reais de início foi chamar addBoundaryTimeObserverForTimes
o player de vídeo, com um período de um milissegundo para ver quando o vídeo realmente começou a ser reproduzido, e considero a diferença desse carimbo de hora com o primeiro lugar em o código que indica qual ativo começar a jogar.
Pelo que vi até agora, descobri que usar a combinação de AVAsset
carregamento e, em seguida, criar um a AVPlayerItem
partir disso quando estiver pronto e, em seguida, esperar AVPlayerStatusReadyToPlay
antes de chamar o jogo, tende a levar entre 1 e 3 segundos para iniciar o grampo.
Desde então mudei para o que considero mais ou menos equivalente: ligar [AVPlayerItem playerItemWithURL:]
e esperar para AVPlayerItemStatusReadyToPlay
jogar. Praticamente o mesmo desempenho.
Uma coisa que estou observando é que o carregamento do primeiro item do AVPlayer é mais lento do que o resto. Parece que uma ideia é fazer um pré-voo do AVPlayer com um ativo curto / vazio antes de tentar reproduzir o primeiro vídeo. Isso pode ser uma boa prática geral. [ Início lento para AVAudioPlayer na primeira vez que um som é reproduzido
Eu adoraria diminuir o tempo de início do vídeo o máximo possível e ter algumas ideias de coisas para experimentar, mas gostaria de receber orientação de alguém que possa ajudar.
Atualização: a ideia 7, abaixo, conforme implementada, produz tempos de comutação de cerca de 500 ms. Isso é uma melhoria, mas seria bom fazer isso ainda mais rápido.
Ideia 1: Use N AVPlayers (não funciona)
Usando ~ 10 AVPPlayer
objetos, inicie e pause todos os ~ 10 clipes e, quando soubermos qual deles realmente precisamos, mude para e retome o correto AVPlayer
e comece tudo de novo para o próximo ciclo.
Não acho que isso funcione, porque li que há um limite de 4 ativos AVPlayer's
no iOS. Alguém perguntou sobre isso no StackOverflow aqui e descobriu sobre o limite de 4 AVPlayer: fast-switching-between-videos-using-avfoundation
Ideia 2: Use AVQueuePlayer (não funciona)
Não acredito que enfiar 10 AVPlayerItems
em um AVQueuePlayer
pré-carregue todos eles para um início perfeito. AVQueuePlayer
é uma fila e acho que realmente só deixa o próximo vídeo da fila pronto para reprodução imediata. Não sei qual dos cerca de 10 vídeos queremos reproduzir, até que seja hora de começar esse. ios-avplayer-video-preloading
Ideia 3: carregar, reproduzir e manter AVPlayerItems
em segundo plano (ainda não tenho 100% de certeza - mas não parece bom)
Estou verificando se há algum benefício em carregar e reproduzir o primeiro segundo de cada videoclipe em segundo plano (suprimir a saída de vídeo e áudio) e manter uma referência para cada um AVPlayerItem
e quando sabemos qual item precisa ser reproduzido real, troque aquele em, e troque o AVPlayer de fundo com o ativo. Enxague e repita.
A teoria seria que os reproduzidos recentemente AVPlayer/AVPlayerItem
ainda podem conter alguns recursos preparados que tornariam a reprodução subsequente mais rápida. Até agora, não vi benefícios disso, mas posso não ter a AVPlayerLayer
configuração correta para o plano de fundo. Duvido que isso realmente melhore as coisas pelo que tenho visto.
Ideia 4: Use um formato de arquivo diferente - talvez um que seja mais rápido de carregar?
No momento, estou usando o formato .m4v (vídeo-MPEG4) H.264. O H.264 tem várias opções de codec diferentes, portanto, é possível que algumas opções sejam mais rápidas de procurar do que outras. Descobri que o uso de configurações mais avançadas que tornam o tamanho do arquivo menor aumenta o tempo de busca, mas não encontrei nenhuma opção que vá de outra maneira.
Ideia 5: Combinação de formato de vídeo sem perdas + AVQueuePlayer
Se houver um formato de vídeo que carregue rapidamente, mas talvez o tamanho do arquivo seja insano, uma ideia pode ser preparar os primeiros 10 segundos de cada clipe de vídeo com uma versão que está inchada, mas mais rápida de carregar, mas de volta isso com um recurso codificado em H.264. Use um AVQueuePlayer e adicione os primeiros 10 segundos no formato de arquivo descompactado e, em seguida, use um que esteja em H.264, que obtém até 10 segundos de preparação / pré-carregamento. Portanto, eu obteria 'o melhor' dos dois mundos: tempos de início rápidos, mas também se beneficia de um formato mais compacto.
Ideia 6: Usar um AVPlayer não padrão / escrever meu / usar o de outra pessoa
Dadas as minhas necessidades, talvez eu não possa usar o AVPlayer, mas tenho que recorrer a AVAssetReader e decodificar os primeiros segundos (possivelmente gravar o arquivo bruto no disco) e, quando se trata de reprodução, fazer uso do formato bruto para reproduzi-lo de volta rápido. Parece um grande projeto para mim, e se eu fizer isso de uma forma ingênua, é pouco claro / improvável que funcione melhor. Cada quadro de vídeo decodificado e descompactado tem 2,25 MB. Falando ingenuamente - se usarmos ~ 30 fps para o vídeo, eu acabaria com o requisito de leitura do disco de ~ 60 MB / s, o que provavelmente é impossível / forçando-o. Obviamente, teríamos que fazer algum nível de compressão de imagem (talvez formatos de compressão openGL / es nativos via PVRTC) ... mas isso é meio louco. Talvez haja uma biblioteca que eu possa usar?
Ideia 7: Combine tudo em um único recurso de filme e procureToTime
Uma ideia que pode ser mais fácil do que algumas das anteriores, é combinar tudo em um único filme e usar seekToTime. O fato é que estaríamos pulando por todo o lugar. Acesso essencialmente aleatório ao filme. Acho que isso pode realmente funcionar bem: avplayer-movie-playing-lag-in-ios5
Qual abordagem você acha que seria a melhor? Até agora, não fiz muito progresso em termos de redução do atraso.