DHEIVER commited on
Commit
12d32cd
·
verified ·
1 Parent(s): 1f4e0e1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -63
app.py CHANGED
@@ -43,13 +43,11 @@ def process_video_chunk(args):
43
 
44
  def concatenate_videos_ffmpeg(video_list, output_path):
45
  """Concatena vídeos usando FFmpeg"""
46
- # Cria arquivo de lista
47
  list_file = tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt')
48
  for video in video_list:
49
  list_file.write(f"file '{video}'\n")
50
  list_file.close()
51
 
52
- # Concatena usando FFmpeg
53
  command = [
54
  'ffmpeg', '-f', 'concat',
55
  '-safe', '0',
@@ -62,21 +60,16 @@ def concatenate_videos_ffmpeg(video_list, output_path):
62
  os.unlink(list_file.name)
63
 
64
  def process_video(video_path, min_silence_len=1000, silence_thresh=-40, max_workers=4):
65
- """
66
- Remove segmentos silenciosos do vídeo com processamento otimizado.
67
- """
68
  if not os.path.exists(video_path):
69
  raise ValueError("Arquivo de vídeo não encontrado")
70
 
71
- # Criar diretório temporário
72
  temp_dir = tempfile.mkdtemp()
73
 
74
  try:
75
- # Extrair áudio
76
  temp_audio = os.path.join(temp_dir, "temp_audio.wav")
77
  extract_audio_ffmpeg(video_path, temp_audio)
78
 
79
- # Detectar segmentos não silenciosos
80
  audio = AudioSegment.from_wav(temp_audio)
81
  nonsilent_ranges = detect_nonsilent(
82
  audio,
@@ -87,10 +80,8 @@ def process_video(video_path, min_silence_len=1000, silence_thresh=-40, max_work
87
  if not nonsilent_ranges:
88
  return video_path
89
 
90
- # Converter para segundos
91
  nonsilent_ranges_sec = [(start/1000.0, end/1000.0) for start, end in nonsilent_ranges]
92
 
93
- # Preparar argumentos para processamento paralelo
94
  chunk_args = []
95
  chunk_outputs = []
96
  for i, (start, end) in enumerate(nonsilent_ranges_sec):
@@ -98,15 +89,12 @@ def process_video(video_path, min_silence_len=1000, silence_thresh=-40, max_work
98
  chunk_args.append((video_path, output_chunk, start, end))
99
  chunk_outputs.append(output_chunk)
100
 
101
- # Processar chunks em paralelo
102
  with ThreadPoolExecutor(max_workers=max_workers) as executor:
103
  list(executor.map(process_video_chunk, chunk_args))
104
 
105
- # Concatenar todos os chunks
106
  output_path = os.path.join(temp_dir, "processed_video.mp4")
107
  concatenate_videos_ffmpeg(chunk_outputs, output_path)
108
 
109
- # Criar cópia do resultado em local permanente
110
  final_output = str(Path(video_path).parent / f"processed_{Path(video_path).name}")
111
  shutil.copy2(output_path, final_output)
112
 
@@ -115,95 +103,96 @@ def process_video(video_path, min_silence_len=1000, silence_thresh=-40, max_work
115
  except Exception as e:
116
  raise Exception(f"Erro ao processar vídeo: {str(e)}")
117
  finally:
118
- # Limpar arquivos temporários
119
  shutil.rmtree(temp_dir)
120
 
121
  def remove_silence(video_input, silence_duration, silence_threshold):
122
- """
123
- Função principal que processa o vídeo e retorna o caminho do vídeo processado
124
- """
125
  try:
126
  if video_input is None:
127
  raise ValueError("Por favor, faça upload de um vídeo")
128
 
129
- # Processar o vídeo
130
  processed_video = process_video(
131
  video_input,
132
  min_silence_len=int(silence_duration * 1000),
133
  silence_thresh=silence_threshold
134
  )
135
 
136
- # Retornar tanto o vídeo original quanto o processado
137
- return {
138
- video_output: processed_video,
139
- video_input_display: video_input
140
- }
 
 
 
 
 
 
 
 
 
 
 
 
141
 
 
142
  except Exception as e:
143
  gr.Error(str(e))
144
  return None
145
 
146
- # Interface Gradio com indicador de progresso
147
  with gr.Blocks(title="Removedor de Silêncio de Vídeos") as app:
148
  gr.Markdown("# Removedor de Silêncio de Vídeos")
149
- gr.Markdown("""
150
- ### Otimizado para processamento rápido
151
- Faça upload de um vídeo e ajuste os parâmetros para remover segmentos silenciosos.
152
- O processamento é feito em paralelo para maior velocidade.
153
- """)
154
 
155
  with gr.Row():
156
  with gr.Column():
157
- # Input components
158
  video_input = gr.Video(
159
  label="Selecione ou Arraste o Vídeo",
160
- format="mp4",
161
- interactive=True
162
- )
163
- silence_duration = gr.Slider(
164
- minimum=0.1,
165
- maximum=5.0,
166
- value=1.0,
167
- step=0.1,
168
- label="Duração Mínima do Silêncio (segundos)"
169
- )
170
- silence_threshold = gr.Slider(
171
- minimum=-60,
172
- maximum=-20,
173
- value=-40,
174
- step=1,
175
- label="Limite de Silêncio (dB)"
176
  )
177
- process_btn = gr.Button("Processar Vídeo")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
 
179
  with gr.Row():
180
- with gr.Column():
181
- # Display do vídeo original
182
- gr.Markdown("### Vídeo Original")
183
- video_input_display = gr.Video(label="Vídeo Original")
184
- with gr.Column():
185
- # Display do vídeo processado
186
- gr.Markdown("### Vídeo Processado (Sem Silêncio)")
187
- video_output = gr.Video(label="Vídeo Processado")
188
 
189
  # Event handlers
190
- video_input.change(
191
- fn=lambda x: x,
192
  inputs=[video_input],
193
- outputs=[video_input_display]
194
  )
195
 
196
- process_btn.click(
197
  fn=remove_silence,
198
  inputs=[
199
  video_input,
200
  silence_duration,
201
  silence_threshold
202
  ],
203
- outputs=[
204
- video_output,
205
- video_input_display
206
- ]
207
  )
208
 
209
  if __name__ == "__main__":
 
43
 
44
  def concatenate_videos_ffmpeg(video_list, output_path):
45
  """Concatena vídeos usando FFmpeg"""
 
46
  list_file = tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt')
47
  for video in video_list:
48
  list_file.write(f"file '{video}'\n")
49
  list_file.close()
50
 
 
51
  command = [
52
  'ffmpeg', '-f', 'concat',
53
  '-safe', '0',
 
60
  os.unlink(list_file.name)
61
 
62
  def process_video(video_path, min_silence_len=1000, silence_thresh=-40, max_workers=4):
63
+ """Remove segmentos silenciosos do vídeo com processamento otimizado."""
 
 
64
  if not os.path.exists(video_path):
65
  raise ValueError("Arquivo de vídeo não encontrado")
66
 
 
67
  temp_dir = tempfile.mkdtemp()
68
 
69
  try:
 
70
  temp_audio = os.path.join(temp_dir, "temp_audio.wav")
71
  extract_audio_ffmpeg(video_path, temp_audio)
72
 
 
73
  audio = AudioSegment.from_wav(temp_audio)
74
  nonsilent_ranges = detect_nonsilent(
75
  audio,
 
80
  if not nonsilent_ranges:
81
  return video_path
82
 
 
83
  nonsilent_ranges_sec = [(start/1000.0, end/1000.0) for start, end in nonsilent_ranges]
84
 
 
85
  chunk_args = []
86
  chunk_outputs = []
87
  for i, (start, end) in enumerate(nonsilent_ranges_sec):
 
89
  chunk_args.append((video_path, output_chunk, start, end))
90
  chunk_outputs.append(output_chunk)
91
 
 
92
  with ThreadPoolExecutor(max_workers=max_workers) as executor:
93
  list(executor.map(process_video_chunk, chunk_args))
94
 
 
95
  output_path = os.path.join(temp_dir, "processed_video.mp4")
96
  concatenate_videos_ffmpeg(chunk_outputs, output_path)
97
 
 
98
  final_output = str(Path(video_path).parent / f"processed_{Path(video_path).name}")
99
  shutil.copy2(output_path, final_output)
100
 
 
103
  except Exception as e:
104
  raise Exception(f"Erro ao processar vídeo: {str(e)}")
105
  finally:
 
106
  shutil.rmtree(temp_dir)
107
 
108
  def remove_silence(video_input, silence_duration, silence_threshold):
109
+ """Função para remoção normal de silêncio"""
 
 
110
  try:
111
  if video_input is None:
112
  raise ValueError("Por favor, faça upload de um vídeo")
113
 
 
114
  processed_video = process_video(
115
  video_input,
116
  min_silence_len=int(silence_duration * 1000),
117
  silence_thresh=silence_threshold
118
  )
119
 
120
+ return processed_video
121
+ except Exception as e:
122
+ gr.Error(str(e))
123
+ return None
124
+
125
+ def remove_max_silence(video_input):
126
+ """Função para remoção máxima de silêncio"""
127
+ try:
128
+ if video_input is None:
129
+ raise ValueError("Por favor, faça upload de um vídeo")
130
+
131
+ # Configurações mais agressivas para detectar todo silêncio
132
+ processed_video = process_video(
133
+ video_input,
134
+ min_silence_len=100, # Detecta silêncios de 0.1 segundos
135
+ silence_thresh=-30 # Limite mais alto para detectar mais silêncio
136
+ )
137
 
138
+ return processed_video
139
  except Exception as e:
140
  gr.Error(str(e))
141
  return None
142
 
143
+ # Interface Gradio
144
  with gr.Blocks(title="Removedor de Silêncio de Vídeos") as app:
145
  gr.Markdown("# Removedor de Silêncio de Vídeos")
 
 
 
 
 
146
 
147
  with gr.Row():
148
  with gr.Column():
 
149
  video_input = gr.Video(
150
  label="Selecione ou Arraste o Vídeo",
151
+ format="mp4"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  )
153
+
154
+ with gr.Row():
155
+ # Botão para remoção máxima de silêncio
156
+ remove_max_btn = gr.Button("🔇 Remover 100% do Silêncio", variant="primary")
157
+
158
+ # Botão para remoção personalizada
159
+ remove_custom_btn = gr.Button("Remover Silêncio Personalizado")
160
+
161
+ with gr.Group():
162
+ gr.Markdown("### Configurações Personalizadas")
163
+ silence_duration = gr.Slider(
164
+ minimum=0.1,
165
+ maximum=5.0,
166
+ value=1.0,
167
+ step=0.1,
168
+ label="Duração Mínima do Silêncio (segundos)"
169
+ )
170
+ silence_threshold = gr.Slider(
171
+ minimum=-60,
172
+ maximum=-20,
173
+ value=-40,
174
+ step=1,
175
+ label="Limite de Silêncio (dB)"
176
+ )
177
 
178
  with gr.Row():
179
+ video_output = gr.Video(label="Vídeo Processado")
 
 
 
 
 
 
 
180
 
181
  # Event handlers
182
+ remove_max_btn.click(
183
+ fn=remove_max_silence,
184
  inputs=[video_input],
185
+ outputs=[video_output]
186
  )
187
 
188
+ remove_custom_btn.click(
189
  fn=remove_silence,
190
  inputs=[
191
  video_input,
192
  silence_duration,
193
  silence_threshold
194
  ],
195
+ outputs=[video_output]
 
 
 
196
  )
197
 
198
  if __name__ == "__main__":