COMMENT ENREGISTRER, TÉLÉCHARGER ET TRANSCODER DES VIDÉOS AVEC WEBRTC

Photo de bc_campaign_editor_2
bc_campaign_editor_2
blog-placeholder image

La vidéo sur le web continue de se développer à pas de géant. L'une des façons dont elle se développe peut être démontrée par WebRTC et l'utilisation des API individuellement. Nous avons construit un exemple simple d'utilisation de getUserMedia pour demander la webcam d'un utilisateur et l'afficher dans un élément vidéo. Pour aller plus loin, prenons cet exemple et utilisons-le pour enregistrer, puis transcoder du contenu directement à partir du navigateur.

Création d'un exemple getUserMedia
Avant d'aller plus loin, jetons un coup d'œil à l'exemple initial, plus simple. Tout ce que nous ferons ici, c'est demander le flux vidéo d'un utilisateur et l'afficher dans un élément vidéo sur la page. Nous utiliserons jQuery pour l'exemple plus avancé, nous allons donc commencer à l'utiliser ici.

// Do the vendor prefix dance
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia || navigator.msGetUserMedia;

// Set up an error handler on the callback
var errCallback = function(e) {
console.log(‘Did you just reject me?!’, e);
};

// Request the user’s media
function requestMedia(e) {
e.preventDefault();

// Use the vendor prefixed getUserMedia we set up above and request just video
navigator.getUserMedia({video: true, audio: false}, showMedia, errCallback);
}

// Actually show the media
function showMedia(stream) {
var video = document.getElementById(‘user-media’);
video.src = window.URL.createObjectURL(stream);

video.onloadedmetadata = function(e) {
console.log(‘Locked and loaded.’);
};
}

