Empreendendo sem dinheiro
Criei uma espécie de desafio mental, esse desafio consiste em resolver problemas já enfrentados ou de outras origens de forma criativa, em pouco tempo e se possível evolvendo pouco ou nenhum custo!
E o desafio da semana foi criar um daqueles projetos de “media indoor”.
Então pensei: “já sei vou usar grpc, s3 rsync, elastic transcoder, fastly, frontend do admin em react e é claro kubernetes!”
Já no cliente, que é responsável por tocar os vídeos…: “vou escrever em Qt, criar a interface em QML, usar boost.asio para o meu downloader e criar uma distribuição de Linux embarcado usando o yocto !“.
“The best code is no code at all.”
Painel administrativo
As pessoas, e desse ramo principalmente, estão acostumadas a usar planilhas para as mais variadas tarefas, então por que não usar uma planilha como “admin”?
Envio, armazenamento, transcodificação e distribuição de vídeos
Ao invés de desenvolver um complexo sistema de gerenciamento de arquivos de vídeo, com transcodificação usando as ferramentas que citei acima, usando lambda e outras coisas, vamos usar o YouTube.
Quê?
É isso mesmo, no nosso protótipo vamos usar o YouTube, pois não tem nenhum custo e já faz a conversão e distribuição do vídeo nos mais variados formatos e tamanhos.
Atenção: De acordo com os termos de uso do YouTube não é permitido reproduzir o conteúdo da plataforma fora do player do youtube, o que estou demonstrando é apenas para fins educacionais.
O nosso work é playá
Nada mais do que um pequeno script em bash será necessário para executar as tarefas de baixar a playlist, os vídeos, a remoção de vídeos não mais usados entre outras coisas.
Já o player propriamente dito é o omxplayer, que é capaz de decodificar vídeos usando aceleração por hardware; omxplayer
foi escrito especialmente para a GPU do Raspberry Pi e faz uso da API OpenMAX, é extremamente eficiente.
O trecho abaixo é de um apps script que transforma a primeira coluna da planilha num array de objetos e serializa a reposta num JSON.
function doGet(request) {
var app = SpreadsheetApp;
var worksheet = app.getActiveSpreadsheet();
var sheet = worksheet.getSheetByName(request.parameters.sheet);
if (sheet) {
var range = sheet.getDataRange();
var values = range.getValues();
var headers = values.shift();
var playlist = values.map(function (el) {
return { url: el[0] };
});
return ContentService.createTextOutput(JSON.stringify({ playlist: playlist })).setMimeType(
ContentService.MimeType.JSON,
);
}
}
É possível publicar o script acima num endereço público e de acesso anônimo, de modo que seja possível baixar o JSON até mesmo pelo cURL, e é com essa reposta que iremos usar para saber quais arquivos baixar e gerar a playlist:
$ curl -sL "https://script.google.com/macros/s/${...}/exec?sheet=Sheet1" | jq
{
"result": [
{
"url": "https://www.youtube.com/watch?v=..."
},
...
]
}
Com uma simples entrada no cron
é possível criar um agendamento para baixar a playlist de tempos em tempos:
*/30 * * * * user curl -sL "https://script.google.com/macros/s/${...}/exec?sheet=Sheet1" > playlists/1.json
A função download
usa a ferramenta jq para gerar uma lista de urls a serem baixadas pelo youtube-dl que por sua vez executa um pequeno script (--exec
) para adicionar o arquivo recém baixado para a playlist, tomando cuidado para não duplicar:
download() {
cat playlists/*.json | jq '.[].url' \
| xargs youtube-dl --exec "grep -sqxF '{}' $playlist || echo '{}' >> $playlist"
}
Alguns parâmetros do
youtube-dl
foram omitidos pois foram movidos para o arquivo de configuração global.
Com o entr é possível monitorar se algum arquivo foi modificado ou mesmo adicionado novos arquivos no diretório; se isso acontecer, a função download
será chamada:
watch() {
while :; do
ls -d playlists/*.json | entr -d "$0" download
done
}
De tempos em tempos é necessário remover os arquivos antigos e downloads incompletos; a função recycle
remove todos os arquivos do tipo vídeo modificados pela última vez há mais de 7 dias e que não estão sendo usados:
A razão de ser alguns dias depois e não imediatamente é de ser maleável caso tenha sido algum equívoco.
recycle() {
declare -a args=(
-mtime +7
-type f
)
while read -r uri; do
args+=(-not -name "$uri")
done <<< "$(cat $playlist)"
find "$PWD" "${args[@]}" -exec bash -c "file -b --mime-type {} | grep -q ^video/" \; -delete
}
Todas essas funções podem ser chamadas inúmeras vezes sem efeitos indesejados.
Tocar a playlist é a parte mais fácil:
play() {
setterm -cursor off
export DISPLAY=":0.0"
while :; do
while read -r uri; do
omxplayer --refresh --no-osd --no-keys "$uri"
xrefresh -display :0
done <<< "$(cat $playlist)"
done
}
Graças ao
omxplayer
o consumo de CPU fica bem baixo, mesmo em 1080@60fps, algo em torno de ~0.5% num Raspberry 3.
O próximo passo é contabilizar algumas estatísticas, como o número de vezes que um vídeo foi tocado, se teve alguma interrupção por falta de energia ou por problemas técnicos, etc.
Para isso uma boa pedida é o papertrail, com essa ferramenta é possível centralizar todos os logs da máquina, exportar para o BigQuery e executar as consultas na mesma planilha que ficam os vídeos.
Ops… Acho que minha febre por cloud computing voltou :-)