ffmpeg

ffmpeg

  • Atualizado script pra geração de vídeo com a GoPro

    Como eu já tinha descrito em Renderizando as fotos da GoPro em vídeo mpeg4 com ffmpeg e NVIDIA, eu gero imagens das pedaladas a cada 0.5 segundo atualmente, e uso ffmpeg pra juntar tudo e fazer o vídeo.

    Recentemente fiz algumas melhoria pra além de gerar o vídeo e transformar em 1080p, também estabilizar.

    E melhorei as mensagens.

    O script está atualizado no CodeBerg:

    https://codeberg.org/helioloureiro/homemadescripts/src/branch/master/render-video-from-gopro-photos.sh

    E agora precisa de uma lib, a heliolib.sh (bem imaginativo o nome), que também está lá:

    https://codeberg.org/helioloureiro/homemadescripts/src/branch/master/heliolib.sh

    O resultado desse template de teste, com só 500 imagens (uma pedalada longa é geralmente algo em torno de 35.000-50.000 imagens), está aqui no YouTube:

    Não é a versão inicial porque o tamanho segue o mesmo das imagens de 4000x3000 pixels.  Nem todo player consegue lidar com vídeo nesse formato.  E o YouTube acaba jogando pra 1080p.

    Já o segundo vídeo, que é acelerado em 10x é esse aqui:

    E finalmente o mesmo vídeo, mas estabilizado:

    O estabilizado não fica lá muito melhor que o anterior, mas é bem mais rápido fazer com o ffmpeg-cuda e jogar pra GPU que deixar pra fazer depois no kdenlive.

     

     

  • Capturas da webcam atualizado pra 2024

    Esse é um update to artigo usando python pra capturar a webcam. E com o uso do obamawatched 2021. Eu atualizei recentemente o obamawatcher pra rodar com PySide6 e está aqui funcionando no meu laptop atual de trabalho. No meu pessoal também. Ao menos acho que está funcionando.

    O resultado final já está no vídeo acima. Como são várias imagens, os comandos que listei antes já não funcionam muito bem. Eu precisei primeiro redimensionar as imagens pra 640x360 para ficar em widescreen (16:9). As fotos mais antigas saíram em formato quadrado porque era o que a Webcam suportava na época. Então precisei cortar pra ficarem no aspecto correto. E pra isso eu usei python com pillow.

      
        #! /usr/bin/env python3
    
    import os
    import re
    import argparse
    try:
        from PIL import Image
    except ModuleNotFoundError as e:
        raise Exception("missing pillow - run: pip install Pillow") from e
    
    
    golden_rate = 1280/720
    default_size_x = 640
    default_size_y = 360
    
    parse = argparse.ArgumentParser(description="Script to resize pictures from a specific directory to the same size")
    parse.add_argument("--directory", required=True, help="directory with images jpg")
    args = parse.parse_args()
    
    for filename in sorted(os.listdir(args.directory)):
        if not re.search("jpg", filename):
            continue
        with Image.open(args.directory + "/" + filename) as image:
            width, height = image.size
            rate = float(width)/float(height)
            is_golden = rate == golden_rate
    
            is_correted = False
            rate_from_default = width / default_size_x
            if rate_from_default == 1:
                pass 
            elif rate_from_default > 1:
                image = image.resize((default_size_x, int(height/rate_from_default)))
                is_correted = True
            else:
                image = image.resize((default_size_x, int(height/rate_from_default)), Image.Resampling.LANCZOS)
                is_correted = True
    
            if not is_golden:
                image = image.crop((0, 0, default_size_x, default_size_y))
    
            image.save(filename)
            print(f"{filename}: {width}x{height}, golden: {is_golden}, corrected: {is_correted}")
    
    
    print(f"Golden rate: {golden_rate}")
     
    

    Tendo as imagens no mesmo formato, basta ordernar e usar ffmpeg pra montar o vídeo.

      
    #! /usr/bin/env bash
    
    die() {
      echo "$1" >&2
      exit 1
    }
    
    counter=0
    for img in [0-9]*.jpg
    do
      serial=$(printf "%06d" $counter)
      new_name="G${serial}.JPG"
      counter=$(expr $counter + 1)
      if [ -f "$new_name" ]; then
        echo "$new_name already exists"
        continue
      fi
      echo "$img => $new_name"
      mv $img $new_name
    done
    
    case $(uname -s) in
      Linux)
        echo "Merging images into single video file: output.mp4"
        ffmpeg -r 8 -i G%06d.JPG -c:v h264 -b:v 5M output.mp4 || \
          die "Failed to render output.mp4"
        ;;
      Darwin) 
        echo "Merging images into single video file: output.mp4"
        ffmpeg -hwaccel auto -r 8 -i G%06d.JPG -c:v h264_videotoolbox -b:v 5M output.mp4 || \
          die "Failed to render output.mp4"
    esac    
     
    

    Eu não testei o código de macOS, então pode ser que não funcione. Meu PC atual, um Lenovo Thinkpad, é processador e GPU Intel. Eu tentei usar -hwaccel vaapi mas as cores saiam erradas, no estilo negativo de filme. Então deixei rodar no processador mesmo.

    E pra comparar o resultado em mpeg comparado com o mesmo em gif:

      
    ░▒▓ …/tmp/imagens-webcam/Webcam2 via v3.12.3 (venv) 15:33 
    ❯ gm convert -delay 20 *JPG output.gif
    ░▒▓ …/tmp/imagens-webcam/Webcam2 via v3.12.3 (venv) 15:38 
    ❯ ls -l output.*
    .rw-rw-r-- 209M helio 27 Nov 15:38  output.gif
    .rw-rw-r-- 103M helio 27 Nov 13:54  output.mp4
     
    

    A geração do gif demorou uma eternidade, 5 minutos. O ffmpeg foram só alguns segundos. O tamanho foi o dobro no gif. Pra ver a imagem, teria de carregar tudo e só depois ver o resultando. Como mpeg, vai enviando o vídeo aos poucos.

    Eu finalizei o vídeo no kdenlive, fazendo o merge com o vídeo anterior e adicionando a música. Ficou uma nostalgia gostosa.

    E com certeza atualizarei daqui alguns anos.

  • Gerando vídeo de images jpeg com ffmpeg usando aceleração de hardware no MacOS

    Eu já escrevi sobre isso em Linux com Intel (Usando a GPU para renderizar vídeo) e depois em Linux com NVIDIA (Renderizando as fotos da GoPro em vídeo mpeg4 com ffmpeg e NVIDIA).  Agora eu testei como fazer isso no MacOS.

    E deu muito certo.

    O comando e saída foram esses:

    $ ffmpeg -r 1 -i G%04d.JPG -c:v h264_videotoolbox -b:v 5M -pix_fmt yuv420p output.mp4
    ffmpeg version 6.0 Copyright (c) 2000-2023 the FFmpeg developers
      built with Apple clang version 14.0.3 (clang-1403.0.22.14.1)
      configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/6.0 --enable-shared --enable-pthreads 
    --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls
    --enable-gpl --enable-libaom --enable-libaribb24 --enable-libbluray --enable-libdav1d
    --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband
    --enable-libsnappy --enable-libsrt --enable-libsvtav1 --enable-libtesseract --enable-libtheora
    --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp
    --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma
    --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass
    --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex
    --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack
    --enable-videotoolbox --enable-neon libavutil 58. 2.100 / 58. 2.100 libavcodec 60. 3.100 / 60. 3.100 libavformat 60. 3.100 / 60. 3.100 libavdevice 60. 1.100 / 60. 1.100 libavfilter 9. 3.100 / 9. 3.100 libswscale 7. 1.100 / 7. 1.100 libswresample 4. 10.100 / 4. 10.100 libpostproc 57. 1.100 / 57. 1.100 Input #0, image2, from 'G%04d.JPG': Duration: 00:03:05.08, start: 0.000000, bitrate: N/A Stream #0:0: Video: mjpeg (Baseline), yuvj422p(pc, bt470bg/unknown/unknown), 4000x3000, 25 fps, 25 tbr, 25 tbn File 'output.mp4' already exists. Overwrite? [y/N] y Stream mapping: Stream #0:0 -> #0:0 (mjpeg (native) -> h264 (h264_videotoolbox)) Press [q] to stop, [?] for help [swscaler @ 0x130018000] deprecated pixel format used, make sure you did set range correctly [swscaler @ 0x128478000] deprecated pixel format used, make sure you did set range correctly [swscaler @ 0x138008000] deprecated pixel format used, make sure you did set range correctly [swscaler @ 0x108e58000] deprecated pixel format used, make sure you did set range correctly Output #0, mp4, to 'output.mp4': Metadata: encoder : Lavf60.3.100 Stream #0:0: Video: h264 (avc1 / 0x31637661), yuv420p(tv, bt470bg/unknown/unknown, progressive), 4000x3000, q=2-31, 5000 kb/s, 1 fps, 16384 tbn Metadata: encoder : Lavc60.3.100 h264_videotoolbox frame= 4627 fps= 21 q=-0.0 Lsize= 2824030kB time=01:17:06.00 bitrate=5001.0kbits/s speed=21.5x video:2823985kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.001582%

    O que fez a mágica aqui foi o parâmetro "h264_videotoolbox".  Juntei 4626 imagens JPEG da última pedalada que fizemos em um vídeo de pouco mais de 1 hora.  E agora vou trabalhar em cima pra fazer o vídeo no formato adequado, trilha sonora e tamanho menor.

  • Meu hackzinho em cima de ffmpeg-full-git do AUR

    Eu tenho uma placa de vídeo relativamente antiga: NVIDIA GTX 1050ti.  Ela tem servido bem pro que preciso, mas deixa pra trás em alguns quesitos como rodar algum modelo mais complexo pelo ollama.  Mas complexo?  Nem os mais simples têm rodado.  Porém o meu maior uso é renderizar os vídeos das pedaladas.  Já escrevi o processo que faço aqui: Renderizando as fotos da GoPro em vídeo mpeg4 com ffmpeg e NVIDIA.

    O problema surgiu quando a NVIDIA anunciou que abandonaria o suporte pra essa placa.  A solução?  Parar de usar o pacote do próprio archlinux e passar a usar um do AUR.  Até aí, sem grandes problemas.  Archlinux é feito pra esse tipo de coisa.  O problema foi que eu usava o pacote ffmpeg-cuda e esse parou de receber updates.

    A primeira solução que tentei foi fazer o build do pacote ffmpeg-full-git.  Depois de trocentas horas compilando, erro.  E não consegui resolver.

    Então parti pra uma solução própria: peguei o pacote do ffmpeg-full-git, removi boa parte do que precisa pra compilar, olhei o que tinha no ffmpeg-cuda e... voilá!  Pacote compilado.

    E subi a solução toda pro codeberg, caso alguém também precise.

    https://codeberg.org/helioloureiro/archlinux-ffmpeg-cuda

    Eu vou precisar manter atualizado em algum momento.  Mas depois descubro como farei isso.  Um problema de cada vez.