No post anterior, mergulhamos na criação de um player inspirado na biblioteca hls.js. Exploramos os fundamentos da arquitetura orientada a eventos e demos os primeiros passos na implementação do código. Hoje, vamos dar um passo adiante! Você vai entender como o é feito o parser da playlist. Vamos lá?
Preparando o projeto
Para facilitar o acompanhamento, criei a branch part-01 no repositório. Nessa branch, você encontrará o código exatamente como o deixamos no último post.
No projeto, o arquivo principal é o main.js
. Ele é responsável por inicializar a classe Hls
e carregar a URL da playlist. Aqui está o código atual:
import Hls from './hls';
const videoSrc = '/video/index.m3u8';
const hls = new Hls();
hls.loadSource(videoSrc);
O que é uma playlist HLS?
A playlist, também conhecida como manifesto, é um arquivo de texto que contém as URLs dos segmentos de vídeo e informações essenciais para a reprodução.
Neste momento, nosso player simplesmente carrega esse arquivo e exibe seu conteúdo no console. Veja um exemplo de playlist:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXTINF:10.000000,
data00.ts
#EXTINF:10.000000,
data01.ts
#EXTINF:10.000000,
data02.ts
#EXT-X-ENDLIST
Cada linha que começa com # é uma tag especial. Vamos entender o significado de cada uma:
- EXTM3U: Indica o tipo do arquivo. Toda playlist HLS começa com essa tag.
- EXT-X-VERSION: Especifica a versão do protocolo HLS. No exemplo, estamos usando a versão 3.
- EXT-X-TARGETDURATION: Define a duração máxima de cada segmento de mídia, que neste caso é de 10 segundos.
- EXTINF: Identifica cada segmento de vídeo com sua duração. Exemplo:
data00.ts
,data01.ts
, etc. - EXT-X-ENDLIST: Indica o fim da playlist, ou seja, que não haverá mais segmentos.
Fazendo o parse da playlist
Atualmente, a playlist é apenas um texto. Para torná-la funcional, precisamos fazer o parse do arquivo. Aqui entra o arquivo m3u8-parser.js
. Adicione este código à pasta loader
:
const LEVEL_PLAYLIST_REGEX_FAST =
/(?:#EXT-X-(MEDIA-SEQUENCE):(\d+))|(?:#EXT-X-(TARGETDURATION):(\d+))|(?:#EXT(INF):([\d.]+)[^\r\n]*[\r\n]+([^\r\n]+)|(?:#EXT-X-(ENDLIST)))/g;
export function parsePlaylist(string, baseurl, id) {
const level = { fragments: [] };
let result = null;
let totalduration = 0;
let currentSN = 0;
while ((result = LEVEL_PLAYLIST_REGEX_FAST.exec(string)) !== null) {
result.shift();
result = result.filter((n) => n !== undefined);
switch (result[0]) {
case "MEDIA-SEQUENCE":
level.startSN = parseInt(result[1]);
break;
case "TARGETDURATION":
level.targetduration = parseFloat(result[1]);
break;
case "ENDLIST":
level.live = false;
break;
case "INF":
const duration = parseFloat(result[1]);
level.fragments.push({
url: `${baseurl}/${result[2].trim()}`,
baseurl,
duration,
start: totalduration,
sn: currentSN++,
level: id,
});
totalduration += duration;
break;
default:
break;
}
}
level.totalduration = totalduration;
level.endSN = currentSN - 1;
return level;
}
Agora vamos usar essa função no arquivo playlist-loader.js
. Adicione a importação e modifique o método onManifestLoading
:
import { parsePlaylist } from './m3u8-parser';
export default class PlaylistLoader {
// ...
onManifestLoading(event, data) {
const { url } = data;
fetch(url)
.then(response => response.text())
.then(text => console.log(parsePlaylist(text, '/video')));
}
}
A função parsePlaylist
transforma o texto da playlist em um objeto JavaScript utilizável no player. Passe o texto da playlist e uma baseUrl
para que os segmentos sejam corretamente localizados no projeto.
Conclusão
Agora, ao abrir o console do navegador, você verá um objeto JavaScript detalhado com os dados da playlist. Esse é o primeiro passo para criar um player HLS totalmente funcional.
No próximo post, vamos explorar como usar esses dados. Fique ligado e acompanhe os próximos capítulos dessa jornada!