Encoder une vid=c3=a9o pour en modifier la vitesse

10 réponses
Avatar
Francois Lafont
Bonjour à tous,

Je suis sous Ubuntu 18.04 et je cherche (pour un usage perso) à modifier
la vitesse de vidéos .mp4 prises avec mon smartphone. Je préviens, je n'y
connais rien encodage de vidéos. Point important peut-être, je me moque
de l'audio, la vidéo que je génère n'a pas de son (seule l'image m'importe).

En cherchant sur le Web, c'est vers ffmpeg que je me suis tourné mais je
n'ai aucune préférence, si un autre outil peut faire le job, je suis preneur.
Un peu par tâtonnement, j'ai trouvé cette commande qui me semble marcher :

factor=0.1 # Pour avoir une vitesse « x 0,1 » (ie 10 fois plus lente)
ffmpeg -i myvideo.mp4 -vf "setpts=(1/$factor)*PTS" -an \
-max_muxing_queue_size 4000 myvideo-slow.mp4

L'option « -max_muxing_queue_size 4000 », je l'ai mise car, sur certaines de
mes vidéos, je suis tombé sur le message d'erreur :

Too many packets buffered for output stream 0:0

et avec l'option l'erreur disparaissait (constat empirique).

Voici mes questions :

1. Est-ce que la façon de faire ci-dessus est correcte d'après vous ?
Peut-être qu'il existe des outils plus simples pour faire cela ?

2. En fait, je pensais que modifier la vitesse d'une vidéo était une
opération rapide où il fallait juste modifier une sorte de metadata du
fichier vidéo (une peu comme on modifierait un header dans une requête
HTTP). Mais je constate que :
a) l'encodage prend du temps (qq dizaines de secondes pour une vidéo
de 38MB en entrée);
b) la taille de la vidéo générée est plus grosse que la vidéo en
entrée (toujours avec mon exemple de vidéo de 38MB en entrée,
la vidéo « ralentie » générée fait 53MB).
Mon idée de la metadata à modifier est donc fausse ? C'est plus compliqué
que ça ? Certains players sont capables de lire une vidéo plus lentement
et pourtant j'imagine qu'ils ne réencodent pas la vidéo à la volée, non ?

3. Avec ma commande, j'ai parfois les messages suivants :

More than 1000 frames duplicated

Ils sont en jaune dans mon terminal, comme si c'était un warning ou une
erreur. Est-ce grave ?

Merci d'avance pour votre aide.

--
François Lafont

10 réponses

Avatar
Francois Lafont
On 5/2/19 1:15 AM, Francois Lafont wrote:
    factor=0.1 # Pour avoir une vitesse « x 0,1 » (ie 10 fois plus lente)
    ffmpeg -i myvideo.mp4 -vf "setpts=(1/$factor)*PTS" -an
        -max_muxing_queue_size 4000 myvideo-slow.mp4

[...]
1. Est-ce que la façon de faire ci-dessus est correcte d'après vous ?
   Peut-être qu'il existe des outils plus simples pour faire cela ?

Je précise que j'ai aussi regardé du côté du programme "mpv" qui avait
l'air de pouvoir faire plein de choses (comme du cropping ce qui pouvait
m'intéresser) mais je n'ai jamais réussi à modifier la vitesse de la
vidéo générée avec "mpv". Si quelqu'un sait comment faire avec "mpv",
ça m'intéresse.
--
François Lafont
Avatar
Jo Engo
Le Thu, 02 May 2019 01:15:25 +0200, Francois Lafont a écrit :
Voici mes questions :
1. Est-ce que la façon de faire ci-dessus est correcte d'après vous ?
Peut-être qu'il existe des outils plus simples pour faire cela ?

0. As-tu essayé de poser la question dans le groupe ad hoc ?
--
16:17 gege> Java en édition light, ca fait Java LE ? Ca sux...
Avatar
Nicolas George
Francois Lafont , dans le message
<5cca288d$0$3395$, a écrit :
Je suis sous Ubuntu 18.04 et je cherche (pour un usage perso) à modifier
la vitesse de vidéos .mp4 prises avec mon smartphone. Je préviens, je n'y
connais rien encodage de vidéos. Point important peut-être, je me moque
de l'audio, la vidéo que je génère n'a pas de son (seule l'image m'importe).

