1littlecoder commited on
Commit
b2da359
·
verified ·
1 Parent(s): 4855114

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -169
app.py CHANGED
@@ -1,172 +1,32 @@
1
  import gradio as gr
2
- import numpy as np
3
- import matplotlib.pyplot as plt
4
- from matplotlib.animation import FuncAnimation
5
- import tempfile
6
- import os
7
- import shutil
8
- import subprocess
9
- from typing import Any
10
- import PIL
11
- import processing_utils # Import or define your custom processing utilities
12
 
13
- def make_waveform(
14
- audio: tuple[int, np.ndarray],
15
- bg_color: str = "#f3f4f6",
16
- bg_image: str | None = None,
17
- fg_alpha: float = 0.75,
18
- bars_color: str | tuple[str, str] = ("#fbbf24", "#ea580c"),
19
- bar_count: int = 50,
20
- bar_width: float = 0.6,
21
- animate: bool = False,
22
- ) -> str:
23
- if isinstance(audio, str):
24
- audio_file = audio
25
- audio = processing_utils.audio_from_file(audio)
26
- else:
27
- tmp_wav = tempfile.NamedTemporaryFile(suffix=".wav", delete=False)
28
- processing_utils.audio_to_file(audio[0], audio[1], tmp_wav.name, format="wav")
29
- audio_file = tmp_wav.name
30
-
31
- if not os.path.isfile(audio_file):
32
- raise ValueError("Audio file not found.")
33
-
34
- ffmpeg = shutil.which("ffmpeg")
35
- if not ffmpeg:
36
- raise RuntimeError("ffmpeg not found.")
37
-
38
- duration = round(len(audio[1]) / audio[0], 4)
39
-
40
- def hex_to_rgb(hex_str):
41
- return [int(hex_str[i : i + 2], 16) for i in range(1, 6, 2)]
42
-
43
- def get_color_gradient(c1, c2, n):
44
- if n < 1:
45
- raise ValueError("Must have at least one stop in gradient")
46
- c1_rgb = np.array(hex_to_rgb(c1)) / 255
47
- c2_rgb = np.array(hex_to_rgb(c2)) / 255
48
- mix_pcts = [x / (n - 1) for x in range(n)]
49
- rgb_colors = [((1 - mix) * c1_rgb + (mix * c2_rgb)) for mix in mix_pcts]
50
- return [
51
- "#" + "".join(f"{int(round(val * 255)):02x}" for val in item)
52
- for item in rgb_colors
53
- ]
54
-
55
- samples = audio[1]
56
- if len(samples.shape) > 1:
57
- samples = np.mean(samples, 1)
58
- bins_to_pad = bar_count - (len(samples) % bar_count)
59
- samples = np.pad(samples, [(0, bins_to_pad)])
60
- samples = np.reshape(samples, (bar_count, -1))
61
- samples = np.abs(samples)
62
- samples = np.max(samples, 1)
63
-
64
- color = (
65
- bars_color
66
- if isinstance(bars_color, str)
67
- else get_color_gradient(bars_color[0], bars_color[1], bar_count)
68
- )
69
-
70
- fig = plt.figure(figsize=(5, 1), dpi=200, frameon=False)
71
- plt.axis("off")
72
- plt.margins(x=0)
73
-
74
- bar_alpha = fg_alpha if animate else 1.0
75
- barcollection = plt.bar(
76
- np.arange(0, bar_count),
77
- samples * 2,
78
- bottom=(-1 * samples),
79
- width=bar_width,
80
- color=color,
81
- alpha=bar_alpha,
82
- )
83
-
84
- tmp_img = tempfile.NamedTemporaryFile(suffix=".png", delete=False)
85
- savefig_kwargs: dict[str, Any] = {"bbox_inches": "tight"}
86
- if bg_image is not None:
87
- savefig_kwargs["transparent"] = True
88
- else:
89
- savefig_kwargs["facecolor"] = bg_color
90
- plt.savefig(tmp_img.name, **savefig_kwargs)
91
-
92
- if not animate:
93
- waveform_img = PIL.Image.open(tmp_img.name)
94
- waveform_img.save(tmp_img.name)
95
- else:
96
- def _animate(_):
97
- for idx, b in enumerate(barcollection):
98
- rand_height = np.random.uniform(0.8, 1.2)
99
- b.set_height(samples[idx] * rand_height * 2)
100
- b.set_y((-rand_height * samples)[idx])
101
-
102
- frames = int(duration * 10)
103
- anim = FuncAnimation(
104
- fig,
105
- _animate,
106
- repeat=False,
107
- blit=False,
108
- frames=frames,
109
- interval=100,
110
- )
111
- anim.save(tmp_img.name, writer="pillow", fps=10, codec="png", savefig_kwargs=savefig_kwargs)
112
-
113
- output_mp4 = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
114
-
115
- ffmpeg_cmd = [
116
- ffmpeg,
117
- "-loop",
118
- "1",
119
- "-i",
120
- tmp_img.name,
121
- "-i",
122
- audio_file,
123
- "-vf",
124
- f"color=c=#FFFFFF77:s=1000x400[bar];[0][bar]overlay=-w+(w/{duration})*t:H-h:shortest=1",
125
- "-t",
126
- str(duration),
127
- "-y",
128
- output_mp4.name,
129
- ]
130
-
131
- subprocess.check_call(ffmpeg_cmd)
132
- return output_mp4.name
133
-
134
- # Gradio app
135
- def generate_waveform(audio, bg_color, fg_alpha, bars_color, bar_count, bar_width, animate):
136
- try:
137
- video_path = make_waveform(
138
- audio=(audio[0], np.array(audio[1])),
139
- bg_color=bg_color,
140
- fg_alpha=fg_alpha,
141
- bars_color=bars_color,
142
- bar_count=bar_count,
143
- bar_width=bar_width,
144
- animate=animate
145
- )
146
- return video_path
147
- except Exception as e:
148
- return str(e)
149
-
150
- with gr.Blocks() as demo:
151
- gr.Markdown("### Audio Waveform Generator")
152
 
