Linux: Como extrair frames de um vídeo? (sem perdas)

Linux: Como extrair frames de um vídeo? (sem perdas)

Li algumas respostas e artigos sobre o uso de programas como VLC, MPlayer, ffmpeg, etc., mas nenhum dos métodos que vi é "sem perdas". Eles não capturam todos os quadros. Quero extrair cada quadro de um vídeo como uma imagem (qualidade 100%, não quero perder nenhum detalhe), para que teoricamente se possa pegar essas imagens e recriar o arquivo de vídeo sem saber a diferença de o original (excluindo a falta de áudio, é claro).

Pontos de bônus se eu puder especificar um horário de início e término para capturar os quadros, para não precisar cortar o arquivo de vídeo com antecedência.

Responder1

Você pode extrair os quadros como PNG, um formato de compactação de imagem sem perdas. Por exemplo, para extrair frames da marca de 5 minutos para a marca de 10 minutos:

ffmpeg -ss 05:00 -i <input> -t 05:00 filename%05d.png

Responder2

Existem várias ferramentas que devem ser capazes de extrair todos os quadros de um arquivo de filme:

avconv
avconv -i file.avi -f image2 Out%00d.jpg

ffmpeg
ffmpeg -i input.file thumb%04d.png -hide_banner

Isso também pode exportar BMP, que leva muito menos tempo de processamento do que PNG ou JPG.

Há também um script bash chamadomov2frame.shque tenta automatizar o processo de extração do FFMPEG.

Jogador
mplayer -ao null -vo png input.file

ou outra opção:

mplayer -nosound -vo png:z=9 my_file.mp4

VLC Aparentemente, este reprodutor de mídia pode exportar conjuntos de imagens usando seus filtros, mas parece problemático, a menos que seja seu único uso ou você tenha uma versão portátil.

  1. Crie uma pasta para armazenar seus frames e copie o caminho para ela. Para usuários de Mac OSX/Linux, este deve ser o caminho completo (sem ~).

  2. Clique em Ferramentas/Preferências no VLC.

  3. Em “mostrar configurações”, clique em “todos”.

  4. Em “Vídeo”, selecione “Filtros”. Marque “Filtro de vídeo de cena”.

  5. Expanda “Filtros” e selecione “Filtro de cena”,

  6. Cole o caminho anterior em “prefixo do caminho do diretório”.

  7. Escolha a fração de quadros a codificar na caixa “proporção de gravação”. 1/12 com saída a cada 12, 1/1 exportará todos eles

  8. Clique em “salvar”.

  9. Clique em Mídia / Abrir vídeo e encontre seu vídeo. Pacientemente, deixe tudo acontecer.

  10. Clique em Ferramentas/Preferências. Em “mostrar configurações”, clique em “todos”. Em “vídeo”, selecione “filtros”. Desmarque “Filtro de vídeo de cena”. Clique em “salvar”. Isso ocorre para que o VLC não gere miniaturas na próxima vez que você reproduzir um vídeo. link

Também parece haver algum problema potencial com as permissões de administrador na primeira execução do programa:

sudo vlc [sudo] password for mint16: VLC is not supposed to be run as root. Sorry. If you need to use real-time priorities and/or privileged TCP ports you can use vlc-wrapper (make sure it is Set-UID root and cannot be run by non-trusted users first).

O VLC também tem um desempenho muito melhor ao extrair para BMP em vez de PNG

Responder3

Ao fazer isso com o ffmpeg, descobri que muitas vezes preciso usar a -vsync 0opção (por exemplo, ao trabalhar com alguns arquivos VOB de DVDs):

ffmpeg -i video.VOB -vsync 0 %06d.bmp

Se você quiser definir um horário de início e de término também, seria mais ou menos assim:

ffmpeg -i video.VOB -vsync 0 -ss 01:30 -to 01:40 %06d.bmp

Responder4

Abaixo está o código em opencv que funcionou para extrair frames do vídeo.

import cv2
import os

# Replace 'your_video_file.mp4' with the path to your video file
video_path = 'your_video_file.mp4'

# Create a VideoCapture object
cap = cv2.VideoCapture(video_path)

# Check if the video file is opened successfully
if not cap.isOpened():
    print("Error: Could not open video file.")
    exit()

# Create a directory to store the frames
output_directory = 'frames'
os.makedirs(output_directory, exist_ok=True)

# Loop to read frames from the video
frame_count = 0
while True:
    # Read a frame from the video
    ret, frame = cap.read()

    # Check if the frame is read successfully
    if not ret:
        print("End of video.")
        break

    # Save the frame as an image file
    frame_filename = os.path.join(output_directory, f'frame_{frame_count:04d}.png')
    cv2.imwrite(frame_filename, frame)

    frame_count += 1

# Release the VideoCapture object
cap.release()

print(f"{frame_count} frames saved in '{output_directory}'.")

informação relacionada