// Set up a click handler to kick off the process
$(function() {
$(‘#get-user-media’).click(requestMedia);
});

Il ne nous reste plus qu'à ajouter le bouton "Get Media" et l'élément vidéo, et nous sommes prêts. Après avoir cliqué sur le bouton et permis au navigateur d'accéder à votre caméra, le résultat final devrait ressembler à ceci.

simple capture d'écran

Cette démo devrait fonctionner avec Firefox, Chrome ou Opera.

Vous avez maintenant accès à la webcam via le navigateur. Cet exemple est amusant mais plutôt inutile puisque tout ce que nous pouvons faire, c'est montrer à quelqu'un ce qu'il est.

Configuration du Media Recorder
Note : Depuis 2014, Firefox est le seul navigateur à avoir implémenté l'API MediaRecorder. Si vous souhaitez que cela fonctionne également dans Chrome, il existe des projets tels que RecordRTC et MediaStreamRecorder.

Nous avons besoin d'un simple composant côté serveur pour cet exemple, mais il ne doit faire que deux choses :

Renvoyer une politique AWS valide afin que nous puissions télécharger directement depuis leur navigateur
Soumettre une tâche d'encodage à Zencoder
Nous aimons utiliser le framework Express pour Node avec des exemples comme celui-ci, mais si vous êtes plus à l'aise avec quelque chose d'autre, comme Sinatra, n'hésitez pas à ignorer cet exemple et à utiliser ce que vous voulez. Puisque nous sommes plus concernés par le code côté client, nous n'allons pas nous attarder sur l'implémentation côté serveur.

var S3_BUCKET = 'YOUR-S3-BUCKET-NAME' ;

<p>var express = require(‘express’);
var path = require(‘path’);
var logger = require(‘morgan’);
var bodyParser = require(‘body-parser’);
var crypto = require(‘crypto’);
var moment = require(‘moment’);
var AWS = require(‘aws-sdk’);
var s3 = new AWS.S3({ params: { Bucket: S3_BUCKET }});
var zencoder = require(‘zencoder’)();

var app = express() ;

app.set('port', process.env.PORT || 3000) ;
app.use(logger('dev')) ;
app.use(bodyParser.json()) ;
app.use(bodyParser.urlencoded()) ;
app.use(express.static(path.join(__dirname, 'public'))) ;

app.post(‘/process’, function(req, res) {
// Build up the S3 URL based on the specified S3 Bucket and filename included
// in the POST request body.
var input = ‘https://’+S3_BUCKET+’.s3.amazonaws.com/’+req.body.filename;
createJob(input, req.body.email, function(err, data) {
if (err) { return res.send(500, err); }

res.send(200, data) ;

}) ;
}) ;

app.post(‘/upload’, function(req, res) {
var cors = createS3Policy();
res.send(201, { url: ‘https://’+S3_BUCKET+’.s3.amazonaws.com/’, cors: cors });
});

function createS3Policy() {
var policy = {
“expiration”: moment().utc().add(‘days’, 1).toISOString(),
“conditions”: [
{ “bucket”: S3_BUCKET },
{ “acl”:”private” },
[ “starts-with”, “$key”, “” ],
[ “starts-with”, “$Content-Type”, “” ],
[ “content-length-range”, 0, 5368709120 ]
]
};

var base64Policy = new Buffer(JSON.stringify(policy)).toString('base64') ;
var signature = crypto.createHmac('sha1', AWS.config.credentials.secretAccessKey).update(base64Policy).digest('base64') ;

return {
key: AWS.config.credentials.accessKeyId,
policy: base64Policy,
signature: signature
};
}

function createJob(input, email, cb) {
var watermark = {
url: ‘https://s3.amazonaws.com/zencoder-demo/blog-posts/videobooth.png’,
x: ‘-0’,
y: ‘-0’,
width: ‘30%’
};

zencoder.Job.create({
input: input,
notifications: [ email ],
outputs: [
{ format: ‘mp4’, watermarks: [watermark] },
{ format: ‘webm’, watermarks: [watermark] }
]
}, cb);
}

var server = app.listen(app.get(‘port’), function() {
console.log(‘Express server listening on port ‘ + server.address().port);
});

Cet exemple devrait fonctionner dans l'ensemble, mais vous devrez avoir des configurations AWS déjà mises en place, ainsi qu'une variable d'environnement ZENCODER_API_KEY\. Vous devrez également avoir configuré CORS sur le bucket que vous utilisez. Voici un exemple de configuration CORS qui fonctionnera :

<?xml version=”1.0″ encoding=”UTF-8″?> <CORSConfiguration xmlns=”http://s3.amazonaws.com/doc/2006-03-01/”> <CORSRule> <AllowedOrigin>\*</AllowedOrigin> <AllowedMethod>POST</AllowedMethod> <AllowedHeader>\*</AllowedHeader> </CORSRule> </CORSConfiguration>

Enregistrement des médias de l'utilisateur
Dans l'exemple simple ci-dessus, nous avons demandé les médias d'un utilisateur à l'aide de l'API getUserMedia. Heureusement, il existe une API appelée MediaRecorder. Firefox est le seul navigateur qui la supporte actuellement (à partir de la version 25), mais il existe des projets comme Whammy qui peuvent agir comme un pseudo-shim pour d'autres navigateurs.

L'API est simple. Il suffit de prendre le même flux que celui utilisé pour la lecture dans l'exemple précédent et de l'utiliser pour créer une nouvelle instance de MediaRecorder. Une fois que nous avons notre nouvel enregistreur, tout ce que nous avons à faire est d'appeler start() pour commencer l'enregistrement, et stop() pour l'arrêter.

var recorder = new MediaRecorder(this.stream) ;
recorder.start() ; // Vous enregistrez maintenant !
// ...Quelques secondes plus tard...
recorder.stop() ;

Obtenir le média enregistré
Ok, nous avons démarré et arrêté l'enregistrement d'une webcam. Maintenant, comment le voir ?

Vous pouvez écouter l'événement ondataavailable sur l'instance de MediaRecorder que nous avons créée pour enregistrer. Lorsque l'enregistrement sera terminé, il inclura un nouveau Blob que vous pourrez lire comme vous l'avez fait pour le média utilisateur d'origine.

// We’ll keep using the same recorder
recorder.ondataavailable = function(e) {
var videoBlob = new Blob([e.data], { type: e.data.type });
var player = document.getElementById(‘playback-video-el’);
var blobUrl = URL.createObjectURL(videoBlob);
player.src = blobUrl;
player.play();
}

Si vous avez suivi et construit ces exemples, vous êtes probablement en train d'essayer de rejouer la vidéo et de vous sentir frustré. Malheureusement, rien de ce que vous faites "correctement" ne fonctionnera ici. L'utilisation de la fonction autoplay sur l'élément vidéo, l'appel à play() ou le réglage de currentTime sur l'événement ended ne feront pas ce que vous voulez.

Il semble qu'il s'agisse simplement d'un problème lié à Firefox lors de la lecture de ces blobs. La solution fonctionnelle consiste à remplacer simplement la source sur l'événement terminé si vous souhaitez que la vidéo soit lue en boucle.

player.onended = function() {
video.pause();
video.src = blobUrl;
video.play();
}

Ce blob que vous avez est une vidéo WebM (en grande partie) fonctionnelle. Si vous créez une balise d'ancrage avec l'url de ce blob comme source, vous pouvez faire un clic droit et enregistrer le fichier localement. Cependant, même localement, ce fichier ne se comporte pas tout à fait correctement (OS X semble penser qu'il s'agit d'un fichier HTML).

C'est ici que Zencoder entre en jeu. Avant de pouvoir le traiter, nous devons mettre le fichier en ligne pour que Zencoder puisse y accéder. Nous utiliserons l'un des points de terminaison de l'API que nous avons créé plus tôt, /upload pour obtenir une politique signée, puis nous l'utiliserons pour POSTER le fichier directement sur S3 (j'utilise jQuery dans cet exemple).

function uploadVideo(video) {
$.post(‘/upload’, { key: “myawesomerecording.webm” }).done(function(data) {
// The API endpoint we created returns a URL, plus a cors object with a key, policy, and signature.
formUpload(data.url, data.cors.key, data.cors.policy, data.cors.signature, filename, recording);
});

function formUpload(url, accessKey, policy, signature, filename, video) {
var fd = new FormData();</p>

fd.append('key', filename) ;
fd.append('AWSAccessKeyId', accessKey) ;
fd.append('acl', 'private') ;
fd.append('policy', policy) ;
fd.append('signature', signature) ;
fd.append('Content-Type', "video/webm") ;
fd.append("file", video) ;

$.ajax({
type: ‘POST’,
url: url,
data: fd,
processData: false,
contentType: false
}).done(function(data) {
cb(null);
}).fail(function(jqxhr, status, err) {
cb(err);
});
}
}

uploadVideo(videoBlob) ;

Maintenant que vous avez une vidéo sur un bucket S3, tout ce qu'il nous reste à faire, c'est de la traiter. Si vous avez remarqué, nous avons ajouté un courriel au point de terminaison /process plus tôt afin que nous puissions recevoir la notification du travail (y compris les liens de téléchargement pour la vidéo) directement à nous quand il est terminé.

function process(email, filename) {
$.post(‘/process’, {
filename: filename,
email: email
}).done(function(data) {
console.log(‘All done! you should get an email soon.’);
}).fail(function(jqXHR, error, data) {
console.log(‘Awww…sad…something went wrong’);
});
};

process('[email protected]', "myawesomerecording.webm") ;

Quelques secondes plus tard, vous devriez recevoir un courriel vous félicitant pour vos toutes nouvelles vidéos enregistrées par le navigateur. Les liens inclus sont temporaires, assurez-vous donc de les télécharger dans les 24 heures ou de modifier le point de terminaison de l'API que nous avons créé pour télécharger les sorties dans un bac que vous possédez.

Nous avons créé une démo pour présenter cette fonctionnalité, y compris un peu de style et une interface pas si fantaisiste. Elle s'appelle VideoBooth, mais n'hésitez pas à cloner le projet et à l'utiliser. Vous pouvez également jouer avec la démo sur Heroku.

capture d'écran videobooth

Brightcove a aidé un fabricant d'équipements de diagnostic à réduire le temps et les dépenses consacrés à la salle de classe tout en améliorant la réussite ...
Brightcove a aidé la place de marché automobile la plus reconnue à gérer son énorme vidéothèque et à la rentabiliser...
Pour préserver l'intégrité de leur marque, les enseignes de distribution ont besoin de lecteurs vidéo personnalisables qui leur permettent d'ajuster les couleurs, la police...

PRÊT À COMMENCER ?

Contactez-nous pour savoir comment nous pouvons améliorer vos efforts de marketing vidéo et vous aider à générer les résultats et le retour sur investissement dont vous avez besoin.