L'audio n'est pas un problème, il y a un filtre efficace pour changer la
vitesse.
En cherchant sur le Web, c'est vers ffmpeg que je me suis tourné mais je
n'ai aucune préférence, si un autre outil peut faire le job, je suis preneur.
Un peu par tâtonnement, j'ai trouvé cette commande qui me semble marcher :
factor=0.1 # Pour avoir une vitesse « x 0,1 » (ie 10 fois plus lente)
ffmpeg -i myvideo.mp4 -vf "setpts=(1/$factor)*PTS" -an
-max_muxing_queue_size 4000 myvideo-slow.mp4

C'est un bon début.
L'option « -max_muxing_queue_size 4000 », je l'ai mise car, sur certaines de
mes vidéos, je suis tombé sur le message d'erreur :
Too many packets buffered for output stream 0:0
et avec l'option l'erreur disparaissait (constat empirique).

L'avertissement disparaît, pas le problème sous-jacent. À première vue,
j'aurais pensé qu'il était causé par l'audio, mais -an est présent. Il
faudrait voir la sortie de diagnostic complète pour voir ce qui peut
clocher.
2. En fait, je pensais que modifier la vitesse d'une vidéo était une
opération rapide où il fallait juste modifier une sorte de metadata du
fichier vidéo (une peu comme on modifierait un header dans une requête
HTTP). Mais je constate que :
a) l'encodage prend du temps (qq dizaines de secondes pour une vidéo
de 38MB en entrée);

Oui, ta ligne de commande transcode la vidéo. Tu peux l'éviter avec « -c
copy », mais alors les filtres ne sont plus appliqués. Mais pour changer
la vitesse, si l'entrée a un débit d'images constant, l'option -r en
entrée devrait suffire.
b) la taille de la vidéo générée est plus grosse que la vidéo en
entrée (toujours avec mon exemple de vidéo de 38MB en entrée,
la vidéo « ralentie » générée fait 53MB).

Tu n'as spécifié aucune option pour la qualité, donc tu te retrouves
avec les valeurs par défaut.
Mon idée de la metadata à modifier est donc fausse ? C'est plus compliqué
que ça ?

Partiellement. Dans les formats décents, chaque paquet est marqué par le
temps où il est censé arriver, c'est ça qu'il faut ajuster. C'est plus
qu'une donnée globale pour le fichier, mais ça ne nécessite pas de tout
réencoder.
3. Avec ma commande, j'ai parfois les messages suivants :
More than 1000 frames duplicated
Ils sont en jaune dans mon terminal, comme si c'était un warning ou une
erreur. Est-ce grave ?

Oui. Mais pour voir pourquoi, il faudrait voir la sortie complète.
Avatar
Francois Lafont
Bonsoir,
On 5/2/19 10:03 AM, Jo Engo wrote:
0. As-tu essayé de poser la question dans le groupe ad hoc ?

Non. Je vais éviter de multiplier les fils de discussion maintenant que j'ai
posté ici mais je garde en tête cette possibilité si jamais mon fil n'aboutit
pas et tombe dans les oubliettes. ;)
--
François Lafont
Avatar
Nicolas George
Francois Lafont , dans le message
<5ccb586a$0$21611$, a écrit :
En fait, je n'ai pas réussi au début à reproduire l'erreur. C'est parce
que l'erreur apparaît seulement quand je ne mets *pas* l'option "-an"
(chose que je n'avais pas remarqué hier). Voici un exemple (sans l'option
"-an" donc) :

Sans -an, c'est normal : tu ralentis la vidéo mais pas l'audio, donc les
paquets vidéos doivent être mis en attente le temps que les paquets
audio les rattrapent.
WARNING: library configuration mismatch

Cette version de ffmpeg semble médiocrement compilée.
Ok, je vois. En effet, ne pas à avoir à transcoder la vidéo serait optimal
pour moi, vu que je souhaite conserver une vidéo en l'état (ie de même
qualité que l'originale) et seulement en modifier la vitesse de lecture. Par
contre, je n'ai pas dû bien comprendre le fonctionnement de l'option -r car
j'obtiens une vidéo qui me semble de même vitesse. Voici ma tentative :