153
- with gr.Row():
154
- audio_input = gr.Audio(label="Upload Audio", source="upload", type="numpy")
155
- video_output = gr.Video(label="Waveform Video")
156
-
157
- with gr.Row():
158
- bg_color = gr.ColorPicker(label="Background Color", value="#f3f4f6")
159
- fg_alpha = gr.Slider(label="Foreground Opacity", minimum=0.1, maximum=1.0, value=0.75)
160
- bar_count = gr.Slider(label="Number of Bars", minimum=10, maximum=100, step=1, value=50)
161
- bar_width = gr.Slider(label="Bar Width", minimum=0.1, maximum=1.0, value=0.6)
162
- bars_color = gr.ColorPicker(label="Bars Color", value="#fbbf24")
163
- animate = gr.Checkbox(label="Animate", value=False)
164
-
165
- generate_button = gr.Button("Generate Waveform")
166
- generate_button.click(
167
- generate_waveform,
168
- inputs=[audio_input, bg_color, fg_alpha, bars_color, bar_count, bar_width, animate],
169
- outputs=video_output
170
- )
171
-
172
- demo.launch(debug = True)
 
 
 
 
 
 
1
  import gradio as gr
2
+ from moviepy.editor import AudioFileClip, ImageClip
 
 
 
 
 
 
 
 
 
3
 
4
+ def create_video(image, audio):
5
+ # Load the audio file
6
+ audio_clip = AudioFileClip(audio.name)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
+ # Load the image file and set it to the duration of the audio
9
+ image_clip = ImageClip(image.name).set_duration(audio_clip.duration)
10
+
11
+ # Set the audio to the image clip
12
+ video_clip = image_clip.set_audio(audio_clip)
13
+
14
+ # Save the video to a temporary file
15
+ output_path = "/tmp/output_video.mp4"
16
+ video_clip.write_videofile(output_path, fps=30)
17
+
18
+ return output_path
19
+
20
+ # Create Gradio interface
21
+ iface = gr.Interface(
22
+ fn=create_video,
23
+ inputs=[
24
+ gr.inputs.Image(type="file", label="Upload Image"),
25
+ gr.inputs.Audio(type="file", label="Upload Audio")
26
+ ],
27
+ outputs=gr.outputs.Video(label="Output Video"),
28
+ title="Image + Audio to Video Converter",
29
+ description="Upload an image and an audio file to generate a video with the image and audio combined."
30
+ )
31
+
32
+ iface.launch()