2017-09-06 3 views
2

J'ai utilisé Node.js et Ffmpeg pour créer des animations. Parce que j'essayais d'éviter les parseurs avi/mp4 tiers, j'ai décidé de sortir l'animation en tant que fichier de données rgb24 brut et ensuite utiliser un programme pour le convertir en fichier mp4.Node.js - Buffer Data to Ffmpeg

J'ai trouvé que Ffmpeg est libre et open source qui peut faire exactement cela. Donc, j'ai fait une application Node.js qui alloue un Buffer de taille 1920 x 1080 x 3 (largeur fois hauteur fois nombre d'octets par pixel), puis j'ai créé une bibliothèque de contexte de rendu, et enfin j'ai animé image par image et sauvé chaque image consécutivement dans un fichier binaire (en utilisant le module fs).

Puis j'ai invoqué Ffmpeg pour le convertir en fichier mp4 et ça marche très bien. Les animations sont assez faciles à réaliser et Ffmpeg fait son travail correctement.

Cependant, le seul problème est parce qu'il est très lent et mange de l'espace sur le disque dur. Je veux créer des animations très longues (plus d'une heure). Le fichier mp4 final est relativement petit, mais le fichier vidéo brut est extrêmement gros. Environ quatre-vingt-dix pour cent de chaque image sont des pixels noirs, donc Ffmpeg est très bon, mais le fichier brut ne peut pas être compressé et il faut parfois plus de 100 gigaoctets. En outre, il y a un double traitement très inutile des mêmes données. Premièrement, je le traite dans Node.js pour enregistrer les données dans un fichier, puis Ffmpeg le lit pour le convertir en mp4. Il y a beaucoup de travail inutile. Donc, je cherche un moyen (et je suis sûr que c'est possible, mais je n'ai pas encore trouvé le moyen de le faire) de sortir des données vidéo brutes (une image à la fois) pour Processus Ffmpeg (sans rien sauvegarder sur le disque dur).

Mon but est de faire ce qui suit:

  1. Ouvrir processus Ffmpeg
  2. rendu un cadre dans Node.js
  3. sortie flux d'octets brut à FFmpeg
  4. Attendez ffmpeg pour encoder et ajouter au fichier mp4
  5. Laissez Ffmpeg attendre que mon processus Node.js restitue la trame suivante

Existe-t-il un moyen de l'atteindre? Je ne vois vraiment pas une raison de poster du code, parce que mon code actuel n'a rien à voir avec la question que je pose ici. Je ne me bats pas avec les erreurs de syntaxe ou les problèmes de mise en œuvre. Non, à la place je ne sais pas quels paramètres passer au processus Ffmpeg afin de réaliser ce que j'ai déjà expliqué.

J'ai cherché dans la documentation pour savoir quels paramètres j'avais besoin de passer au processus Ffmpeg pour pouvoir lire les données brutes de stdin à la place du fichier, et aussi attendre que mon processus Node.js restitue la trame suivante (donc pour désactiver la limite de temps) parce que le rendu d'une image peut prendre plus de 24 heures. Par conséquent, le processus Ffmpeg devrait attendre sans limite de temps. Cependant, je n'ai rien trouvé à ce sujet dans la documentation.

Je sais comment écrire sur stdin à partir de Node.js et d'autres choses techniques similaires, donc pas besoin de l'expliquer. La seule question (s) ici:

  1. Quels paramètres à transmettre à Ffmpeg?
  2. Ai-je besoin de créer un processus Ffmpeg (en utilisant child_process) avec des options spéciales?

Merci à l'avance. S'il vous plaît, prenez le temps, c'est ma première question! :)

+0

Ce sera sur le modèle de 'ffmpeg -f rawvideo -s 1920x1080 -framerate R -pixel_format rgb24 -i - sortie.mp4' – Mulvya

+0

@Mulvya. Donc, '-i -' est la réponse? Je me demandais juste pourquoi je ne l'ai pas trouvé dans les docs. Merci –

+0

@estus. Merci aussi. –

Répondre

2

Comme suggéré par @Mulvya et @estus, le paramètre correct est -i - (pour permettre l'entrée de stdin):

'use strict'; 

var cp = require('child_process'); 

var proc = cp.spawn('ffmpeg', [ 
    '-hide_banner', 
    '-f', 'rawvideo', 
    '-pix_fmt', 'rgb24', 
    '-s', '2x2', 
    '-i', '-', 
    '1.png' 
]); 

proc.stdin.write(Buffer.from([ 
    255, 0, 0, 
    0, 255, 0, 
    0, 255, 255, 
    255, 0, 255 
])); 

proc.stdin.end(); 

proc.stderr.pipe(process.stdout); 

Il produit cette image:
result
Il fonctionne pour les animations aussi .

Merci les gars pour aider!