Felipe Weckx

Streaming de videos com PHP

Vídeo para Web

Com o amplo suporte ao HTML5 nos navegadores mais modernos todos tem a capacidade de entender a tag <video>  que permite colocar o elemento na página, porém não é qualquer formato de vídeo que pode ser distribuído, já limitações de acordo com o navegador e sua versão. Então antes de colocar o vídeo na web precisamos convertê-lo para um formato suportado.

Formatos Suportados

O formato MP4 é o que hoje possui o suporte mais abrangente, mas uma das vantagens da tag <video> do HTML5 é permitir especificar diversos arquivos de vídeo, assim o navegador irá escolher automaticamente o arquivo com o formato suportado. De acordo com o site da W3Schools os formatos suportados para cada navegador são:

Navegador MP4 WebM Ogg
Internet Explorer SIM NÃO NÃO
Chrome SIM SIM SIM
Firefox NÃO SIM SIM
Safari SIM NÃO NÃO
Opera NÃO SIM SIM

Utilizaremos como exemplo este vídeo que está no formato Quicktime (.mov).  Para converter pode-se utilizar a ferramenta FFmpeg, disponível para Linux, Windows e MAC.

Convertendo para MP4

Para converter o vídeo para o formato MP4 podemos utilizar a linha de comando abaixo:

ffmpeg -i Rain_Fire.mov -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset slower -crf 23 -vf "scale=trunc(in_w/2)*2:trunc(in_h/2)*2" -movflags +faststart rain.mp4

Alguns parâmetros importantes do comando acima:

  • -c:v libx264 – Importante pois o codec x264 é o mais suportado
  • -pix_fmt yuv420p – Pixel format a utilizar
  • -profile:v baseline – Profile de vídeo. O baseline é para que o vídeo seja facilmente entendido em dispositivos Android
  • – preset slower – Determina a relação qualidade de vídeo/tempo de codificação. Pode ser diversos valores (faster, fast, medium, slow)
  • -crf 23 – Nível de qualidade do encoding 0 é sem perdas e 51 a pior qualidade possível. O valor de 23 é o padrão e pode ser omitido.
  • -vf “scale=trunc(in_w/2)*2:trunc(in_h/2)*2” – Por alguns motivos os vídeos MP4 encodados nesta forma devem ter os valores de largura e altura com números pares. Este parâmetro ajusta o tamanho do vídeo
  • -movflags +faststart – Faz com que os cabeçalhos de informação do vídeo sejam colocados no começo do arquivo, desta forma o navegador não precisa baixar o vídeo todo para saber qual o seu tamanho e formato. Este parâmetro é essencial para que possa ser feito o streaming do vídeo.

Para mais informações ver a documentação do FFmpeg sobre codificação de vídeos com H.264.

Convertendo para WebM

Outra possibilidade de formato de vídeo é o WebM, um formato recentemente adquirido pelo Google que o tornou de uso público. Para converter o vídeo para este formato podemos utilizar o comando abaixo:

ffmpeg -i Rain_Fire.mov -c:v libvpx -c:a libvorbis -pix_fmt yuv420p -b:v 2M -crf 5 rain.webm

De forma semelhante os parâmetros da conversão:

  • -c:v libvpx – o codec a utilizar para o video
  • -c:a libvorbis – o codec a utilizar para o áudio
  • -pix_fmt – formato de pixel
  • -b:v 2M – bitrate desejado. É importante definir este parâmetro pois o padrão não gera videos de boa qualidade
  • -crf 5 – Nível de qualidade do vídeo. Pode ser de 4 – 63. Quanto menor mais qualidade

Mais informações na documentação do FFmpeg.

Servindo o arquivo

Com os arquivos no formato correto podemos então criar nossa página para exibi-lo ao usuário. Vamos montar uma estrutura de diretórios da seguinte forma:

Estrutura de diretórios

Estrutura de diretórios

No diretório public ficarão os arquivos visíveis pelo servidor web e no diretório resource os arquivos de vídeo que iremos servir. No arquivo index.php está o HTML para a página e o arquivo stream.php será o responsável por ler os arquivos de vídeo e enviá-los ao navegador do usuário.

Streaming

O streaming é uma forma de distribuição de dados aonde o conteúdo é fornecido ao usuário conforme necessário, sem a necessidade de que ele receba todo o conteúdo para visualiza-lo. Esta é a melhor forma de servir vídeos pois permite a rápida visualização pelo usuário (ele não tem de esperar o download do vídeo todo) e também diminui a banda de rede utilizada pelo servidor. Os navegadores utilizam o cabeçalho HTTP Range para indicar qual parte do vídeo eles desejam que seja enviada. Assim se o usuário clicar na barra de navegação do vídeo o navegador envia uma nova requisição para o período respectivo.

Tratando o cabeçalho Range

Com o arquivo no formato correto podemos criar um script PHP para fazer a leitura do arquivo e envia-lo para o usuário. Porém precisamos considerar o cabeçalho Range para que sejam enviados somente os bytes que o navegador solicitou. De acordo com a RFC2616 que especifica o protocolo HTTP versão 1.1 o conteúdo do campo tem um dos seguintes formatos:

  • Os primeiros 500 bytes: bytes=0-499
  • O segundo lote de 500 bytes: bytes=500-999
  • Os últimos 500 bytes: bytes=-500
  • Todos os bytes à partir do byte 9500: bytes=9500-

