O streaming de vídeo é parte integrante da experiência moderna da Internet. Está em todo lugar: em telefones celulares, computadores desktop, TVs e até mesmo em wearables. Ele precisa funcionar perfeitamente em cada dispositivo e tipo de rede, seja em conexões móveis lentas, WiFi, atrás de firewalls, etc. HTTP Live Streaming da Apple (HLS) foi criado exatamente com esses desafios em mente.
Quase todos os dispositivos modernos vêm equipados com hardware moderno que é rápido o suficiente para reproduzir vídeo, de modo que a velocidade e a confiabilidade da rede surgem como o maior problema. Por que é que? Até alguns anos atrás, a maneira canônica de armazenar e publicar vídeo eram protocolos baseados em UDP, como RTP. Isso se provou problemático de várias maneiras, para listar apenas alguns:
Claro, você pode pensar que todos esses problemas são fáceis de resolver. Basta armazenar arquivos de vídeo (por exemplo, arquivos mp4) em seu servidor http e usar seu serviço CDN favorito para atendê-los em qualquer lugar do mundo.
Isso está longe de ser a melhor solução por alguns motivos, eficiência sendo um deles . Se você armazenar arquivos de vídeo originais em resolução total, os usuários em áreas rurais ou partes do mundo com conectividade fraca terão dificuldade em apreciá-los. Seus reprodutores de vídeo terão dificuldade em baixar dados suficientes para reproduzi-los em tempo de execução.
Portanto, você precisa de uma versão especial do arquivo para que a quantidade de vídeo baixada seja aproximadamente a mesma que pode ser reproduzida. Por exemplo, se a resolução e a qualidade do vídeo são tais que em cinco segundos ele pode baixar outros cinco segundos de vídeo, isso é ideal. No entanto, se demorar cinco segundos para baixar apenas três segundos de vídeo, o player irá parar e aguardar o próximo trecho do stream para baixar.
Por outro lado, reduzir ainda mais a qualidade e a resolução só degradaria a experiência do usuário em conexões mais rápidas, pois você estaria economizando largura de banda desnecessariamente. No entanto, existe uma terceira via.
Embora você possa enviar diferentes versões de vídeo para diferentes usuários, então você precisa ter a capacidade de controlar seus jogadores e calcular qual é o melhor stream para sua conexão e dispositivo. Em seguida, o jogador precisa alternar entre eles (por exemplo, quando um usuário muda de 3G para WiFi). E mesmo assim, e se o cliente mudar o tipo de rede? Em seguida, o player deve alternar para um vídeo diferente, mas deve começar a jogar não desde o início, mas em algum lugar no meio do vídeo. Então, como você calcula o intervalo de bytes a ser solicitado?
Uma coisa legal seria se os reprodutores de vídeo pudessem detectar mudanças no tipo de rede e na largura de banda disponível e, em seguida, alternar de forma transparente entre diferentes fluxos (do mesmo vídeo preparado para velocidades diferentes) até encontrar o melhor.
Isso é exatamente o que Streaming de taxa de bits adaptável resolve.
Nota: Este tutorial de HLS não cobrirá criptografia, reproduções sincronizadas e IMSC1.
HTTP Live Streaming é um protocolo de transmissão de taxa de bits adaptável introduzido pela Apple em 2009. Ele usa arquivos m3u8 para descrever fluxos de mídia e usa HTTP para a comunicação entre o servidor e o cliente. É o protocolo de streaming de mídia padrão para todos dispositivos iOS , mas pode ser usado em navegadores Android e web.
Os blocos de construção básicos de um fluxo HLS são:
Vamos começar respondendo a uma pergunta básica: O que são arquivos M3U8 ?
M3U (ou M3U8) é um formato de arquivo de texto simples criado originalmente para organizar coleções de arquivos MP3. O formato é estendido para HLS, onde é usado para definir fluxos de mídia. No HLS, existem dois tipos de arquivos m3u8:
Um URL de transmissão ao vivo chamado M3U8 nada mais é do que URLs para arquivos M3U8, como: https://s3-us-west-2.amazonaws.com/hls-playground/hls.m3u8 .
Um arquivo M3U8 contém uma lista de urls ou caminhos de arquivos locais com alguns metadados adicionais. As linhas de metadados começam com #.
por que usar ruby on rails
Este exemplo ilustra a aparência de um arquivo M3U8 para um fluxo HLS simples:
#EXTM3U #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-ALLOW-CACHE:YES #EXT-X-TARGETDURATION:11 #EXTINF:5.215111, 00000.ts #EXTINF:10.344822, 00001.ts #EXTINF:10.344822, 00002.ts #EXTINF:9.310344, 00003.ts #EXTINF:10.344822, 00004.ts ... #EXT-X-ENDLIST
EXT-X-VERSION
é a versão do formato M3U8 (deve ser pelo menos 3 se quisermos usar entradas EXTINF
).EXT-X-TARGETDURATION
tag contém a duração máxima de cada “pedaço” de vídeo. Normalmente, esse valor é cerca de 10s. #EXTINF:10.344822, 00001.ts
Este é um “pedaço” de vídeo. Este representa o 00001.ts
pedaço que tem exatamente 10,344822 segundos de duração. Quando um reprodutor de vídeo cliente precisa iniciar um vídeo a partir de um determinado ponto no referido vídeo, ele pode calcular facilmente qual .ts
arquivo que ele precisa para solicitar somando as durações de pedaços visualizados anteriormente. A segunda linha pode ser um nome de arquivo local ou um URL para esse arquivo.
O arquivo M3U8 com seu .ts
os arquivos representam a forma mais simples de um fluxo HLS - uma lista de reprodução de mídia. Você pode abrir um exemplo simples Aqui .
Lembre-se de que nem todo navegador pode reproduzir streams HLS por padrão.
O exemplo anterior do M3U8 aponta para uma série de .ts
pedaços. Eles são criados a partir do arquivo de vídeo original, que é redimensionado, codificado e dividido em partes.
Isso significa que ainda temos o problema descrito na introdução - e os clientes em redes muito lentas (ou excepcionalmente rápidas)? Ou clientes em redes rápidas com telas muito pequenas? Não faz sentido transmitir um arquivo em resolução máxima se ele não puder ser mostrado em toda a sua glória em seu novo telefone.
O HLS resolve esse problema introduzindo outra “camada” de M3U8. Este arquivo M3U8 não vou contêm ponteiros para .ts
arquivos, mas tem ponteiros para outros arquivos M3U8 que, por sua vez, contêm arquivos de vídeo preparados com antecedência para taxas de bits e resoluções específicas.
Aqui está um exemplo de um arquivo M3U8:
#EXTM3U #EXT-X-STREAM-INF:BANDWIDTH=1296,RESOLUTION=640x360 https://.../640x360_1200.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=264,RESOLUTION=416x234 https://.../416x234_200.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=464,RESOLUTION=480x270 https://.../480x270_400.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=1628,RESOLUTION=960x540 https://.../960x540_1500.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=2628,RESOLUTION=1280x720 https://.../1280x720_2500.m3u8
O player de vídeo escolherá pares de linhas, como:
#EXT-X-STREAM-INF:BANDWIDTH=1296,RESOLUTION=640x360 https://.../640x360_1200.m3u8
Estes são chamados variantes do mesmo vídeo preparado para diferentes velocidades de rede e resoluções de tela. Este arquivo M3U8 específico (640x360_1200.m3u8
) contém os pedaços do arquivo de vídeo redimensionados para 640 x 360 pixels e preparado para taxas de bits de 1296 kbps . Observe que a taxa de bits relatada deve levar em consideração ambos os fluxos de vídeo e áudio No vídeo.
O player de vídeo geralmente começa a reproduzir a partir do primeiro stream variante (no exemplo anterior, é 640x360_1200.m3u8). Por esse motivo, você deve tomar cuidado especial para decidir qual variante será a primeira da lista. A ordem das outras variantes não é importante.
Se o primeiro arquivo .ts demorar muito para baixar (causando 'buffering', ou seja, aguardando a próxima parte), o player de vídeo mudará para um para um stream com uma taxa de bits menor. E, claro, se for carregado rápido o suficiente, isso significa que pode mudar para uma qualidade melhor variante , mas apenas se isso fizer sentido para a resolução da tela.
Se o primeiro fluxo na lista do índice M3U8 não for o melhor, o cliente precisará de um ou dois ciclos até que se estabeleça com a variante certa.
Então, agora temos três camadas de HLS:
.ts
arquivos (pedaços) que são arquivos binários com partes do vídeo.Você pode assistir a um exemplo de arquivo de índice M3U8 Aqui (novamente, depende do seu navegador / sistema operacional).
projeto nativo de reação aberta no Android Studio
Às vezes, você sabe com antecedência que o cliente está em uma rede lenta ou rápida. Nesse caso, você pode ajudar o cliente a escolher a variante certa, fornecendo um arquivo de índice M3U8 com uma primeira variante diferente. Há duas maneiras de fazer isso.
http://.../index_wifi.m3u8
ou http://.../index_mobile.m3u8
.Existem dois blocos de construção importantes do HTTP Live Streaming da Apple. Uma é a maneira como os arquivos de vídeo são armazenados (para serem servidos via HTTP posteriormente) e a outra é a M3U8 arquivo (s) de índice que informa ao jogador (o aplicativo cliente de streaming) onde obter qual arquivo de vídeo.
Vamos começar com arquivos de vídeo. O protocolo HLS espera que os arquivos de vídeo sejam armazenados em pedaços menores de igual duração, normalmente 10 segundos cada. Originalmente, esses arquivos precisavam ser armazenados em arquivos MPEG-2 TS (.ts
) e codificados com o formato H.264 com áudio em MP3, HE-AAC ou AC-3.
Isso significa que um vídeo de 30 segundos será dividido em 3 menores .ts
arquivos, cada um com aproximadamente 10 segundos de comprimento.
Observe que a versão mais recente do HLS também permite arquivos .mp4 fragmentados. Como isso ainda é uma coisa nova e alguns reprodutores de vídeo ainda precisam implementá-lo, os exemplos neste artigo usarão .ts
arquivos.
Os pedaços devem ser codificados com um quadro-chave no início de cada arquivo. Cada vídeo contém quadros. Os frames são imagens, mas os formatos de vídeo não armazenam imagens completas, o que ocuparia muito espaço em disco. Eles codificam apenas a diferença do quadro anterior. Quando você pula para um ponto intermediário no vídeo, o player precisa de um “ponto de partida” de onde aplicar todas as diferenças para mostrar a imagem inicial e, em seguida, começar a reproduzir o vídeo.
É por isso que .ts
os pedaços devem ter um quadro-chave no início. Às vezes, os jogadores precisam começar no meio do bloco. O jogador sempre pode calcular a imagem atual adicionando todos os “diffs” do primeiro quadro-chave. Mas, se começar 9 segundos desde o início, ele precisa calcular 9 segundos de “diferenças”. Para tornar esse cálculo mais rápido, é melhor criar quadros-chave a cada poucos segundos (melhor cca 3s).
Existem situações em que você deseja que vários videoclipes sejam reproduzidos em sucessão. Uma maneira de fazer isso é mesclar os arquivos de vídeo originais e, em seguida, criar os streams HLS com esse arquivo, mas isso é problemático por vários motivos. E se você quiser mostrar um anúncio antes ou depois do seu vídeo? Talvez você não queira fazer isso para todos os usuários e provavelmente deseja anúncios diferentes para usuários diferentes. E, claro, você não deseja preparar arquivos HLS com anúncios diferentes com antecedência.
Para corrigir esse problema, existe uma tag #EXT-X-DISCONTINUITY
que pode ser usado na lista de reprodução m3u8. Essa linha basicamente diz ao reprodutor de vídeo para se preparar com antecedência para o fato de que, a partir deste ponto, o .ts
os arquivos podem ser criados com uma configuração diferente (por exemplo, a resolução pode mudar). O jogador precisará recalcular tudo e possivelmente trocar para outra variante e deverá estar preparado para tais pontos de “descontinuidade”.
Existem basicamente dois tipos de “streaming de vídeo”. Um é Video On Demand ( VOD ) para vídeos gravados com antecedência e transmitidos ao usuário quando ele decidir. E aqui está Transmissão ao vivo . Embora HLS seja uma abreviatura de HTTP Live Streaming, tudo explicado até agora foi centrado em torno de VOD, mas também existe uma maneira de fazer streaming ao vivo com HLS.
Existem algumas mudanças em seus arquivos M3U8. Primeiro, deve haver um #EXT-X-MEDIA-SEQUENCE:1
tag no arquivo variante M3U8. Então, o arquivo M3U8 Não deve termine com #EXT-X-ENDLIST
(que caso contrário deve ser sempre colocado no final).
Enquanto grava sua transmissão, você terá constantemente novos .ts
arquivos. Você precisa anexá-los à lista de reprodução M3U8 e cada vez que adicionar um novo, o contador no #EXT-X-MEDIA-SEQUENCE:
deve ser aumentado em 1.
O player de vídeo verificará o contador. Se alterado desde a última vez, ele saberá se há novos blocos a serem baixados e reproduzidos. Certifique-se de que o arquivo M3U8 seja servido com os cabeçalhos sem cache, porque os clientes continuarão recarregando os arquivos M3U8 esperando que novos blocos sejam reproduzidos.
Outro recurso interessante para streams HLS é que você pode incorporar Web Video Text Track (MTB) arquivos neles. Os arquivos VTT podem ser usados para vários usos. Por exemplo, para um player HLS da web, você pode especificar instantâneos de imagem para várias partes do vídeo. Quando o usuário move o mouse sobre a área do temporizador de vídeo (abaixo do player de vídeo), o player pode mostrar instantâneos daquela posição no vídeo.
Outro uso óbvio para arquivos VTT são as legendas. O fluxo HLS pode especificar várias legendas para vários idiomas:
converter carimbo de data / hora em javascript de data
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID='subs',NAME='English',DEFAULT=YES,AUTOSELECT=YES,FORCED=NO,LANGUAGE='en',CHARACTERISTICS='public.accessibility.transcribes-spoken-dialog, public.accessibility.describes-music-and-sound',URI='subtitles/eng/prog_index.m3u8'
Então, theprog_index.m3u8
parece:
#EXTM3U #EXT-X-TARGETDURATION:30 #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-PLAYLIST-TYPE:VOD #EXTINF:30, 0000.webvtt #EXTINF:30, 0001.webvtt ...
O VTT real (por exemplo 0000.webvtt
):
WEBVTT X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000 00:00:01.000 --> 00:00:03.000 Subtitle -Unforced- (00:00:01.000) 00:00:03.000 --> 00:00:05.000 ...text here... -Unforced- (00:00:03.000) ...text here...
Além dos arquivos VTT, a Apple anunciou recentemente que o HLS apresentará suporte para IMSC1, um novo formato de legenda otimizado para entrega de streaming. Sua vantagem mais importante é que ele pode ser estilizado usando CSS.
A Apple introduziu uma série de ferramentas HSL úteis, que são descritas em mais detalhes no guia oficial HLS .
mediastreamsegmenter
para criar arquivos de segmento dinamicamente a partir de um fluxo de vídeo contínuo.mediastreamvalidator
. Ele verificará suas listas de reprodução M3U8, baixará os arquivos de vídeo e relatará vários problemas. Por exemplo, quando a taxa de bits relatada não é a mesma calculada a partir dos arquivos .ts.Um dos problemas mais frequentes encontrados no vídeo é a sincronização de áudio. Se você achar que o áudio em alguns de seus streams HLS está fora de sincronia com o vídeo (ou seja, um ator abre a boca, mas você percebe que a voz está alguns milissegundos adiantada ou atrasada), é possível que o arquivo de vídeo original tenha sido filmado usando uma taxa de quadros variável. Certifique-se de convertê-lo em taxa de bits constante.
Se possível, é ainda melhor certificar-se de que seu software está configurado para gravar vídeo em uma taxa de quadros constante.
Eu preparei um Aplicativo HLS Android que transmite um HLS predefinido usando o ExoPlayer jogador. Ele mostrará um vídeo e uma lista de “eventos” HLS abaixo dele. Esses eventos incluem: a cada .ts
arquivo baixado ou cada vez que o player decidir mudar para um fluxo de taxa de bits maior ou menor.
Vamos passar pelas partes principais da inicialização do visualizador. Na primeira etapa, recuperaremos o tipo de conexão atual do dispositivo e usaremos essas informações para decidir qual m3u8
arquivo para recuperar.
String m3u8File = 'hls.m3u8'; ConnectivityManager connectivity = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetwork = connectivity.getActiveNetworkInfo(); if (activeNetwork != null && activeNetwork.isConnectedOrConnecting()) { int type = activeNetwork.getType(); int subType = activeNetwork.getSubtype(); if (type == ConnectivityManager.TYPE_MOBILE && subType == TelephonyManager.NETWORK_TYPE_GPRS) { m3u8File = 'hls_gprs.m3u8'; } } String m3u8URL = 'https://s3-us-west-2.amazonaws.com/hls-playground/' + m3u8File;
Observe que isso não é estritamente necessário. O player HLS sempre se ajustará à variante HLS certa após alguns pedaços, mas isso significa que nos primeiros 5 a 20 segundos o usuário pode não assistir à variante ideal do stream.
Lembre-se, a primeira variante no m3u8
arquivo é aquele com o qual o visualizador começará. Como estamos no lado do cliente e podemos detectar o tipo de conexão, podemos pelo menos tentar evitar a troca inicial do jogador entre as variantes, solicitando o m3u8
arquivo que é preparado com antecedência para este tipo de conexão.
Na próxima etapa, inicializamos e iniciamos nosso player HLS:
Handler mainHandler = new Handler(); DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter.Builder() .setEventListener(mainHandler, bandwidthMeterEventListener) .build(); TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter); TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); LoadControl loadControl = new DefaultLoadControl(); SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);
Em seguida, preparamos o player e o alimentamos com o m3u8 certo para este tipo de conexão de rede:
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, 'example-hls-app'), bandwidthMeter); HlsMediaSource videoSource = new HlsMediaSource(Uri.parse(m3u8URL), dataSourceFactory, 5, mainHandler, eventListener); player.prepare(videoSource);
E aqui está o resultado:
Há um requisito da Apple para aplicativos de streaming de vídeo no iOS que eles devo use HLS se os vídeos tiverem mais de 10 minutos ou mais de 5 MB. Isso por si só já é uma garantia de que a HLS veio para ficar. Houve algumas preocupações sobre HLS e MPEG-DASH e qual será o vencedor na arena dos navegadores da web. HLS não é implementado em todos os navegadores modernos (você provavelmente notou isso se clicou nos exemplos de url m3u8 anteriores). No Android, por exemplo, em versões inferiores a 4.0, não funcionará de todo. Do 4.1 ao 4.4 funciona apenas parcialmente (por exemplo, falta o áudio ou falta o vídeo, mas o áudio funciona).
Mas essa “batalha” ficou um pouco mais simples recentemente. maçã anunciado que o novo protocolo HLS permitirá arquivos MP4 fragmentados (fMP4
). Anteriormente, se você quisesse ter suporte a HLS e MPEG-DASH, você tinha que codificar seus vídeos duas vezes. Agora, você poderá reutilizar os mesmos arquivos de vídeo e recompactar apenas os arquivos de metadados (.m3u8
para HLS e .mpd
para MPEG-DASH).
Outro anúncio recente é o suporte para Codec de vídeo de alta eficiência (HEVC). Se usado, deve ser empacotado em arquivos MP4 fragmentados. E isso provavelmente significa que o futuro do HLS é fMP4
.
A situação atual no mundo dos navegadores é que apenas algumas implementações de navegador da tag irão reproduzir HLS fora da caixa. Mas existem soluções de código aberto e comerciais que oferecem compatibilidade com HLS. A maioria deles oferece HLS por ter um substituto do Flash, mas existem algumas implementações completamente escritas em JavaScript.
Este artigo enfoca especificamente o HTTP Live Streaming, mas conceitualmente também pode ser lido como uma explicação de como o Adaptive Bitrate Streaming (ABS) funciona. Concluindo, podemos dizer que HLS é uma tecnologia que resolve inúmeros problemas importantes no streaming de vídeo:
Independentemente de você acabar usando HLS ou MPEG-DASH, ambos os protocolos devem oferecer funcionalidades semelhantes e, com a introdução do mp4 fragmentado (fMP4) no HLS, você pode usar os mesmos arquivos de vídeo. Isso significa que, na maioria dos casos, você precisa entender os fundamentos de ambos os protocolos. Felizmente, eles parecem estar se movendo na mesma direção, o que deve torná-los mais fáceis de dominar.
O M3U (ou M3U8) é um formato de arquivo de texto simples originalmente criado para organizar coleções de arquivos MP3. O formato é estendido para HLS, onde é usado para definir fluxos de mídia.
HTTP Live Streaming (HLS) é um protocolo de transmissão de taxa de bits adaptável introduzido pela Apple em 2009. Ele usa arquivos m3u8 para descrever fluxos de mídia e HTTP para comunicação entre o servidor e o cliente. É o protocolo de streaming de mídia padrão para todos os dispositivos iOS.
MPEG-DASH é uma solução de streaming amplamente usada, construída em torno de HTTP, assim como o Apple HLS. DASH significa Dynamic Adaptive Streaming over HTTP.
Nos últimos anos, o suporte HLS foi adicionado à maioria dos navegadores. No entanto, as diferenças persistem. Por exemplo, Chrome e Firefox apresentam suporte apenas parcial em plataformas de desktop.