Executando verificação de segurança...
2

Como gerei mais de 200 thumbnails em menos de 20 minutos com Python

Eu estava trabalhando em um projeto que envolvia uma base de dados contendo diversos vídeos em formato MP4 armazenados no Firebase. A necessidade principal era exibir a miniatura (thumbnail) desses vídeos no aplicativo, mas sem comprometer a performance e sobrecarregar o processamento.

Após uma investigação aprofundada e várias tentativas, desenvolvi uma solução automatizada usando Python e Firebase, que simplifica significativamente este processo.

Todo o código mostrado aqui está disponível no Colab.

Passo 1: Configuração das dependências

import os
import firebase_admin
from firebase_admin import credentials, firestore
from google.cloud import storage
import requests
from moviepy.editor import VideoFileClip
import tempfile

Passo 2: Configuração do firebase
O código, disponível no Colab, requer a configuração das seguintes dependências:

# Defina o caminho para o arquivo JSON da chave privada do Google
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "/content/example.json"

# Inicialize o Firebase Admin apenas se ainda não tiver sido inicializado
if not firebase_admin._apps:
    cred = credentials.Certificate("/content/example.json")
    firebase_admin.initialize_app()

# criando instância do Firestore e Cloud Storage
db = firestore.client()
firebase_bucket_name = 'BUCKET_DO_DATABASE_AQUI'
client = storage.Client()
bucket = client.get_bucket(bucket_or_name = firebase_bucket_name)

Passo 3: Criação das funções
Temos 4 funções auxiliares que fazem cada parte do processo de forma isolada.

  1. download_video: Baixa vídeos a partir de URLs fornecidas.
  2. generate_thumbnail: Usa moviepy para extrair e salvar um frame como thumbnail.
  3. upload_thumbnail_to_storage: Carrega o thumbnail gerado no Firebase Storage.
  4. update_document_with_thumbnail: Atualiza o documento Firestore com a URL do thumbnail gerado.
# Função para baixar um vídeo da URL fornecida
def download_video(url):
    temp_video_path = tempfile.NamedTemporaryFile(delete=False).name
    response = requests.get(url)
    with open(temp_video_path, 'wb') as file:
        file.write(response.content)
    return temp_video_path

# Função para gerar um thumbnail do vídeo
def generate_thumbnail(video_path):
    temp_thumbnail_path = tempfile.NamedTemporaryFile(suffix='.png', delete=False).name
    with VideoFileClip(video_path) as clip:
        clip.save_frame(temp_thumbnail_path, t=1)
    return temp_thumbnail_path

# Função para carregar o thumbnail gerado para o Firebase Storage
def upload_thumbnail_to_storage(bucket_name, local_thumbnail_path, thumbnail_storage_path):
    with open(local_thumbnail_path, 'rb') as image_file:
        blob = bucket.blob(thumbnail_storage_path)
        blob.upload_from_file(image_file, content_type='image/png')
        blob.make_public()
        file_url = blob.public_url
    return file_url

# Função para atualizar o documento Firestore com a URL do thumbnail
def update_document_with_thumbnail(document_id, thumbnail_url):
    video_ref = db.collection('videos').document(document_id)
    video_ref.update({'thumb': thumbnail_url})

Passo 4: Criação da função principal

def process_all_videos():
    db = firestore.Client()
    videos_ref = db.collection('videos') #Collection onde estão os dados que quero atualizar
    snapshot = videos_ref.get()

    if not snapshot:
        return 'Nenhum vídeo encontrado.'

    for doc in snapshot:
        video_id = doc.id
        video_data = doc.to_dict()
        video_url = video_data['videoUrl'] # Campo de referência para o vídeo ao qual quero criar a thumb
        local_video_path = download_video(video_url)
        local_thumbnail_path = generate_thumbnail(local_video_path)
        thumbnail_storage_path = f'thumbs/{video_id}.png'
        thumbnail_url = upload_thumbnail_to_storage(firebase_bucket_name, local_thumbnail_path, thumbnail_storage_path)
        update_document_with_thumbnail(video_id, thumbnail_url)
        os.remove(local_video_path)
        os.remove(local_thumbnail_path)

    return 'Todos os vídeos foram processados.'

O Algoritmo demorou 17 minutos para gerar 210 thumbnails de forma automática para todos os registros que tenho no Firebase, um feito que manualmente levaria horas, se não dias, para completar.

Carregando publicação patrocinada...
2

Interessante, o método "generate_thumbnail" você sempre está utilizando o parâmetro t=1 , não seria o caso de avaliar se nesse momento o video tem de fato alguma imagem "útil" para thumbnail? Uma tela preta,por exemplo, neste momento poderia prejudicar o resultado do método.

1

Sugestão super válida, vou considerar rodar um teste paralelo para verificar o resultado!

No cenário que eu tinha não fiz essa verificação pois se tratavam de vídeos de crossfit, e sempre nos primeiros segundos o instrutor do vídeo estava na posição do movimento que ia ensinar, então preferi manter t=1 pq já teria uma imagem bem legal!