Há alguns dias, ficou disponível um concerto raro de um artista que muito aprecio (Jan Blomqvist), num conhecido site televisivo internacional.
O concerto só ia estar disponível 7 dias e não existia um botão de download. Se quisesse ficar com ele no disco, tinha 2 soluções:
- gravar o ecrã e o áudio;
- encontrar uma forma de descarregar o ficheiro original do stream.
A primeira opção é válida, mas não só ficaria com o computador indisponível durante os 65 minutos do concerto, como não sabia a resolução nativa do vídeo para ficar com a gravação no formato ideal.
A segunda ideia era bastante mais geek e provavelmente mais morosa, mas produziria um ficheiro “perfeito”. O desafio era bem mais interessante, portanto foi este o caminho escolhido.
Ao todo foram 4 passos, que em princípio poderás replicar noutros sites quando quiseres descarregar um stream para o teu computador. Dependendo da forma como o site apresenta os streams, talvez também tenhas sorte!
Vou tentar ser o mais descritivo possível, mas convém estares minimamente confortável com o terminal e com o inspetor de um browser (como as DevTools do Google Chrome) para acompanhares este artigo.
Passo #1: Usar o painel Network das Chrome DevTools para encontrar os fragmentos do stream
Um stream raramente é um ficheiro único, com o vídeo completo; o conteúdo está habitualmente dividido num conjunto de fragmentos.
Isto é conveniente para quem está a assistir ao stream, porque não tem que esperar que o ficheiro completa seja descarregado se só quiser assistir a umas partes específicas do vídeo. Para quem aloja o vídeo, isto também significa que pode poupar um pouco na conta do hosting no final do mês.
As 2 partes ganham – mas no nosso caso, vamos precisar de encontrar todos esses fragmentos.
No Google Chrome, se abrires as Chrome Dev Tools (basta carregar no botão direito do rato e fazer “Inspect” algures na página que tem o vídeo que pretendes), terás uma tab de nome “Network”. Tudo o que naquela página está a ser descarregado pelo teu browser é apresentado ali.
Podes filtrar por tipos de ficheiro, como JS, CSS ou Imagens. Para streams, é boa ideia filtrar por “XHR”.

No caso deste concerto, podes ver que os ficheiros cumprem um padrão: segmentxx_1.av.ts
, onde xx
é o número do fragmento. Habitualmente, é assim que estão repartidos.
Avançando até ao final do vídeo no leitor, vejo que no caso do meu vídeo, o último segmento tem o número 392.
Temos então 392 fragmentos para descarregar. Para encontrares o URL, basta clicares num segmento com o botão direito do rato e escolher “Copy > Copy Link Address”.

Passo #2: Criar uma lista com todos os segmentos
O URL vai ser igual para os 392 fragmentos, mas o número do ficheiro vai mudar. Precisamos então de criar uma lista.
Há várias maneiras de chegar a este documento. No fundo, apenas precisamos de algo que repita o URL mas que acrescente +1 ao número do segmento.
Isto pode ser conseguido com Excel, com um editor de texto como o SublimeText com um plugin como o Text Pastry, ou por exemplo com JavaScript.
Para este caso, foi precisamente esta última opção que usei. Com um bom e velho loop, problema resolvido.
Assim sendo, nas DevTools podemos passar da aba “Network” para “Console” e colocar um código JS deste género:
// O número total de fragmentos fica nesta variável - no meu caso, 392
const length = 392;
// O URL que obtiveste com o "Copy Link Address" vai para esta variável, em forma de string - deves remover o nome do ficheiro, ou seja, o segmentxx_1.av.ts
const baseUrl = 'https://ositedoconcerto.com/pasta/outrapasta/'
// Criamos uma função com um loop para acrescentar o número ao segmento
function getURL() {
for (let index = 1; index < length; index++) {
const url = baseUrl +segment${index}_1_av.ts
console.log(url);
}
}
// Corremos a função, para que nos apresente a lista completa
getURL();
Passo #3: Descarregar todos os segmentos
Agora que temos a lista com o URL de todos os segmentos, podemos usar algum tipo de download manager para descarregar cada um, ou usar o terminal.
Sou grande fã do terminal para ações deste tipo e optei por recorrer ao wget para descarregar todos os ficheiros. Também poderás optar pelo curl (que podes utilizar em qualquer terminal), se preferires.
Para o caso do wget, basta editar a função que usámos no passo anterior, para o seguinte (a alteração é só dentro do console.log()
):
// Criamos uma função com um loop para acrescentar o número ao segmento
function getURL() {
for (let index = 1; index < length; index++) {
const url = baseUrl +segment${index}_1_av.ts
console.log("wget " + url);
}
}
Voltamos a correr o código completo nas DevTools e abrimos o terminal para colar a nova lista obtida de ficheiros a descarregar, já com o comando wget inserido por nós para as 392 ocasiões.
Passo #4: Juntar todos os segmentos
Agora que temos o nosso computador com todos os segmentos descarregados, está na altura de os juntar todos num só vídeo.
Para isso, vamos voltar a usar o terminal, e o poderoso FFmpeg. Esta é uma solução incrível para manipular vídeo e até áudio, e é claramente mais rápida que um programa como o Adobe Premiere ou o Final Cut.
Com o concat
do FFmpeg, é fácil juntar uma enorme quantidade de vídeos.
O comando mágico a utilizar é o seguinte: ffmpeg -f concat -i segmentlist.txt -c copy all.ts
Como podes ver, o concat
recebe uma lista de ficheiros, vinda de um TXT que dei o nome de segmentlist.txt
.
O ficheiro TXT terá que ter o seguinte aspecto:
file 'segment1_1_av.ts'
file 'segment2_1_av.ts'
file 'segment3_1_av.ts'
file 'segment4_1_av.ts'
file 'segment5_1_av.ts'
E assim sucessivamente. Novamente, podes utilizar várias soluções para gerar esta lista, da mesma forma que no passo #2.
Vamos voltar então a recorrer ao JavaScript e inserir o seguinte na consola:
const length = 392;
function getFileList() {
for (let index = 1; index < length; index++) {
const fileName = `segment${index}_1_av.ts`
console.log(`file '${fileName}'`)
}
}
getFileList();
Agora, copiamos o resultado para um ficheiro de nome segmentlist.txt
.
Corremos finalmente o comando do FFmpeg com o concat
e o nosso vídeo estará pronto com o nome all.ts
, visto que, neste caso, a extensão dos fragmentos era TS.