Offex commited on
Commit
3fb14a2
Β·
verified Β·
1 Parent(s): dcc09a9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -44
app.py CHANGED
@@ -4,9 +4,9 @@ import uuid
4
  import re
5
  from pydub import AudioSegment, silence
6
 
7
- # -----------------------------
8
- # Filename cleaner
9
- # -----------------------------
10
  def clean_file_name(file_path):
11
  base = os.path.basename(file_path)
12
  name, ext = os.path.splitext(base)
@@ -17,18 +17,21 @@ def clean_file_name(file_path):
17
  uid = uuid.uuid4().hex[:6]
18
  return os.path.join(os.path.dirname(file_path), f"{name}_{uid}{ext}")
19
 
20
- # -----------------------------
21
- # Fast silence removal
22
- # -----------------------------
23
- def remove_silence_fast(file_path, keep_silence_ms=50):
24
  audio = AudioSegment.from_file(file_path)
 
 
25
  audio = audio.set_channels(1)
26
 
27
- silence_thresh = audio.dBFS - 16
 
28
 
29
  chunks = silence.split_on_silence(
30
  audio,
31
- min_silence_len=120,
32
  silence_thresh=silence_thresh,
33
  keep_silence=keep_silence_ms
34
  )
@@ -36,60 +39,81 @@ def remove_silence_fast(file_path, keep_silence_ms=50):
36
  if not chunks:
37
  return file_path
38
 
39
- out = chunks[0]
40
- for c in chunks[1:]:
41
- out += c
 
 
 
42
 
43
- out_path = clean_file_name(file_path)
44
- out.export(out_path)
45
- return out_path
46
 
47
- # -----------------------------
48
- # Duration
49
- # -----------------------------
50
  def duration(path):
51
- return len(AudioSegment.from_file(path)) / 1000
 
52
 
53
- # -----------------------------
54
- # Main function
55
- # -----------------------------
56
- def process_audio(audio_file, seconds):
57
- keep_ms = int(seconds * 1000)
58
 
59
  before = duration(audio_file)
60
- output = remove_silence_fast(audio_file, keep_ms)
61
  after = duration(output)
62
 
63
- text = (
64
- f"Old Duration : {before:.2f}s\n"
65
- f"New Duration : {after:.2f}s\n"
66
- f"Saved : {before - after:.2f}s"
67
  )
68
 
69
- return output, output, text
70
-
71
- # -----------------------------
72
- # UI
73
- # -----------------------------
74
- with gr.Blocks(title="Remove Silence From Audio") as demo:
75
- gr.Markdown("## πŸ”‡ Fast Audio Silence Remover")
 
 
 
 
 
 
76
 
77
  with gr.Row():
78
  with gr.Column():
79
- audio = gr.Audio(type="filepath", sources=["upload", "microphone"])
80
- silence_keep = gr.Number(value=0.05, label="Keep Silence (seconds)")
 
 
 
 
 
 
 
 
 
81
  btn = gr.Button("Remove Silence")
82
 
83
  with gr.Column():
84
- out_audio = gr.Audio()
85
- out_file = gr.File()
86
- info = gr.Textbox()
87
 
88
  btn.click(
89
  process_audio,
90
- [audio, silence_keep],
91
- [out_audio, out_file, info]
92
  )
93
 
94
- # βœ… HF EXPECTS THIS ONLY
 
 
95
  demo.queue().launch()
 
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)
 
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
  )
 
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()