L'option -r en entrée est censée marcher, mais elle cassez de temps en
temps. Essaie avec la toute dernière version, et si ça ne marche
signale-le sur le bug-tracker.
Ce cette sortie, je conclue (à tort peut-être, je n'y connais rien) que la
vitesse de lecture de la vidéo est de 240 frames par secondes.

Probablement, mais ce n'est pas certain. Le MP4 est vraiment un format pourri.
Ah ok. Mon but est de conserver la qualité de la vidéo identique à l'originale.

Si on ne transcode pas, la sortie est identique à l'original. Si on
transcode, cette notion n'a pas de sens rigoureusement défini.
Voici un exemple (je ne mets pas en verbose car c'est vraiment long, j'espère
qu'il y aura assez d'éléments) :

Le verbose est rarement utile, en fait.
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709/bt709/smpte170m), 1920x1080, 72527 kb/s, SAR 1:1 DAR 16:9, 239.68 fps, 240 tbr, 90k tbn, 180k tbc (default)
Stream #0:0(eng): Video: h264 (libx264) (avc1 / 0x31637661), yuv420p, 1080x1920 [SAR 1:1 DAR 9:16], q=-1--1, 240 fps, 15360 tbn, 240 tbc (default)

Voilà le problème : l'entrée semble être à 240 images par seconde, comme
tu l'as dit. Donc la sortie est mise au même rythme. Or le muxer MP4 de
ffmpeg ne supporte que les débits d'image constants. Donc il va chercher
à faire vraiment du 240 images par seconde, en décuplant chaque image.
Il faudrait préciser -r en sortie.
Avatar
Francois Lafont
On 5/2/19 11:50 PM, Nicolas George wrote:
Sans -an, c'est normal : tu ralentis la vidéo mais pas l'audio, donc les
paquets vidéos doivent être mis en attente le temps que les paquets
audio les rattrapent.

Ok.
WARNING: library configuration mismatch

Cette version de ffmpeg semble médiocrement compilée.

C'est la version packagée dans Ubuntu 18.04.
L'option -r en entrée est censée marcher, mais elle cassez de temps en
temps. Essaie avec la toute dernière version, et si ça ne marche
signale-le sur le bug-tracker.

Ok, je testerai.
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709/bt709/smpte170m), 1920x1080, 72527 kb/s, SAR 1:1 DAR 16:9, 239.68 fps, 240 tbr, 90k tbn, 180k tbc (default)
Stream #0:0(eng): Video: h264 (libx264) (avc1 / 0x31637661), yuv420p, 1080x1920 [SAR 1:1 DAR 9:16], q=-1--1, 240 fps, 15360 tbn, 240 tbc (default)

Voilà le problème : l'entrée semble être à 240 images par seconde, comme
tu l'as dit. Donc la sortie est mise au même rythme. Or le muxer MP4 de
ffmpeg ne supporte que les débits d'image constants. Donc il va chercher
à faire vraiment du 240 images par seconde, en décuplant chaque image.
Il faudrait préciser -r en sortie.

Et bien, sauf erreur, ça ne marche pas où alors je n'ai pas fait comme il
fallait :
---------------------------------------------------------
$ ffmpeg -i myvideo.mp4 -an -c copy -r 10 myvideo-slow.mp4; echo $?
ffmpeg version 3.4.4-0ubuntu0.18.04.1 Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 7 (Ubuntu 7.3.0-16ubuntu3)
configuration: [...]
avcodec configuration: [...]
libavutil 55. 78.100 / 55. 78.100
libavcodec 57.107.100 / 57.107.100
libavformat 57. 83.100 / 57. 83.100
libavdevice 57. 10.100 / 57. 10.100
libavfilter 6.107.100 / 6.107.100
libavresample 3. 7. 0 / 3. 7. 0
libswscale 4. 8.100 / 4. 8.100
libswresample 2. 9.100 / 2. 9.100
libpostproc 54. 7.100 / 54. 7.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'myvideo.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: isommp42
creation_time : 2019-05-01T15:10:26.000000Z
location : +48.7367+002.2386/
location-eng : +48.7367+002.2386/
com.android.version: 9
com.android.capture.fps: 240.000000
Duration: 00:00:03.97, start: 0.000000, bitrate: 72422 kb/s
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709/bt709/smpte170m), 1920x1080, 72527 kb/s, SAR 1:1 DAR 16:9, 239.68 fps, 240 tbr, 90k tbn, 180k tbc (default)
Metadata:
rotate : 90
creation_time : 2019-05-01T15:10:26.000000Z
handler_name : VideoHandle
Side data:
displaymatrix: rotation of -90.00 degrees
Stream #0:1(eng): Audio: aac (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 256 kb/s (default)
Metadata:
creation_time : 2019-05-01T15:10:26.000000Z
handler_name : SoundHandle
Output #0, mp4, to 'myvideo-slow.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: isommp42
com.android.capture.fps: 240.000000
location : +48.7367+002.2386/
location-eng : +48.7367+002.2386/
com.android.version: 9
encoder : Lavf57.83.100
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709/bt709/smpte170m), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 72527 kb/s, 239.68 fps, 240 tbr, 10240 tbn, 10 tbc (default)
Metadata:
rotate : 90
creation_time : 2019-05-01T15:10:26.000000Z
handler_name : VideoHandle
Side data:
displaymatrix: rotation of -90.00 degrees
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
frame= 946 fps=0.0 q=-1.0 Lsize= 34955kB time:00:03.94 bitrater623.8kbits/s speed= 182x
video:34945kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.029969%
0
---------------------------------------------------------
Et la vidéo générée a toujours une vitesse identique à l'originale.
--
François Lafont
Avatar
Francois Lafont
On 5/3/19 12:38 AM, Francois Lafont wrote:
L'option -r en entrée est censée marcher, mais elle cassez de temps en
temps. Essaie avec la toute dernière version, et si ça ne marche
signale-le sur le bug-tracker.

