Docker-VideoEncoding

Stars
3

Docker-VideoEncoding

Description du projet

Ce projet, ralis lors du module proejt d'ESIR 2 a pour but de raliser un scheduling temporel de containers docker fonctionnant sur un cluster de RaspberryPi dans le but de raliser l'encodage de vidos.

Architecture du projet

Ce rpertoire contient :

  • Docker_Files : Les diffrents docker utilis pour faire tourner le projet. C'est--dire les docker pour glusterfs (utilis pour avoir un espace commun), swarm (utilis pour le scheduling temporel des containers), FileUploader qui est l'interface utilisateur, split/encode/merge (utiliss pour encoder une vido).
  • FileUploader : Le code source destin au fonctionnement de l'interface (o on upload et lance l'encodage d'une vido)
  • Script : Les scripts pour encoder une vido.
  • swarm : Notre version de DockerSwarm pour grer le scheduling temporel.
  • the-graph : L'interface utilis pour voir l'tat des dockers.

Pour rsumer, ce projet est compos d'un cluster de raspberry pi qui font tourner une instance de glusterfs afin d'avoir un espace de fichier partag. Un des raspberrys (node1) fait tourner une interface web dans lequel l'utilisateur peut envoyer un fichier a encoder. Ce docker lance un processus (split/encode/merge) o les containers sont grs par DockerSwarm. Enfin, the-graph sert la visualisation des tats des containers.

Monter sa propre instance

Prparation d'un RaspberryPi

Il suffit de flasher une image raspbian puis d'xcuter le script prepareRpi.sh qui mettera en place le hostname et dmarrera les containers ncessaires (glusterfs, dockerswarm, etc).

FileUploader

Utilisation

Sur le node 1, il suffit de faire tourner le docker fileuploader avec la commande suivante : docker run -it -p 3000:3000 --volume-driver=glusterfs --volume uploads:/uploads --name fileuploader fileuploader

Ce qui donnera pour interface : fileuploader

Les fichers seront uploads dans le dossier uploads du glusterfs.

Fonctionnement interne

Le serveur est dvelopp avec nodejs (le code source se trouve dans /FileUploader). Lors de l'envoie d'un fichier, 2 fichiers sont ajouts sur le serveur. Un fichier de la forme toEncode_$DATE$ qui est le fichier upload et un .json contenant :

{
  "toEncode":"toEncode_1464009095314",
  "original_name":"$ORIGINALNAME$",
  "wanted_name":"$WANTEDNAME$",
  "bitrate":"$BITRATE$"
}

Encodage d'une vido

Pour comprendre comment ont t install l'ensemble des packages ncessaires pour cette partie, veuillez vous rfrer au Dockerfile correspondant chaque partie (Split, Encode, Merge).

Split

Ce script permet de couper notre vido d'origine en un nombre de parties donn en paramtre de notre script.

