DHEIVER commited on
Commit
25ef972
·
verified ·
1 Parent(s): f170576

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +89 -47
app.py CHANGED
@@ -1,70 +1,112 @@
1
  import gradio as gr
2
- from moviepy.editor import VideoFileClip, concatenate_videoclips
3
- from pydub import AudioSegment
4
- from pydub.silence import detect_nonsilent
5
  import numpy as np
 
 
6
  import tempfile
7
  import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
  def process_video(video_path, min_silence_length=1000, silence_threshold=-40):
10
- """
11
- Process video to remove silent parts
12
- Parameters:
13
- - video_path: path to input video
14
- - min_silence_length: minimum length of silence to detect (in ms)
15
- - silence_threshold: volume threshold to consider as silence (in dB)
16
- """
17
- # Create temporary directory for processing
18
  temp_dir = tempfile.mkdtemp()
19
 
20
  try:
21
- # Load video
22
- video = VideoFileClip(video_path)
23
 
24
- # Extract audio and save temporarily
25
- temp_audio_path = os.path.join(temp_dir, "temp_audio.wav")
26
- video.audio.write_audiofile(temp_audio_path, codec='pcm_s16le')
27
 
28
- # Load audio with pydub
29
- audio = AudioSegment.from_wav(temp_audio_path)
30
 
31
- # Detect non-silent parts
32
- nonsilent_ranges = detect_nonsilent(
33
- audio,
34
- min_silence_len=min_silence_length,
35
- silence_thresh=silence_threshold
36
- )
37
-
38
- if not nonsilent_ranges:
39
- return None, "No non-silent parts detected in the video."
40
 
41
- # Convert timestamps to seconds
42
- nonsilent_ranges_sec = [(start/1000, end/1000) for start, end in nonsilent_ranges]
 
 
43
 
44
- # Cut video based on non-silent parts
45
- clips = []
46
- for start, end in nonsilent_ranges_sec:
47
- clip = video.subclip(start, end)
48
- clips.append(clip)
 
 
 
 
 
 
49
 
50
- # Concatenate all non-silent clips
51
- final_clip = concatenate_videoclips(clips)
52
 
53
- # Save the result
54
- output_path = os.path.join(temp_dir, "output_video.mp4")
55
- final_clip.write_videofile(output_path, codec='libx264')
 
 
 
 
56
 
57
- # Clean up
58
- video.close()
59
- final_clip.close()
60
-
61
- return output_path, "Video processed successfully!"
62
 
63
  except Exception as e:
64
- return None, f"Error processing video: {str(e)}"
65
-
66
  finally:
67
- # Clean up temporary files
68
  for file in os.listdir(temp_dir):
69
  try:
70
  os.remove(os.path.join(temp_dir, file))
 
1
  import gradio as gr
2
+ import cv2
 
 
3
  import numpy as np
4
+ import soundfile as sf
5
+ from scipy.io import wavfile
6
  import tempfile
7
  import os
8
+ import subprocess
9
+
10
+ def extract_audio(video_path):
11
+ """Extrai áudio do vídeo usando ffmpeg"""
12
+ temp_audio = tempfile.mktemp('.wav')
13
+ command = [
14
+ 'ffmpeg', '-i', video_path,
15
+ '-ab', '160k', '-ac', '2', '-ar', '44100', '-vn', temp_audio
16
+ ]
17
+ subprocess.call(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
18
+ return temp_audio
19
+
20
+ def detect_silence(audio_path, min_silence_length=1000, silence_threshold=-40):
21
+ """Detecta períodos de silêncio no áudio"""
22
+ # Lê o arquivo de áudio
23
+ sample_rate, audio_data = wavfile.read(audio_path)
24
+
25
+ # Converte para mono se estéreo
26
+ if len(audio_data.shape) > 1:
27
+ audio_data = audio_data.mean(axis=1)
28
+
29
+ # Calcula a energia do áudio em janelas
30
+ window_size = int(sample_rate * (min_silence_length/1000))
31
+ overlapping = int(window_size/2)
32
+
33
+ non_silent_ranges = []
34
+ start = None
35
+
36
+ for i in range(0, len(audio_data), overlapping):
37
+ window = audio_data[i:i+window_size]
38
+ if len(window) < window_size:
39
+ break
40
+
41
+ energy_db = 10 * np.log10(np.mean(window**2) + 1e-10)
42
+
43
+ if energy_db > silence_threshold:
44
+ if start is None:
45
+ start = i
46
+ elif start is not None:
47
+ non_silent_ranges.append((start/sample_rate, i/sample_rate))
48
+ start = None
49
+
50
+ if start is not None:
51
+ non_silent_ranges.append((start/sample_rate, len(audio_data)/sample_rate))
52
+
53
+ return non_silent_ranges
54
 
55
  def process_video(video_path, min_silence_length=1000, silence_threshold=-40):
56
+ """Processa o vídeo removendo partes silenciosas"""
 
 
 
 
 
 
 
57
  temp_dir = tempfile.mkdtemp()
58
 
59
  try:
60
+ # Extrai áudio
61
+ audio_path = extract_audio(video_path)
62
 
63
+ # Detecta ranges não silenciosos
64
+ non_silent_ranges = detect_silence(audio_path, min_silence_length, silence_threshold)
 
65
 
66
+ if not non_silent_ranges:
67
+ return None, "Nenhuma parte não-silenciosa detectada no vídeo."
68
 
69
+ # Abre o vídeo
70
+ cap = cv2.VideoCapture(video_path)
71
+ fps = cap.get(cv2.CAP_PROP_FPS)
72
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
73
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
 
 
 
 
74
 
75
+ # Prepara o arquivo de saída
76
+ output_path = os.path.join(temp_dir, "output_video.mp4")
77
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
78
+ out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
79
 
80
+ # Processa cada range não silencioso
81
+ for start_time, end_time in non_silent_ranges:
82
+ start_frame = int(start_time * fps)
83
+ end_frame = int(end_time * fps)
84
+
85
+ cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
86
+ for _ in range(end_frame - start_frame):
87
+ ret, frame = cap.read()
88
+ if not ret:
89
+ break
90
+ out.write(frame)
91
 
92
+ cap.release()
93
+ out.release()
94
 
95
+ # Adiciona áudio ao vídeo final
96
+ final_path = os.path.join(temp_dir, "final_output.mp4")
97
+ command = [
98
+ 'ffmpeg', '-i', output_path, '-i', audio_path,
99
+ '-c:v', 'copy', '-c:a', 'aac', final_path
100
+ ]
101
+ subprocess.call(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
102
 
103
+ return final_path, "Vídeo processado com sucesso!"
 
 
 
 
104
 
105
  except Exception as e:
106
+ return None, f"Erro ao processar vídeo: {str(e)}"
107
+
108
  finally:
109
+ # Limpa arquivos temporários
110
  for file in os.listdir(temp_dir):
111
  try:
112
  os.remove(os.path.join(temp_dir, file))