Ok, je testerai.

Je viens de tester avec la dernière version de ffmpeg (sauf erreur) et j'ai
toujours une vidéo générée de vitesse identique à la vidéo d'origine. J'ai
tenté avec -r en entrée puis avec -r en sortie. Voici les commandes :
-------------------------------------------------------------------
$ pwd
/home/flaf/tmp/ffmpeg-git-amd64-static/ffmpeg-git-20190429-amd64-static
$ ./ffmpeg -r 10 -i myvideo.mp4 -an -c copy myvideo-slow.mp4; echo $?
ffmpeg version N-48722-gac551c54b1-static https://johnvansickle.com/ffmpeg/ Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 6.3.0 (Debian 6.3.0-18+deb9u1) 20170516
configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio
--disable-outdev=sndio --cc=gcc-6 --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gmp
--enable-gray --enable-libaom --enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype
--enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg
--enable-librubberband --enable-libsoxr --enable-libspeex --enable-libvorbis --enable-libopus
--enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp
--enable-libx264 --enable-libx265 --enable-libxml2 --enable-libdav1d --enable-libxvid --enable-libzvbi
--enable-libzimg
libavutil 56. 26.100 / 56. 26.100
libavcodec 58. 52.100 / 58. 52.100
libavformat 58. 27.103 / 58. 27.103
libavdevice 58. 7.100 / 58. 7.100
libavfilter 7. 50.100 / 7. 50.100
libswscale 5. 4.100 / 5. 4.100
libswresample 3. 4.100 / 3. 4.100
libpostproc 55. 4.100 / 55. 4.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'myvideo.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: isommp42
creation_time : 2019-05-01T15:10:26.000000Z
location : +48.7367+002.2386/
location-eng : +48.7367+002.2386/
com.android.version: 9
com.android.capture.fps: 240.000000
Duration: 00:00:03.97, start: 0.000000, bitrate: 72422 kb/s
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709/bt709/smpte170m), 1920x1080, 72527 kb/s, SAR 1:1 DAR 16:9, 239.68 fps, 240 tbr, 90k tbn, 180k tbc (default)
Metadata:
rotate : 90
creation_time : 2019-05-01T15:10:26.000000Z
handler_name : VideoHandle
Side data:
displaymatrix: rotation of -90.00 degrees
Stream #0:1(eng): Audio: aac (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 256 kb/s (default)
Metadata:
creation_time : 2019-05-01T15:10:26.000000Z
handler_name : SoundHandle
Output #0, mp4, to 'myvideo-slow.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: isommp42
com.android.capture.fps: 240.000000
location : +48.7367+002.2386/
location-eng : +48.7367+002.2386/
com.android.version: 9
encoder : Lavf58.27.103
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709/bt709/smpte170m), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 72527 kb/s, 239.68 fps, 240 tbr, 10240 tbn, 10 tbc (default)
Metadata:
rotate : 90
creation_time : 2019-05-01T15:10:26.000000Z
handler_name : VideoHandle
Side data:
displaymatrix: rotation of -90.00 degrees
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
frame= 946 fps=0.0 q=-1.0 Lsize= 34955kB time:00:03.94 bitrater623.8kbits/s speed= 193x
video:34945kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.029966%
0
$ ./ffmpeg -i myvideo.mp4 -an -c copy -r 10 myvideo-slow.mp4; echo $?
ffmpeg version N-48722-gac551c54b1-static https://johnvansickle.com/ffmpeg/ Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 6.3.0 (Debian 6.3.0-18+deb9u1) 20170516
configuration: [...]
libavutil 56. 26.100 / 56. 26.100
libavcodec 58. 52.100 / 58. 52.100
libavformat 58. 27.103 / 58. 27.103
libavdevice 58. 7.100 / 58. 7.100
libavfilter 7. 50.100 / 7. 50.100
libswscale 5. 4.100 / 5. 4.100
libswresample 3. 4.100 / 3. 4.100
libpostproc 55. 4.100 / 55. 4.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'myvideo.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: isommp42
creation_time : 2019-05-01T15:10:26.000000Z
location : +48.7367+002.2386/
location-eng : +48.7367+002.2386/
com.android.version: 9
com.android.capture.fps: 240.000000
Duration: 00:00:03.97, start: 0.000000, bitrate: 72422 kb/s
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709/bt709/smpte170m), 1920x1080, 72527 kb/s, SAR 1:1 DAR 16:9, 239.68 fps, 240 tbr, 90k tbn, 180k tbc (default)
Metadata:
rotate : 90
creation_time : 2019-05-01T15:10:26.000000Z
handler_name : VideoHandle
Side data:
displaymatrix: rotation of -90.00 degrees
Stream #0:1(eng): Audio: aac (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 256 kb/s (default)
Metadata:
creation_time : 2019-05-01T15:10:26.000000Z
handler_name : SoundHandle
Output #0, mp4, to 'myvideo-slow.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: isommp42
com.android.capture.fps: 240.000000
location : +48.7367+002.2386/
location-eng : +48.7367+002.2386/
com.android.version: 9
encoder : Lavf58.27.103
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709/bt709/smpte170m), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 72527 kb/s, 239.68 fps, 240 tbr, 10240 tbn, 10 tbc (default)
Metadata:
rotate : 90
creation_time : 2019-05-01T15:10:26.000000Z
handler_name : VideoHandle
Side data:
displaymatrix: rotation of -90.00 degrees
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
frame= 946 fps=0.0 q=-1.0 Lsize= 34955kB time:00:03.94 bitrater623.8kbits/s speed= 204x
video:34945kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.029966%
0
-------------------------------------------------------------------
Est-ce qu'il faut considérer qu'il y a un bug ou je m'y suis mal pris ?
--
François Lafont
Avatar
Nicolas George
Francois Lafont , dans le message
<5ccb7179$0$31434$, a écrit :
C'est la version packagée dans Ubuntu 18.04.

