Offex commited on
Commit
c766d00
·
verified ·
1 Parent(s): 5cedc27

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -71
app.py CHANGED
@@ -1,119 +1,120 @@
1
  import gradio as gr
2
- import os
3
- import uuid
4
- import re
5
  from pydub import AudioSegment, silence
6
 
7
- # -------------------------------------------------
8
- # Clean filename
9
- # -------------------------------------------------
10
- def clean_file_name(file_path):
11
- base = os.path.basename(file_path)
12
- name, ext = os.path.splitext(base)
13
 
14
- name = re.sub(r'[^a-zA-Z0-9]+', '_', name)
15
- name = re.sub(r'_+', '_', name).strip('_')
 
 
 
 
16
 
17
- uid = uuid.uuid4().hex[:6]
18
- return os.path.join(os.path.dirname(file_path), f"{name}_{uid}{ext}")
19
 
20
- # -------------------------------------------------
21
- # SAFE Silence Removal (NO WORD LOSS)
22
- # -------------------------------------------------
23
- def remove_silence_safe(file_path, keep_silence_ms=250):
24
- audio = AudioSegment.from_file(file_path)
25
 
26
- # mono for speed, safe for voice
27
- audio = audio.set_channels(1)
 
 
 
28
 
29
- # 🔐 conservative threshold (speech friendly)
30
  silence_thresh = audio.dBFS - 22
31
 
32
  chunks = silence.split_on_silence(
33
  audio,
34
- min_silence_len=350, # ignore natural speech pauses
35
  silence_thresh=silence_thresh,
36
- keep_silence=keep_silence_ms
37
  )
38
 
39
  if not chunks:
40
- return file_path
41
-
42
- output = AudioSegment.empty()
43
 
44
- for chunk in chunks:
45
- # soften edges so words never cut
46
- chunk = chunk.fade_in(20).fade_out(20)
47
- output += chunk
48
 
49
- output_path = clean_file_name(file_path)
50
- output.export(output_path)
51
- return output_path
 
 
 
52
 
53
- # -------------------------------------------------
54
- # Duration helper
55
- # -------------------------------------------------
56
  def duration(path):
57
- audio = AudioSegment.from_file(path)
58
- return len(audio) / 1000
59
 
60
- # -------------------------------------------------
61
- # Main processing
62
- # -------------------------------------------------
63
  def process_audio(audio_file, keep_seconds):
64
  keep_ms = int(max(keep_seconds, 0.25) * 1000)
65
 
66
- before = duration(audio_file)
67
- output = remove_silence_safe(audio_file, keep_ms)
68
- after = duration(output)
 
 
 
 
 
 
69
 
70
  info = (
71
- f"Old Duration : {before:.2f} sec\n"
72
- f"New Duration : {after:.2f} sec\n"
73
- f"Silence Removed : {before - after:.2f} sec"
74
  )
75
 
76
- return output, output, info
77
 
78
- # -------------------------------------------------
79
- # UI (Hugging Face SAFE)
80
- # -------------------------------------------------
81
- with gr.Blocks(title="Safe Silence Remover") as demo:
82
  gr.Markdown(
83
- """
84
- ## 🔇 Safe Silence Remover
85
- ✔ Removes **only silence**
86
- ✔ Words & voice **100% preserved**
87
- """
88
  )
89
 
90
  with gr.Row():
91
  with gr.Column():
92
- audio_input = gr.Audio(
93
- label="Upload Audio",
94
  type="filepath",
95
- sources=["upload", "microphone"]
 
96
  )
97
 
98
- keep_silence = gr.Number(
99
- label="Keep Silence (seconds)",
100
- value=0.25
101
  )
102
 
103
  btn = gr.Button("Remove Silence")
104
 
105
  with gr.Column():
106
- audio_out = gr.Audio(label="Processed Audio")
107
- file_out = gr.File(label="Download")
108
- info_out = gr.Textbox(label="Info")
109
 
110
  btn.click(
111
  process_audio,
112
- [audio_input, keep_silence],
113
- [audio_out, file_out, info_out]
114
  )
115
 
116
- # -------------------------------------------------
117
- # Hugging Face Entry Point
118
- # -------------------------------------------------
119
  demo.queue().launch()
 
