Créer des vidéos de formes d’onde audio avec FFmpeg & Node.js

Ce n’est un secret pour personne, chez Transloadit, nous aimons les projets open source. Nous avons publié plusieurs projets ambitieux, comme Uppy et tus, et nos fondateurs se sont même rencontrés en contribuant à un projet open source. Nous utilisons également de nombreux outils open source en coulisses, comme FFmpeg, qui est au cœur de notre encodage vidéo.
FFmpeg (Fast Forward MPEG) est un utilitaire en ligne de commande qui permet de transcoder des fichiers audio et vidéo. Il peut convertir des fichiers entre différents formats, modifier les fréquences d’échantillonnage et les résolutions, et bien plus encore. FFmpeg fait fonctionner nos services d’encodage vidéo et d’encodage audio, qui disposent chacun de plusieurs Robots.
Par défaut, Transloadit configure FFmpeg et adapte sa capacité en coulisses, en proposant une
abstraction puissante pour les cas d’usage courants. Mais vous pouvez aussi sortir des sentiers
battus. Les Robots de ces catégories exposent un paramètre
ffmpeg qui vous permet d’interagir directement avec FFmpeg et de créer des
fonctionnalités au-delà de celles que nous proposons par défaut.
L’objectif du jour
Dans cet article, nous souhaitons mettre en lumière les options de transcodage plus créatives proposées par Transloadit, à l’aide de notre paramètre FFmpeg et de notre SDK Node.js. Nous avons déjà des démonstrations qui montrent comment utiliser FFmpeg pour supprimer un flux vidéo (English), modifier une fréquence d’échantillonnage (English) et créer des préréglages d’encodage personnalisés (English). Aujourd’hui, nous allons vous montrer comment créer une Assembly pour générer des images de formes d’onde audio qui défilent horizontalement au rythme d’une piste audio fournie en entrée.
La configuration nécessaire sera rédigée dans un document JSON. Nous l’enregistrons sous forme de Template pour pouvoir la réutiliser plus tard.
Créons notre Template. Rendez-vous dans la section Template de votre compte Transloadit, puis cliquez sur « Nouveau Template » et enregistrez-y le JSON suivant.
Créez d’abord un ensemble d’informations d’identification de Template
pour Amazon S3, puis remplacez MY_S3_CREDENTIALS ci-dessous par son nom enregistré.
Le guide de configuration S3 (English) décrit les autorisations requises
pour le bucket. Utilisez un bucket privé avec S3 Block Public Access activé et ne fournissez aucun
en-tête ACL ou d’octroi d’autorisations. Le réglage bucket-default omet l’en-tête ACL
généré ; il ne rend pas un bucket privé et ne remplace ni sa politique ni les éventuels en-têtes
ACL ou d’octroi d’autorisations fournis.
{
"steps": {
":original": {
"robot": "/upload/handle"
},
"waveformed": {
"robot": "/audio/waveform",
"use": ":original",
"result": true,
"width": 8000,
"height": 600,
"background_color": "ffffffff",
"outer_color": "1974c7aa",
"center_color": "1974c7aa",
"format": "image"
},
"merged": {
"robot": "/video/merge",
"use": {
"steps": [
{
"name": "waveformed",
"as": "image"
},
{
"name": ":original",
"as": "audio"
}
]
},
"result": true,
"ffmpeg_stack": "v7",
"preset": "ipad-high",
"width": "${file.meta.width}",
"height": "${file.meta.height}"
},
"encode_effect": {
"robot": "/video/encode",
"use": "merged",
"ffmpeg_stack": "v7",
"preset": "empty",
"ffmpeg": {
"vf": "crop=w=800:h=${file.meta.height}:x='(${file.meta.width}-800)*t/${file.meta.duration}':y=0",
"t": "${file.meta.duration}"
}
},
"exported": {
"use": "encode_effect",
"robot": "/s3/store",
"credentials": "MY_S3_CREDENTIALS",
"acl": "bucket-default"
}
}
}
Voyons maintenant ce qui se passe. Notre premier Step,
nommé ":original" ci-dessus, sert à recevoir le fichier que nous transmettrons
avec le SDK Node.js dans cet exemple ; rien de surprenant jusque-là.
Notre deuxième Step, "waveformed",
génère l’image de notre forme d’onde. Nous pouvons définir des options comme
background_color et outer_color (la couleur extérieure de la forme
d’onde). Restons simples, avec un fond blanc et une forme d’onde bleue. Dans ce
Step, vous remarquerez peut-être que nous avons défini
le paramètre width de la forme d’onde générée à une valeur bien supérieure
à celle que vous attendriez habituellement. Nous expliquerons cela plus en détail ci-dessous.
Retenez surtout que plus la largeur augmente, plus l’effet de transition par défilement devient
fluide.
Passons à notre troisième Step,
"merged". Comme le nom de ce Step
l’indique, nous fusionnons les images de formes d’onde
qui viennent d’être générées avec notre fichier audio d’origine pour produire un nouveau fichier
vidéo mp4. Utilisez la convention de nommage "name",
"as" dans le paramètre use, et tout sera prêt.
Nous utilisons ensuite des Assembly Variables pour définir les
valeurs des paramètres width et height aux mêmes
dimensions que notre image d’entrée.
Passons maintenant à la partie amusante. C’est dans notre
Step "encode_effect" que les choses
deviennent un peu inhabituelles. Nous transmettons ici notre fichier vidéo de forme d’onde,
entièrement fusionné, au Robot
/video/encode. Le paramètre FFmpeg nous permet d’interagir
directement avec l’utilitaire en ligne de commande FFmpeg. Nous utiliserons l’option
"vf" pour générer notre effet vidéo. Regardons cela de plus près !
"crop=w=800:h=${file.meta.height}:x='(${file.meta.width}-800)*t/${file.meta.duration}':y=0"
Nous utilisons ici le filtre crop pour ajuster la taille du résultat final.
Dans notre Step waveformed, nous
avons défini la largeur totale à 8000. Nous avons donc choisi de n’afficher que 10 % de l’image
entière pendant le défilement, en saisissant 800 comme largeur cible.
Nous utilisons à nouveau une des Assembly Variables pour définir
la hauteur cible à celle du fichier d’entrée. Comme nous nous déplaçons uniquement de gauche à
droite, nous définissons y à 0.
Pour x, notre expression détermine la position horizontale de la fenêtre
de recadrage et fait commencer notre vidéo au bord gauche de l’image. À l’aide de
t, nous calculons le temps nécessaire pour que l’image recadrée atteigne
le bord opposé de notre image. Cette valeur sera différente pour chaque fichier audio fourni à
notre Assembly. C’est pourquoi nous utilisons à nouveau une
Assembly Variable pour obtenir systématiquement la bonne valeur
de temps à partir des métadonnées du fichier d’entrée.
Mais ce n’est pas la seule option que nous utilisons dans notre paramètre FFmpeg. Nous utilisons
également l’option t. Elle sert simplement à définir la durée du fichier
produit. Vous remarquerez que nous utilisons la même valeur pour cette option que pour l’option
vf ci-dessus.
Enfin, nous exportons notre résultat à l’aide du Robot /s3/store (English), et le tour est joué !
Premiers pas
Maintenant que nous avons notre Template, configurons l’intégration de notre SDK. Nous avons choisi Node.js pour cette démonstration, mais vous pourriez facilement adapter cet exemple à nos autres SDK disponibles. Avant de commencer, nous devons toutefois installer le SDK Node.js de Transloadit. Après avoir initialisé npm dans le dossier de votre projet, exécutez la commande suivante.
npm i transloadit@4 --save
Utilisez Node.js 20 ou une version plus récente et enregistrez le programme complet sous le nom
waveform-video.mjs pour que Node le charge comme un module ES. Exécutez-le avec
node waveform-video.mjs après avoir défini les informations d’identification ci-dessous.
Ci-dessous, nous avons divisé notre code en une série de fragments de code. Pour vous éviter de copier laborieusement chaque fragment, une version prête à copier-coller vous attend à la fin.
Nous importons d’abord la bibliothèque Transloadit.
import { Transloadit } from 'transloadit'
Nous configurons ensuite notre client Transloadit. Définissez TRANSLOADIT_AUTH_KEY et
TRANSLOADIT_SECRET_KEY dans votre environnement serveur à l’aide de l’Auth Key et de l’Auth
Secret de votre Workspace. Il ne s’agit pas d’ensembles d’informations d’identification de Template
destinés au stockage. Exécutez ce code sur votre propre ordinateur ou sur un serveur de confiance,
jamais dans un navigateur.
const transloadit = new Transloadit({
authKey: process.env.TRANSLOADIT_AUTH_KEY,
authSecret: process.env.TRANSLOADIT_SECRET_KEY,
})
Nous définissons maintenant le fichier audio que nous souhaitons utiliser dans notre
Assembly. Placez le fichier audio de votre choix dans le
répertoire de travail et déclarez les deux variables filePath et
fieldName. Nous les transmettrons à createAssembly dans son option
files.
const filePath = './joakim_karud-rock_angel.mp3'
const fieldName = 'my_file'
Nous créons ensuite notre Assembly avec l’identifiant du
Template enregistré. Le SDK renvoie une Promise ; waitForCompletion attend la fin du
traitement, et pas seulement celle du téléversement. Le fragment suivant doit se trouver dans une
fonction asynchrone, comme dans le programme complet ci-dessous.
const opts = {
files: { [fieldName]: filePath },
waitForCompletion: true,
params: {
template_id: 'YOUR_TEMPLATE_ID',
},
}
const result = await transloadit.createAssembly(opts)
console.log(result)
Une fois tout notre code rassemblé, nous pouvons exécuter notre programme. Voici à nouveau le programme complet :
import { Transloadit } from 'transloadit'
async function main() {
const transloadit = new Transloadit({
authKey: process.env.TRANSLOADIT_AUTH_KEY,
authSecret: process.env.TRANSLOADIT_SECRET_KEY,
})
const filePath = './joakim_karud-rock_angel.mp3'
const fieldName = 'my_file'
const result = await transloadit.createAssembly({
files: { [fieldName]: filePath },
waitForCompletion: true,
params: { template_id: 'YOUR_TEMPLATE_ID' },
})
console.log(result)
}
main().catch(() => {
console.error('Waveform video generation failed.')
process.exitCode = 1
})
Pour le fichier audio, nous avons choisi la piste « Joakim karud-rock angel », que nous avons souvent utilisée dans bon nombre de nos démonstrations (English). Si vous souhaitez utiliser le même fichier, vous le trouverez dans le dépôt GitHub ci-dessous.
Une fois l’exécution de notre programme terminée, nous pouvons nous connecter à S3 et consulter le résultat final.
Comme vous pouvez le constater, tout s’est déroulé comme prévu. Mais les choses peuvent devenir encore plus intéressantes. Avec FFmpeg, les possibilités offertes à vos Assemblies sont pratiquement infinies. Pourquoi ne pas essayer de faire défiler la forme d’onde verticalement ou de transcoder la vidéo pour la lire à l’envers ?
Vous pouvez aussi utiliser le paramètre ffmpeg pour appliquer une gamme
extrêmement variée de filtres.
Nous espérons que cet article vous a montré toute la polyvalence de l’API Transloadit et l’utilité
du paramètre ffmpeg pour créer toutes sortes de projets créatifs et amusants.
Si vous souhaitez télécharger les ressources utilisées dans ce projet, rendez-vous dans le dépôt GitHub suivant !