English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Utilisation de ffmpeg pour synchroniser la lecture audio et vidéo avec Javacv

Récemment, j'ai utilisé le capturateur de trame FFmpegFrameGrabber du paquet javaCV pour synchroniser la lecture des trames audio et vidéo capturées. La méthode de synchronisation utilisée est la synchronisation vidéo vers l'audio.

Programme et code source

Les idées spécifiques sont les suivantes :

(1)Présentation de la manière dont ffmpeg capture les images et le son des fichiers vidéo

FFmpegFrameGrabber fg = new FFmpegFrameGrabber("un chemin de fichier vidéo ou une URL); 

Après avoir obtenu l'objet du capturateur de trame, appeler sa méthode grab() renvoie l'objet Frame capturé. Ce Frame peut être une trame vidéo ou une trame audio, car les trames audio et vidéo sont alignées dans l'ordre du timestamp en fonction du temps de lecture. Bien sûr, les trames capturées sont déjà décodées et stockées dans l'objet java.nio.Buffer, pour les trames vidéo, le Buffer stocke les données des pixels de l'image, par exemple RGB, puis

BufferedImage bi = (new Java2DFrameConverter()).getBufferedImage(f); 

On peut obtenir une image, et cette image peut être traitée ou affichée directement dans un composant Swing. En ce qui concerne les trames audio, le Buffer est utilisé pour stocker les données PCM de l'audio, qui peuvent être de type float ou short. Ensuite, en utilisant la méthode write de sourceDataLine dans java.sounds.sample, ces données PCM audio peuvent être écrites dans le haut-parleur.

(2)Puis, présentons comment jouer en continu les cadres obtenus. Tout d'abord, jouer le vidéo seul:

while(true) 
{ 
  Frame f = fg.grab();  
  if(f.image!=null) 
  label.setIcon(new ImageIcon((new Java2DFrameConverter()).getBufferedImage(f))); 
  Thread.sleep(1000/framerate);  
} 

La lecture audio seule est la même, écrivez les données sur la carte son.

(3)modèle producteur-consommateur.

Le schéma ci-dessus est la méthode d'implémentation du programme, utilisant le modèle producteur-consommateur pour juger des cadres capturés, s'il s'agit d'un cadre vidéo, il est produit dans le FIFO vidéo, s'il s'agit d'un cadre audio, il est produit dans le FIFO audio, puis les threads de lecture audio et vidéo consomment respectivement les cadres de leurs dépôts. La raison pour laquelle nous utilisons le modèle producteur-consommateur est que la vitesse de capture des cadres est supérieure à la consommation des cadres, donc nous préférons capturer les cadres pour缓冲 ou prétraiter davantage les cadres capturés, tandis que les threads de lecture vidéo et audio n'ont besoin que de jouer directement les cadres traités.

(4)Méthode pour réaliser la synchronisation audio-vidéo : jouer tous les cadres vidéo dans les deux cadres audio.

Pour réaliser la synchronisation audio-vidéo, il faut avoir le timestamp du cadre, ici, les cadres capturés ne contiennent que le timestamp de lecture PTS, pas le timestamp de décodage DTS, donc nous devons décider de la lecture uniquement en fonction du timestamp de lecture.

l'implémentation du programme est basée sur le schéma ci-dessus, lorsque la file d'attente audio commence à jouer le cadre audio A1lorsque, appeler la méthode setRun de la file d'attente vidéo, et transmettre le timestamp du cadre audio à jouer curTime et le prochain cadre audio A2le timestamp nextTime est donné à la file d'attente vidéo en état d'attente, puis la file d'attente vidéo démarre, commence à extraire les cadres vidéo G du FIFO vidéo1ensuite, calculer G1et A1l'écart de temps, en tant que délai de lecture, Thread.sleep(t1) après quoi, la file d'attente vidéo affiche l'image sur le composant Swing, par exemple JLabel.setIcon(image). Ensuite, la file d'attente vidéo tire un cadre d'image G2comparaison G2le timestamp et A2le timestamp, si G2le timestamp est inférieur à A2donc, la file d'attente vidéo continue de décaler de t2après, jouer cette G2l'image, puis G3de la même manière, jusqu'à ce que G soit obtenu4et A2comparaison révèle G4le timestamp est supérieur à A2donc, la file d'attente vidéo entre en état d'attente, en attendant le prochain démarrage. Ensuite, la file d'attente audio joue A1Après que le cadre audio a été joué, le cadre audio A est pris à partir du dépôt3ensuite, puis A2le timestamp et A3le timestamp est transmis à la file d'attente vidéo, puis commence à jouer A2Puis, la file d'attente de la vidéo continue de jouer de la même manière.

(5)Ajustement dynamique du temps d'attente

Comme les PC personnels ne sont pas des systèmes d'exploitation temps réel, c'est-à-dire que Thread.sleep n'est pas précis et est contraint par la lecture du son de la carte son, donc la méthode sourceDataLine de Java doit être améliorée. Premièrement, la méthode sourceDataLine de Java tire des données du tampon interne à une certaine vitesse pour que le thread audio les écrive, si les données audio sont complètement récupérées, la lecture audio peut être bloquée, mais si trop de données audio sont écrites à la fois, la synchronisation audio-vidéo peut être perturbée, donc il faut s'assurer que le tampon interne de sourceDataLine est laissé avec une certaine quantité de données, sinon cela peut entraîner des blocages, mais la quantité de données ne peut pas être trop importante, donc nous devons régler G3à A2pendant cette période pour régler la lecture du son, en raison de l'imprécision de l'attente, l'écriture de A1données de trames peuvent ne pas être remplies à temps t6peut être complètement récupéré par la carte son, donc les données du G3Après avoir créé l'image, le thread de lecture de son jugera en fonction de la quantité de données retournée par sourceDataLine.available() pour déterminer si la quantité de données est presque épuisée, puis réduira G3à A2du temps d'attente t4De cette manière, vous pouvez vous assurer que la quantité de données ne deviendra pas 0 et que le son ne sera pas bloqué.

(6)Voici le programme dans window64Le test suivant et ubuntu14Le graphique de test suivant : La lecture est fluide, la synchronisation est également possible, mais en ouvrant la lecture, il peut y avoir des problèmes de ralentissement par rapport à l'écriture de code dans un IDE comme IDEA, car IDEA est également développé en Java, donc l'exécution d'IDEA peut affecter d'autres programmes Java, mais d'autres processus ne le feront pas.


Voici la totalité du contenu de cet article, j'espère qu'il vous sera utile dans vos études, et j'espère que vous soutiendrez également le tutoriel d'encouragement.

Déclaration : le contenu de cet article est issu du réseau, propriété de l'auteur original, le contenu est apporté par les utilisateurs d'Internet de manière volontaire et téléversé, ce site ne détient pas de droits de propriété, n'a pas été traité par l'éditeur humain et n'assume aucune responsabilité juridique. Si vous trouvez du contenu présumé de violation de droits d'auteur, veuillez envoyer un e-mail à : notice#oldtoolbag.com (au moment de l'envoi d'un e-mail, veuillez remplacer # par @ pour signaler une violation, et fournir des preuves pertinentes. Une fois vérifié, le site supprimera immédiatement le contenu présumé de violation de droits d'auteur.)

Vous pourriez aimer