Carlex22222 commited on
Commit
2667dea
·
verified ·
1 Parent(s): 04e5cdc

Upload 4 files

Browse files
Files changed (4) hide show
  1. Dockerfile +45 -0
  2. README.md +12 -7
  3. environment.yml +55 -0
  4. main.py +108 -0
Dockerfile ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dockerfile (VERSÃO FINAL PARA API FASTAPI)
2
+
3
+ # 1. COMEÇAR COM A BASE CORRETA
4
+ FROM nvidia/cuda:12.1.1-devel-ubuntu22.04
5
+
6
+ # 2. INSTALAR DEPENDÊNCIAS DO SISTEMA
7
+ ENV DEBIAN_FRONTEND=noninteractive
8
+ RUN apt-get update && apt-get install -y --no-install-recommends \
9
+ wget \
10
+ git \
11
+ && apt-get clean \
12
+ && rm -rf /var/lib/apt/lists/*
13
+
14
+ # 3. INSTALAR O MINICONDA
15
+ RUN wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh && \
16
+ /bin/bash ~/miniconda.sh -b -p /opt/conda && \
17
+ rm ~/miniconda.sh
18
+
19
+ # 4. ADICIONAR CONDA AO PATH
20
+ ENV PATH /opt/conda/bin:$PATH
21
+
22
+ # 5. COPIAR TODOS OS ARQUIVOS DO REPOSITÓRIO
23
+ COPY . /app
24
+ WORKDIR /app
25
+
26
+ # 6. ACEITAR OS TERMOS DE SERVIÇO
27
+ RUN yes | conda tos accept
28
+
29
+ # 7. ATUALIZAR O CONDA
30
+ RUN conda update -n base -c defaults conda
31
+
32
+ # 8. CRIAR O AMBIENTE CONDA
33
+ RUN conda env create -f environment.yml && conda clean --all -y
34
+
35
+ # 9. INSTALAR FLASH_ATTN SEM COMPILAR CUDA (PARA EVITAR ERRO DE MEMÓRIA)
36
+ RUN conda run -n seedvr env FLASH_ATTENTION_SKIP_CUDA_BUILD=TRUE \
37
+ pip install "flash_attn==2.5.9.post1" --no-build-isolation --no-cache-dir
38
+
39
+ # 10. BAIXAR O MODELO
40
+ WORKDIR /app/SeedVR
41
+ RUN huggingface-cli download ByteDance-Seed/SeedVR2-3B --local-dir ckpts --local-dir-use-symlinks False
42
+
43
+ # 11. DEFINIR O COMANDO FINAL PARA INICIAR A API
44
+ WORKDIR /app
45
+ CMD ["conda", "run", "-n", "seedvr", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -1,13 +1,18 @@
1
  ---
2
- title: SeedVR2-3B
3
  emoji: 🎥
4
  colorFrom: blue
5
  colorTo: green
6
- sdk: gradio
7
- sdk_version: 5.29.0
8
  app_file: app.py
9
- pinned: false
10
- license: apache-2.0
11
- short_description: SeedVR2-3B Image & Video API Demo
12
  ---
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: SeedVR2 Inference
3
  emoji: 🎥
4
  colorFrom: blue
5
  colorTo: green
6
+ sdk: docker
7
+ sdk_version: 5.44.1
8
  app_file: app.py
 
 
 
9
  ---
10
+
11
+ ## Instruções de Uso:
12
+
13
+ 1. **Faça o upload de um vídeo:** Use a caixa de upload para enviar seu arquivo de vídeo de entrada.
14
+ 2. **Ajuste os parâmetros:** Configure o `seed`, dimensões de saída e `sp_size` conforme necessário.
15
+ 3. **Clique em "Gerar Vídeo":** O processo de inferência será iniciado. Você pode acompanhar o progresso em tempo real na caixa de logs.
16
+ 4. **Visualize o resultado:** O vídeo gerado aparecerá na galeria de saída quando o processo for concluído.
17
+
18
+ **Nota Importante:** A primeira inicialização deste Space pode demorar vários minutos, pois ele precisa baixar o modelo de 3GB e instalar todas as dependências.
environment.yml ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Nome do ambiente Conda que será criado
2
+ name: seedvr
3
+
4
+ # Canais de onde o Conda irá baixar os pacotes, em ordem de prioridade.
5
+ # pytorch e nvidia são essenciais para obter as versões corretas com suporte a GPU.
6
+ channels:
7
+ - pytorch
8
+ - nvidia
9
+ - defaults
10
+
11
+ # Lista de todas as dependências
12
+ dependencies:
13
+ # Pacotes principais instalados via Conda para máxima compatibilidade com a GPU
14
+ - python
15
+ - pytorch
16
+ - torchvision
17
+ - torchaudio
18
+ - pytorch-cuda # Garante que o PyTorch seja compatível com a CUDA da imagem Docker
19
+ - pip # Instala o gerenciador de pacotes pip dentro do ambiente
20
+
21
+ # Pacotes instalados via Pip
22
+ - pip:
23
+ # Dependências da API FastAPI
24
+ - fastapi
25
+ - uvicorn
26
+ - python-multipart
27
+
28
+ # Dependências do projeto SeedVR
29
+ - accelerate
30
+ - av
31
+ - beautifulsoup4
32
+ - controlnet_aux
33
+ - diffusers
34
+ - einops
35
+ - ftfy
36
+ - huggingface_hub
37
+ - iopath
38
+ - mediapy
39
+ - omegaconf
40
+ - opencv-python
41
+ - pandas
42
+ - pytorch-lightning
43
+ - pytorchvideo
44
+ - regex
45
+ - scikit-image
46
+ - timm
47
+ - tqdm
48
+ - transformers
49
+ - webdataset
50
+ - xformers
51
+
52
+ # NOTA IMPORTANTE:
53
+ # 'flash_attn' não está listado aqui de propósito.
54
+ # Sua instalação requer flags especiais para evitar erros de memória durante a construção.
55
+ # Por isso, ele é instalado separadamente com um comando RUN dedicado no Dockerfile. # A linha do flash_attn foi REMOVIDA daqui
main.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # main.py (API com FastAPI)
2
+
3
+ import os
4
+ import uuid
5
+ import shutil
6
+ import subprocess
7
+ from fastapi import FastAPI, UploadFile, File, Form, HTTPException
8
+ from fastapi.responses import FileResponse
9
+ from fastapi.concurrency import run_in_threadpool
10
+
11
+ # Diretório base onde o código do SeedVR está
12
+ SEEDVR_DIR = "/app/SeedVR"
13
+
14
+ app = FastAPI()
15
+
16
+ def run_inference_blocking(input_video_path: str, output_dir: str, seed: int, res_h: int, res_w: int) -> str:
17
+ """
18
+ Função síncrona que executa o script torchrun.
19
+ Ela bloqueia a execução, por isso deve ser chamada em um thread separado.
20
+ """
21
+ # O script de inferência espera ser executado de dentro do diretório SeedVR
22
+ # e que os caminhos de entrada/saída sejam relativos a ele.
23
+
24
+ # Constrói o caminho relativo para a pasta de entrada
25
+ input_folder_relative = os.path.relpath(os.path.dirname(input_video_path), SEEDVR_DIR)
26
+
27
+ # Constrói o caminho relativo para a pasta de saída
28
+ output_folder_relative = os.path.relpath(output_dir, SEEDVR_DIR)
29
+
30
+ command = [
31
+ "torchrun",
32
+ "--nproc-per-node=4",
33
+ "projects/inference_seedvr2_3b.py",
34
+ "--video_path", input_folder_relative,
35
+ "--output_dir", output_folder_relative,
36
+ "--seed", str(seed),
37
+ "--res_h", str(res_h),
38
+ "--res_w", str(res_w),
39
+ "--sp_size", "1", # Mantido fixo ou pode se tornar um parâmetro
40
+ ]
41
+
42
+ try:
43
+ print(f"Executando comando: {' '.join(command)}")
44
+ # Executa o subprocesso a partir do diretório do SeedVR
45
+ subprocess.run(command, cwd=SEEDVR_DIR, check=True, capture_output=True, text=True)
46
+ except subprocess.CalledProcessError as e:
47
+ # Se o script falhar, captura o erro e o log para depuração
48
+ print("Erro na execução do subprocesso!")
49
+ print(f"Stdout: {e.stdout}")
50
+ print(f"Stderr: {e.stderr}")
51
+ raise HTTPException(status_code=500, detail=f"A inferência falhou: {e.stderr}")
52
+
53
+ # Encontra o arquivo de saída gerado
54
+ output_files = [f for f in os.listdir(output_dir) if f.endswith(('.mp4', '.png'))]
55
+ if not output_files:
56
+ raise HTTPException(status_code=500, detail="A inferência foi concluída, mas nenhum arquivo de saída foi encontrado.")
57
+
58
+ return os.path.join(output_dir, output_files[0])
59
+
60
+
61
+ @app.get("/")
62
+ async def root():
63
+ return {"message": "API de Inferência SeedVR2 está online. Use o endpoint /infer/ para processar vídeos."}
64
+
65
+
66
+ @app.post("/infer/", response_class=FileResponse)
67
+ async def create_inference_job(
68
+ video: UploadFile = File(...),
69
+ seed: int = Form(666),
70
+ res_h: int = Form(720),
71
+ res_w: int = Form(1280),
72
+ ):
73
+ """
74
+ Recebe um vídeo e parâmetros, executa a inferência e retorna o vídeo processado.
75
+ """
76
+ # Cria diretórios temporários únicos para esta requisição para evitar conflitos
77
+ job_id = str(uuid.uuid4())
78
+ input_dir = os.path.join("/app", "temp_inputs", job_id)
79
+ output_dir = os.path.join("/app", "temp_outputs", job_id)
80
+ os.makedirs(input_dir, exist_ok=True)
81
+ os.makedirs(output_dir, exist_ok=True)
82
+
83
+ input_video_path = os.path.join(input_dir, video.filename)
84
+
85
+ try:
86
+ # Salva o vídeo enviado para o disco
87
+ with open(input_video_path, "wb") as buffer:
88
+ shutil.copyfileobj(video.file, buffer)
89
+
90
+ # Executa a função de inferência pesada em um thread separado
91
+ # para não bloquear o servidor da API
92
+ result_path = await run_in_threadpool(
93
+ run_inference_blocking,
94
+ input_video_path=input_video_path,
95
+ output_dir=output_dir,
96
+ seed=seed,
97
+ res_h=res_h,
98
+ res_w=res_w
99
+ )
100
+
101
+ # Retorna o arquivo de vídeo como uma resposta para download
102
+ return FileResponse(path=result_path, media_type='video/mp4', filename=os.path.basename(result_path))
103
+
104
+ finally:
105
+ # Limpa os diretórios temporários após a conclusão ou falha
106
+ print("Limpando diretórios temporários...")
107
+ shutil.rmtree(input_dir, ignore_errors=True)
108
+ shutil.rmtree(output_dir, ignore_errors=True)