Les deux paramtres de ce script sont :

  • Le nom du json correspondant notre vido (sans l'extension .json)
  • Le nombre de split que l'on souhaite obtenir

Fonctionnement :

Dans un premier temps on rcupre les informations qui nous intresse dans le .json de notre vido (la valeur de toEndode pour obtenir le nom du fichier d'origine split qui sera donc rentr en paramtre de notre script et la valeur de wanted_name pour connatre le nom qu'aura chacun de nos splits, si cette valeur est absente on prend alors l'original_name par dfaut).

inputFile="$directory"$(grep -Po '(?<="toEncode":")[^"]*' "$directory""$1.json")
outputFile="$directory"$(grep -Po '(?<="wanted_name":")[^"]*' "$directory""$1.json")
outputFileName=$(echo $outputFile | cut -f1 -d '.')

Ensuite, on rcupre des informations sur la vido tel que sa dure mais galement toutes ses key_frames que l'on stocke dans un fichier texte ("$inputFile"_key_frame.txt). Pour effectuer cela, on a utilis la commande avprobe (installe sur les raspberry et provenant du package libav-tools).

avprobe -show_format_entry duration -v quiet "$inputFile"

avprobe  -v quiet -show_packets -of json "$inputFile" | awk '$0 ~ /"pts_time" : "([0-9]|\.)*"/ {toPrint=$3} $0 ~ /"flags" : "K"/ {print toPrint} '
| grep -oE \([0-9]\|\\\.\)*  > "$inputFile"_key_frame.txt

Une fois toutes ces informations obtenues, on peut alors procder au dcoupage de notre vido. Pour cela cette fois, nous avons utilis la commande avconv. Enfin si l'utilisateur entre en second paramtre un nombre souhait de split suprieur au nombre total de key_frames de notre vido, alors cette dernire sera dcoup en cette deuxime valeur (#key_frames).

avconv -y -i "$inputFile" -ss $startTime -t "$splitTime" -codec copy "$outputFileName"_part_"$fileCurrentNumber".mp4

Retour :

  • Un fichier .part qui rpertorie tous les noms des diffrents splits de la vido (qui sera utilis ensuite dans le script de merge)
  • Notre vido dcoup en n parties voulues ou au maximum de parties possibles (#key_frames)

Encode

Ce script permet d'encoder nos splits de vido obtenus grce au script prcdent (scriptSplit).

Les deux paramtres de ce script sont :

  • Le nom du json correspondant notre vido (sans l'extension .json)
  • Le numro du split que l'on souhaite encoder

Fonctionnement :

Nous rcuprons la valeur du bitrate sur le fichier json pass en paramtre. Si cette information n'est pas disponible, on donne comme valeur de bitrate celle de la vido d'origine obtenue via la commande avprobe. Avec cette valeur nous pouvons ensuite lanc notre commande d'encodage via cette fois la commande gst-launch-1.0 (package gstreamer1.0) o le bitrate est justement plac en otion de cette commande. Pour l'encodage, on se sert de omxh264enc qui est l'encodeur hardware prsent dans nos raspberrys.

gst-launch-1.0 -v filesrc location="$outputFileName"_part_"$2" ! decodebin ! videoconvert ! \
    videoscale ! omxh264enc control-rate=1 \
    target-bitrate="$bitRate" ! h264parse ! mp4mux ! \
    filesink location="$outputFileName"_part_"$2"_encoded.mp4

Retour :

  • Notre split de vido choisi encod

Merge

Ce script permet de faire fusionner nos splits de vido obtenus grce au script scriptSplit et aprs l'encodage de ces derniers (scriptEncode).

L'unique paramtre de ce script est :

  • Le nom du json correspondant notre vido (sans l'extension .json)

Fonctionnement :

On rcupre premirement dans ce fichier JSON le nom qu'aura notre vido finale (wanted_name ou si absent original_name).

outputFile=$(grep -Po '(?<="wanted_name":")[^"]*' "$1.json")

Ensuite, nous procdons au merge via la commande ffmpeg (ici nous n'avons pas russi rutiliser avconv pour le merge, cela ne fonctionnait pas...). On met en paramtre de cette commande le fichier .part obtenu aprs le split de notre vido.

ffmpeg -y -f concat -i $1.part -c copy "$outputFile"

Retour :

  • La vido complte et encode

DockerSwarm

Cette partie du projet sert raliser le scheduling temporel des containers.

Utilisation

Pour lancer un container sur le swarm : docker -H tcp://$IPADD:2375 run -d -P --name NAME IMAGE

Il est possible de faire en sorte qu'un container attende qu'un autre soit finit avec -e waitfor:container==NAME. Ainsi par exemple docker -H tcp://$IPADD:2375 run -d -P -e waitfor:container==h1 --name h2 armhf/hello-world va crer un container h2 qui attendra que le container h1 soit arrt.

Fonctionnement interne

Le code source est disponible dans le module du dossier /swarm, principalement dans le dossier swarm/cluster/state/. Lors de l'appel la mthode run, swarm vrifie si toutes les dpendances sont termines, sinon le container est rajout une liste de containers bloqus. chaque fois qu'un container termine, les dpendances sont vrifies. Si on peut lancer un container bloqu car toutes les dpendances sont rsolues, on le fait.

The-Graph

Installation of the graph

Get dependencies using Bower and Browserify (via npm and grunt):

bower install
npm install
grunt build

But du graph

La librairie open-source the-graph est bas sur noflograph. Dans notre projet cette librairie nous permet d'afficher les images docker qui sont installs sur les diffrents Raspberry Pi. Il y a 3 types d'images affichs : 1 image split -> Cette image reli sur ses sorties aux diffrentes images encode. n images encode -> Ces images sont relis l'image split sur leur entre et l'image merge sur leur sorties. 1 image merge -> Cette image est reli sur son entre aux diffrentes images encode.

Fonctionnement interne

The-graph fonctionne grce des objets JSON. En effet il faut produire les fichiers JSON qui permettent de dcrire tous les noeuds et toutes les connections entre les diffrents noeuds. Il faut au pralable avoir dfini ces noeuds en tant que "components" pour que cela fonctionne.

Pour ce faire, 2 fichiers ont t modifis pour correspondre notre projet :

read-status.js -> Les fonctions ncessaires au bon fonctionnement de notre graph sont dfinis ici. Une fonction permet de rcuprer le json envoy par la requte GET au swarm. Une fonction permettant de gnrer la librairie de components et une fonction permettant d'afficher les nodes ainsi que les connections entre les nodes.

index.html -> Permet d'appeler les fonctions dfinis dans read-status afin de charger le graphe.

Fonctionnalits

Fonctionnalits existantes

  • Upload de fichiers sur le glusterfs
  • Choix du bitrate depuis l'interface web
  • Split/Merge d'une vido
  • waitfor pour le swarm

TODOList

  • Relier au swarm custom du projet.
  • Encoder une vido
  • Relier a the-graph

Licence

DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
            Version 2, December 2004

Copyright (C) 2004 Sam Hocevar <[email protected]>

Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.

    DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0\. You just DO WHAT THE FUCK YOU WANT TO.