comment puis-je extraire de la vidéo en utilisant ffmpeg avec des informations d'horodatage

2

J'utilise ffmpeg pour extraire une image et l'enregistrer dans un fichier jpg comme suit.

ffmpeg -i video.avi -r 1 -f image2 -q 1 %05d.jpg

Cependant, comment puis-je obtenir les informations d'horodatage de chaque image extraite. Par exemple, je voudrais enregistrer le fichier jpg avec le nom de fichier sous le nom hh_mm_ss.jpg?

Min Sun
la source
Jetez un oeil à cette question posée sur Stack Overflow. La réponse acceptée fournit une solution de contournement à l'aide d'ImageMagick, car FFmpeg n'est pas capable de le faire lui-même.
Nick van Tilborg
@NickvanTilborg Je pense que la question demande des horodatages pris dans la vidéo (PTS, Presentation Time Stamp) - de sorte qu'une image prise à une minute 30 secondes dans la vidéo aurait un nom de fichier comme 00_01_30.jpg- plutôt que l'horodatage de l'heure système à laquelle le fichier a été créé.
Evilsoup
Ah oui, mais alors un simple script de changement de nom devrait faire l'affaire. @MinSun, pouvez-vous s'il vous plaît confirmer ce que vous voulez?
Nick van Tilborg
J'ai la même question, précisément ce que je crois qu'il demande (comme je le suis) pour l'horodatage de la vidéo, c'est-à-dire qu'une image prise 20 secondes après dans la vidéo aurait un nom de fichier avec: image-00_20_00.jpg
davidparks21

Réponses:

1

Eh bien, il semble que ffmpeg ne puisse pas gérer cela (pas plus que d’autres solutions populaires telles que VLC Media Player). Une solution de contournement que j'ai utilisée consiste à obtenir la durée de la vidéo ffmpeg -i video_file.mp4et à la diviser par le nombre d'images.

À titre d'exemple, voici un script bash que j'ai écrit: le traitement par lots traite un ensemble de vidéos, les divise en images (@ 30 ips) et renomme les fichiers afin qu'ils aient à la fois l'horodatage de la vidéo (en millisecondes à compter du début de la vidéo) et le numéro de l'image. à l'origine.

Je suis sûr que le script pourrait être plus efficace, mais il fonctionne assez bien pour mes besoins, donc j'espère qu'il trouvera une utilisation (puisque cette question est à venir dans les recherches sur Google):

# Regular expression definitions to get frame number, and to get video duration from ffmpeg -i
FRAME_REGEX="frame-([0-9]*)\.jpeg"
LEN_REGEX="Duration: ([0-9]*):([0-9]*):([0-9]*)\.([0-9]*), start"

# Loops through the files passed in command line arguments, 
# example: videotoframes video-*.mp4
#      or: videotoframes file1.mp4 file2.mp4 file3.mp4
for vf in "$@"; do
    video_info=$(ffmpeg -i $vf 2>&1)                                                                                                                        # Get the video info as a string from ffmpeg -i
    [[ $video_info =~ $LEN_REGEX ]]                                                                                                                         # Extract length using reges; Groups 1=hr; 2=min; 3=sec; 4=sec(decimal fraction)
    LENGTH_MS=$(bc <<< "scale=2; ${BASH_REMATCH[1]} * 3600000 + ${BASH_REMATCH[2]} * 60000 + ${BASH_REMATCH[3]} * 1000 + ${BASH_REMATCH[4]} * 10")          # Calculate length of video in MS from above regex extraction

    mkdir frames-$vf                                                # Make a directory for the frames (same as the video file prefixed with "frames-"
    ffmpeg -i $vf -r 30 -f image2 frames-$vf/frame-%05d.jpeg        # Convert the video file to frames using ffmpeg, -r = 30 fps
    FRAMES=$(ls -1 frames-$vf | wc -l)                              # Get the total number of frames produced by the video (used to extrapolate the timestamp of the frame in a few lines)

    # Loop through the frames, generate a timestamp in milliseconds, and rename the files
    for f in frames-$vf/frame-*; do
        [[ $f =~ $FRAME_REGEX ]]                                                        # Regex to grab the frame number for each file
        timestamp=$(bc <<< "scale=0; $LENGTH_MS/$FRAMES*${BASH_REMATCH[1]}")            # Calculate the timestamp (length_of_video / total_frames_generated * files_frame_number)
        `printf "mv $f frames-$vf/time-%07d-%s" $timestamp $(basename $f)`              # Execute a mv (move) command, uses the `printf ...` (execute command returned by printf) syntax to zero-pad the timestamp in the file name
    done;
done;
davidparks21
la source