1
  import gradio as gr
2
+ import os, uuid, re, tempfile
 
 
3
  from pydub import AudioSegment, silence
4
 
5
+ # ----------------------------------
6
+ # Utils
7
+ # ----------------------------------
8
+ def clean_name(path, ext):
9
+ name = re.sub(r'[^a-zA-Z0-9]+', '_', os.path.basename(path))
10
+ return f"{name}_{uuid.uuid4().hex[:6]}.{ext}"
11
 
12
+ # ----------------------------------
13
+ # Convert to WAV (FAST PROCESSING)
14
+ # ----------------------------------
15
+ def ensure_wav(path):
16
+ if path.lower().endswith(".wav"):
17
+ return path
18
 
19
+ audio = AudioSegment.from_file(path)
20
+ audio = audio.set_channels(1)
21
 
22
+ tmp = tempfile.gettempdir()
23
+ wav_path = os.path.join(tmp, clean_name(path, "wav"))
24
+ audio.export(wav_path, format="wav")
25
+ return wav_path
 
26
 
27
+ # ----------------------------------
28
+ # SAFE Silence Removal
29
+ # ----------------------------------
30
+ def remove_silence_safe(path, keep_ms=250):
31
+ audio = AudioSegment.from_wav(path)
32
 
 
33
  silence_thresh = audio.dBFS - 22
34
 
35
  chunks = silence.split_on_silence(
36
  audio,
37
+ min_silence_len=350,
38
  silence_thresh=silence_thresh,
39
+ keep_silence=keep_ms
40
  )
41
 
42
  if not chunks:
43
+ return path
 
 
44
 
45
+ out = AudioSegment.empty()
46
+ for c in chunks:
47
+ out += c.fade_in(20).fade_out(20)
 
48
 
49
+ out_path = os.path.join(
50
+ tempfile.gettempdir(),
51
+ clean_name(path, "wav")
52
+ )
53
+ out.export(out_path, format="wav")
54
+ return out_path
55
 
56
+ # ----------------------------------
57
+ # Duration
58
+ # ----------------------------------
59
  def duration(path):
60
+ return len(AudioSegment.from_wav(path)) / 1000
 
61
 
62
+ # ----------------------------------
63
+ # Main
64
+ # ----------------------------------
65
  def process_audio(audio_file, keep_seconds):
66
  keep_ms = int(max(keep_seconds, 0.25) * 1000)
67
 
68
+ wav = ensure_wav(audio_file)
69
+ before = duration(wav)
70
+
71
+ cleaned = remove_silence_safe(wav, keep_ms)
72
+ after = duration(cleaned)
73
+
74
+ # Export final MP3 (user friendly)
75
+ final_mp3 = cleaned.replace(".wav", ".mp3")
76
+ AudioSegment.from_wav(cleaned).export(final_mp3, format="mp3")
77
 
78
  info = (
79
+ f"Old Duration : {before:.2f}s\n"
80
+ f"New Duration : {after:.2f}s\n"
81
+ f"Silence Removed : {before - after:.2f}s"
82
  )
83
 
84
+ return final_mp3, final_mp3, info
85
 
86
+ # ----------------------------------
87
+ # UI
88
+ # ----------------------------------
89
+ with gr.Blocks(title="Fast Silence Remover") as demo:
90
  gr.Markdown(
91
+ "## ⚡ Fast MP3/WAV Silence Remover (No Word Loss)"
 
 
 
 
92
  )
93
 
94
  with gr.Row():
95
  with gr.Column():
96
+ audio = gr.Audio(
 
97
  type="filepath",
98
+ sources=["upload"],
99
+ label="Upload MP3 or WAV"
100
  )
101
 
102
+ keep = gr.Number(
103
+ value=0.25,
104
+ label="Keep Silence (seconds)"
105
  )
106
 
107
  btn = gr.Button("Remove Silence")
108
 
109
  with gr.Column():
110
+ out_audio = gr.Audio(label="Processed Audio")
111
+ out_file = gr.File(label="Download")
112
+ info = gr.Textbox(label="Info")
113
 
114
  btn.click(
115
  process_audio,
116
+ [audio, keep],
117
+ [out_audio, out_file, info]
118
  )
119
 
 
 
 
120
  demo.queue().launch()