O valor do campo vem na variável $_SERVER[‘HTTP_RANGE’] então podemos criar o código que irá ler o arquivo utilizando as funções de sistema de arquivos do PHP e colocar no arquivo stream.php:

É essencial tratar o cabeçalho Range quando estamos servindo arquivos que serão consumidos via streaming pois se não o usuário não conseguirá avançar/retroceder no vídeo  e terá de esperar o download completo do vídeo antes de começar a assisti-lo, o que é muito pouco prático para vídeos grandes.

A página web

Vamos agora criar o arquivo index.php que será acessado pelo usuário. Ele terá apenas o HTML necessário para a tag <video>:

Com o arquivo index.php criado podemos agora acessá-lo e ver o vídeo. Caso não queira utilizar um servidor web para testar pode-se utilizar o servidor web embutido do PHP executando:

php -S localhost:8000 index.php

E então acessar no navegador o endereço http://localhost:8000

 A tag <video>

A tag <video> é utilizada para inserir o vídeo na página. Dentro dela pode haver qualquer número de elementos <source> cada um deles indicando um formato de vídeo diferente ou até mesmo um arquivo de áudio. Então pode-se, por exemplo, colocar um arquivo de vídeo e um de áudio e o navegador vai “juntar” os dois na reprodução. No nosso caso especificamos dois elementos source, um com o vídeo no formato MP4 e outro com o vídeo no formato WebM. Desta forma o navegador vai escolher o que for suportado. Os atributos da tag são:

  • controls – Se devem ser exibidos os controles (avanço, retrocesso, volume, etc)
  • preload – Se o vídeo deve ser carregado juntamente com a página. Pode ser auto para carregar junto com página, metadata para o navegador carregar apenas os dados básico ou none para não carregar junto com página. O Internet Explorer não respeita este parâmetro.
  • width height – Largura e altura, respectivamente
  • poster – URL para uma imagem que será exibida no lugar do vídeo enquanto o mesmo não é carregado. Veja abaixo como gerar uma utilizando o FFmpeg.
  • autoplay – se especificado este parâmetro o vídeo irá começar a tocar assim que possível

Além destes diversos outros parâmetros estão disponíveis que permitem controlar o comportamento do vídeo.

Criando o poster

Como mostrado acima é possível especificar uma imagem que irá aparecer no lugar do vídeo enquanto este não for carregado. Podemos gerar esta imagem com o FFmpeg utilizando o comando abaixo:

ffmpeg -i Rain_Fire.mov -r 1 -vframes 1 -ss 0:05 poster.png

O parâmetro mais importante acima é o -ss 0:05 que especifica de qual momento será criada a imagem

Utilizando o video.js

A página acima funciona em qualquer navegador moderno que suporte HTML5. Mas e os navegadores mais antigos como Internet Explorer 7  e 8 que ainda são bastante utilizados? Para estes casos podemos utilizar a biblioteca video.js que faz automaticamente o fallback para um player em Flash caso o navegador não tenha suporte a HTML5. A utilização é bastante simples e há diversos exemplos no site. Segue a versão do nosso index.php utilizando a biblioteca:

 Conclusão

A tag <video> do HTML5 permite adicionar facilmente vídeos à paginas web, porém é necessário tomar cuidado com os formatos de vídeos suportados e fazer as conversões necessárias. É essencial que os arquivos sejam servidos via streaming para diminuir o tráfego de rede e melhorar a experiência do usuário e para tanto é essencial que o cabeçalho Range seja tratado de forma adequada, algo que pode ser feito facilmente pelo PHP. O código aqui mostrado tem apenas as funções básicas e pode com certeza ser muito melhorado.

O código de exemplo está disponível no Github: https://github.com/weckx/wcx-video-stream

Criando Túneis SSH

O SSH é um protocolo de comunicação segura muito utilizado para acesso remoto via terminal, ou seja para executar comandos. Mas ele possui muitas outras funcionalidades, uma delas é a de tunelamento. Tunelamento é a capacidade de um protocolo de rede encapsular um outro protocolo dentro dele, tornando-se efetivamente o meio de transporte deste protocolo. Isto abre uma série de possibilidades, basicamente permitindo que você possa ter acesso a qualquer recurso de rede que o host aonde você consegue se conectar por SSH  tem. Por exemplo, você está em um lugar aonde o acesso a determinados sites é bloqueado mas você tem acesso via SSH a um servidor que esta fora desta rede. Neste caso você pode criar um túnel dinâmico da seguinte forma:

ssh -N -D2342 usuario@servidor.com

Depois de conectar ao servidor configure o seu navegador para utilizar um proxy SOCKS no localhost, porta 2342. No caso do Firefox está configuração está disponível no menu Edit -> Preferences -> Network -> Settings :

Configuração de tunelamento FireFox

Com esta configuração o Firefox não vai mais se conectar diretamente aos sites que você tentar acessar. Ao invés disso ele irá conectar no proxy SOCKS que configuramos ao iniciar o SSH e irá conectar através dele. Então o acesso está sendo feito através do servidor.com ao qual nos conectamos.

 

Enviando mensagens via syslog com PHP

O Syslog é um padrão de mensagens de log de aplicações utilizado por diversos tipos de equipamentos de computação como: servidores, impressoras, roteadores, firewalls, etc. A ideia principal é permitir que todos os logs gerados por uma ou mais aplicações possam ser enviados para um mesmo local, que pode ser no próprio equipamento ou em um servidor remoto.

Neste post vamos entender como funciona a mensagem Syslog e como criar uma classe simples de envio com o PHP.

Continuar lendo