Spaces:
Running
Running
File size: 7,266 Bytes
80b326d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
from scripts import cut_json
import os
import subprocess
import json
def cut(segments, project_folder="tmp", skip_video=False):
def check_nvenc_support():
# ... (unchanged)
try:
result = subprocess.run(["ffmpeg", "-encoders"], capture_output=True, text=True)
return "h264_nvenc" in result.stdout
except subprocess.CalledProcessError:
return False
def generate_segments(response, project_folder, skip_video):
if not check_nvenc_support():
print("NVENC is not supported on this system. Falling back to libx264.")
video_codec = "libx264"
else:
video_codec = "h264_nvenc"
# Procurar input_video.mp4 no project_folder ou tmp
input_file = os.path.join(project_folder, "input.mp4")
if not os.path.exists(input_file):
# Tenta fallback legado
input_file_legacy = os.path.join(project_folder, "input_video.mp4")
if os.path.exists(input_file_legacy):
input_file = input_file_legacy
else:
print(f"Input file not found in {project_folder}")
return
# Pasta de saida para os cortes
cuts_folder = os.path.join(project_folder, "cuts")
os.makedirs(cuts_folder, exist_ok=True)
# Pasta de saida para legendas json cortadas
subs_folder = os.path.join(project_folder, "subs")
os.makedirs(subs_folder, exist_ok=True)
# Input JSON (Transkription original)
input_json_path = os.path.join(project_folder, "input.json")
segments = response.get("segments", [])
for i, segment in enumerate(segments):
start_time = segment.get("start_time", "00:00:00")
duration = segment.get("duration", 0)
# Heurística para duration:
if isinstance(duration, (int, float)):
if duration < 1000:
duration_seconds = float(duration)
else:
duration_seconds = duration / 1000.0
duration_str = f"{duration_seconds:.3f}"
else:
# Tenta converter string (HH:MM:SS ou float str)
try:
duration_seconds = float(duration)
duration_str = f"{duration_seconds:.3f}"
except ValueError:
# Assumindo formato hh:mm:ss se nao for float
# Implementar parser se necessario, mas assumindo float por enquanto baseado no historico
duration_seconds = 0
duration_str = duration
# Heurística para start_time:
if isinstance(start_time, (int, float)):
if start_time > 10000: # Se for milisegundos grandes? Assumindo segundos ou HHMMSS?
# O código original: if start_time int -> start_time/1000.0.
# Vamos manter a lógica original: int -> milisegundos
pass
# Refazendo a logica original exata para seguranca e capturando o float:
if isinstance(start_time, int):
start_time_seconds = start_time / 1000.0
start_time_str = f"{start_time_seconds:.3f}"
elif isinstance(start_time, float):
start_time_seconds = start_time
start_time_str = f"{start_time_seconds:.3f}"
else:
# String "00:00:00" ou "12.34"
try:
start_time_seconds = float(start_time)
start_time_str = f"{start_time_seconds:.3f}"
except:
# Se for HH:MM:SS, ffmpeg aceita, mas precisamos converter para float para o json cutter
# Função auxiliar simples
h, m, s = str(start_time).split(':')
start_time_seconds = int(h) * 3600 + int(m) * 60 + float(s)
start_time_str = str(start_time)
# Título para nome de arquivo
title = segment.get("title", f"Segment_{i}")
safe_title = "".join([c for c in title if c.isalnum() or c in " _-"]).strip()
safe_title = safe_title.replace(" ", "_")[:60]
base_name = f"{i:03d}_{safe_title}"
output_filename = f"{base_name}_original_scale.mp4"
output_path = os.path.join(cuts_folder, output_filename)
print(f"Processing segment {i+1}/{len(segments)}")
print(f"Start time: {start_time}, Duration: {duration}")
# print(f"Executing command: {' '.join(command)}")
# VIDEO GENERATION
if not skip_video:
# Comando ffmpeg
command = [
"ffmpeg",
"-y",
"-loglevel", "error", "-hide_banner",
"-ss", start_time_str,
"-i", input_file,
"-t", duration_str,
"-c:v", video_codec
]
if video_codec == "h264_nvenc":
command.extend([
"-preset", "p1",
"-b:v", "5M",
])
else:
command.extend([
"-preset", "ultrafast",
"-crf", "23"
])
command.extend([
"-c:a", "aac",
"-b:a", "128k",
output_path
])
try:
subprocess.run(command, check=True, capture_output=True, text=True)
if os.path.exists(output_path):
file_size = os.path.getsize(output_path)
print(f"Generated segment: {output_filename}, Size: {file_size} bytes")
except subprocess.CalledProcessError as e:
print(f"Error executing ffmpeg: {e}")
else:
print(f"Skipping video generation for {output_filename} (using existing). check json...")
# --- JSON CUTTING (ALWAYS RUN) ---
end_time_seconds = start_time_seconds + float(duration_seconds)
# Nome do json correspondente ao vídeo FINAL com titulo
json_output_filename = f"{base_name}_processed.json"
json_output_path = os.path.join(subs_folder, json_output_filename)
cut_json.cut_json_transcript(input_json_path, json_output_path, start_time_seconds, end_time_seconds)
# --------------------
print("\n" + "="*50 + "\n")
# Reading the JSON file if segments not provided (legacy behavior)
if segments is None:
json_path = os.path.join(project_folder, 'viral_segments.txt')
with open(json_path, 'r', encoding='utf-8') as file:
response = json.load(file)
else:
response = segments
generate_segments(response, project_folder, skip_video)
|