C'est bien ce que je disais...
Et bien, sauf erreur, ça ne marche pas où alors je n'ai pas fait comme il
fallait :
$ ffmpeg -i myvideo.mp4 -an -c copy -r 10 myvideo-slow.mp4; echo $?

Il faut utiliser l'option -r en sortie avec setpts, et donc sans -c
copy.
Et la vidéo générée a toujours une vitesse identique à l'originale.

Mais a bien dix images par seconde.
Avatar
Nicolas George
Francois Lafont , dans le message
<5ccb761d$0$3517$, a écrit :
Je viens de tester avec la dernière version de ffmpeg (sauf erreur) et j'ai

Erreur : 32 commits de retard. Aucun n'est en rapport avec le problème,
mais ça aurait pu si c'est un bug qui a été réintroduit récemment.
Il vaut mieux compiler soi-même.
$ ./ffmpeg -r 10 -i myvideo.mp4 -an -c copy myvideo-slow.mp4; echo $?
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709/bt709/smpte170m), 1920x1080, 72527 kb/s, SAR 1:1 DAR 16:9, 239.68 fps, 240 tbr, 90k tbn, 180k tbc (default)

De mémoire, c'est censé marcher. Manifestement, ce n'est pas le cas,
donc...
Est-ce qu'il faut considérer qu'il y a un bug ou je m'y suis mal pris ?

Oui.
Accessoirement :
echo $?

... est avantageusement remplacé par « setopt printexitvalue » dans zsh.
Avatar
Francois Lafont
Bonjour,
On 5/3/19 11:15 AM, Nicolas George wrote:
Est-ce qu'il faut considérer qu'il y a un bug ou je m'y suis mal pris ?

Oui.

Pour information, j'ai tenté un bug report ici :
https://trac.ffmpeg.org/ticket/7911
À suivre...
--
François Lafont