ilakurd commited on
Commit
56c7995
·
verified ·
1 Parent(s): 94c48e6

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +172 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,174 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
 
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
+ import whisper
3
+ import os
4
+ import requests
5
+ from bs4 import BeautifulSoup
6
+ from moviepy.editor import *
7
+ from moviepy.video.fx.all import crop, resize, fadeout, fadein, accelere_decelere
8
+ import arabic_reshaper
9
+ from bidi.algorithm import get_display
10
+ from googletrans import Translator
11
+ import time
12
 
13
+ # --- فەنکشنە پێشکەوتووەکان ---
14
+
15
+ def apply_text_motion(clip, text, font_path, motion_type, duration):
16
+ """دانانی مۆشنی تێکست بەپێی جۆری هەڵبژێردراو."""
17
+
18
+ # چاککردنی فارسی/کوردی
19
+ reshaped_text = arabic_reshaper.reshape(text)
20
+ bidi_text = get_display(reshaped_text)
21
+
22
+ # دانانی شێوازی بنەڕەتی بۆ تێکست
23
+ txt_clip = TextClip(bidi_text, fontsize=80, color='yellow', font=font_path, stroke_color='black', stroke_width=3, method='caption', align='center', size=(700, None))
24
+
25
+ if motion_type == "Fade In/Out":
26
+ # دەرکەوتن و ونبوون
27
+ clip = txt_clip.set_duration(duration).set_pos('bottom').fx(fadein, 0.5).fx(fadeout, 0.5)
28
+
29
+ elif motion_type == "Zoom In":
30
+ # زووم کردن و گەورەبوون
31
+ def zoom_in_effect(t):
32
+ scale = 1 + 0.5 * (t / duration)
33
+ return txt_clip.set_scale(scale).get_frame(t)
34
+ clip = txt_clip.set_duration(duration).set_pos('center').fl(zoom_in_effect, apply_to=['mask', 'video'])
35
+
36
+ elif motion_type == "Slide Up":
37
+ # هاتنەسەرەوە لە خوارەوە
38
+ w, h = txt_clip.size
39
+ clip = txt_clip.set_duration(duration)
40
+ clip = clip.set_pos(lambda t: ('center', 100 + h * (1 - t / duration)))
41
+
42
+ else: # Default (Simple Fade In/Out)
43
+ clip = txt_clip.set_duration(duration).set_pos('bottom').fx(fadein, 0.5).fx(fadeout, 0.5)
44
+
45
+ return clip.set_duration(duration)
46
+
47
+
48
+ def apply_image_motion(image_clip, motion_type):
49
+ """دانانی ئیفێکتی Ken Burns و جوڵەی تری وێنە."""
50
+
51
+ if motion_type == "Ken Burns (Zoom Out)":
52
+ # زووم ئاوتێکی هێواش
53
+ clip = image_clip.fx(vfx.resize, lambda t: 1.2 - 0.2 * (t / image_clip.duration))
54
+
55
+ elif motion_type == "Ken Burns (Zoom In)":
56
+ # زووم ئینێکی هێواش
57
+ clip = image_clip.fx(vfx.resize, lambda t: 1 + 0.2 * (t / image_clip.duration))
58
+
59
+ elif motion_type == "Slide Right":
60
+ # خشاندن بۆ لای ڕاست
61
+ w, h = image_clip.size
62
+ clip = image_clip.set_pos(lambda t: ('-100+{}'.format(int(200 * t / image_clip.duration)), 'center'))
63
+
64
+ else:
65
+ clip = image_clip # بێ جوڵە
66
+
67
+ # دڵنیابوون لە قەبارەی شۆرتی یوتیوب (9:16)
68
+ clip = vfx.resize(clip, height=1280)
69
+ clip = vfx.crop(clip, width=720, height=1280, x_center=clip.w / 2, y_center=clip.h / 2)
70
+ return clip
71
+
72
+ # --- فەنکشنی دروستکردنی ڤیدیۆ (بۆ تێست) ---
73
+ # تێبینی: بەهۆی قورسی دروستکردنی AI Image لەسەر سێرڤەری خۆڕایی، ئێمە وێنەی ڕەنگینی سادە بەکاردێنین بۆ تێست
74
+ def create_ai_images(prompts):
75
+ """لێرە کۆدی دروستکردنی وێنە بە AI (Stable Diffusion/Hugging Face API) دادەنرێت"""
76
+ st.info("بەهۆی سنوورداربوونی سێرڤەری خۆڕایی، 5 وێنەی کاتی دروست دەکرێت.")
77
+ images = []
78
+ colors = [(255, 100, 100), (100, 255, 100), (100, 100, 255), (255, 255, 100), (100, 255, 255)]
79
+ for i in range(5):
80
+ # دروستکردنی وێنەی ڕەنگ بە پیلۆ
81
+ img = ImageClip(np.array([colors[i]]*100*100, dtype=np.uint8).reshape(100, 100, 3), duration=3)
82
+ images.append(img)
83
+ return images
84
+
85
+
86
+ # --- UI سەرەکی ---
87
+ st.title("🎼 ئۆتۆمەیشنی شۆرتی گۆرانی فارسی (پڕۆ)")
88
+ st.caption("سیستەمی 'یەک کلیک' لەسەر Hugging Face Spaces + Streamlit")
89
+
90
+ # ئیختیاراتی بەکاربەر
91
+ st.sidebar.header("🎨 هەڵبژاردەی کوالێتی")
92
+ text_motion = st.sidebar.selectbox("جوڵەی تێکست (Text Motion):", ["Fade In/Out", "Zoom In", "Slide Up", "بێ جوڵە"])
93
+ image_motion = st.sidebar.selectbox("جوڵەی وێنە (Image Motion):", ["Ken Burns (Zoom Out)", "Ken Burns (Zoom In)", "Slide Right", "بێ جوڵە"])
94
+
95
+ uploaded_file = st.file_uploader("فایلی گۆرانییەکە ئەپلۆد بکە (.mp3, .wav)", type=["mp3", "wav"])
96
+
97
+ if uploaded_file is not None:
98
+ st.audio(uploaded_file, format='audio/mp3')
99
+
100
+ if st.button('◀️ دروستکردنی ڤیدیۆ (دەستپێکردن)', key='start_button'):
101
+
102
+ # دڵنیابوون لە سڕینەوەی فایلی پێشوو
103
+ if os.path.exists("temp_audio.mp3"): os.remove("temp_audio.mp3")
104
+ if os.path.exists("final_short.mp4"): os.remove("final_short.mp4")
105
+
106
+ # 1. خەزنکردنی دەنگ
107
+ with open("temp_audio.mp3", "wb") as f:
108
+ f.write(uploaded_file.getbuffer())
109
+
110
+ # 2. Transcribe & Search (هەنگاوەکان)
111
+ with st.spinner('1. ساغکردنەوەی دەنگ و دۆزینەوەی شعر...'):
112
+ model = whisper.load_model("base")
113
+ result = model.transcribe("temp_audio.mp3")
114
+ transcribed_text = result["text"]
115
+
116
+ # لێرە کۆدی گەڕان لە گوگڵ و بەراوردکردن دادەنرێت
117
+
118
+ # دابەشکردنی تێکست بۆ دێڕی کورت بۆ نیشاندان
119
+ lyrics_lines = final_lyrics.split('\n')
120
+ if len(lyrics_lines) < 5: lyrics_lines = [final_lyrics] * 5
121
+ st.success(f"شعرەکە دۆزرایەوە (نموونە): {lyrics_lines[0]}...")
122
+
123
+
124
+ # 3. AI Image Generation (یاخود وێنەی کاتی)
125
+ with st.spinner('2. دروستکردنی وێنەکانی چیرۆکەکە...'):
126
+ image_clips = create_ai_images(lyrics_lines)
127
+ st.success(f"5 وێنەی کاتی دروست کرا.")
128
+
129
+
130
+ # 4. Video Construction
131
+ with st.spinner('3. مۆنتاژکردن و دانانی مۆشنی پڕۆفیشناڵ...'):
132
+
133
+ final_clips = []
134
+ segment_duration = audio_clip.duration / len(image_clips) # دابەشکردنی کات
135
+
136
+ # دروستکردنی ڤیدیۆی سەرەکی
137
+ for i, img_clip in enumerate(image_clips):
138
+
139
+ # دانانی کات بۆ وێنەکە
140
+ img_clip = img_clip.set_duration(segment_duration)
141
+
142
+ # دانانی جوڵە بۆ وێنە (Ken Burns, Slide)
143
+ motion_clip = apply_image_motion(img_clip, image_motion)
144
+
145
+ # دانانی تێکست لەسەر وێنەکە
146
+ if i < len(lyrics_lines):
147
+ text_segment = lyrics_lines[i]
148
+ # دانانی جوڵە بۆ تێکست
149
+ text_clip = apply_text_motion(motion_clip, text_segment, 'Arial', text_motion, segment_duration)
150
+ final_clip = CompositeVideoClip([motion_clip, text_clip])
151
+ else:
152
+ final_clip = motion_clip
153
+
154
+ final_clips.append(final_clip)
155
+
156
+ # یەکخستنی هەموو بەشەکان
157
+ final_video = concatenate_videoclips(final_clips)
158
+
159
+ # دانانی دەنگەکە لەسەر ڤیدیۆ کۆتاییەکە
160
+ audio_clip = AudioFileClip("temp_audio.mp3")
161
+ final_video = final_video.set_audio(audio_clip)
162
+
163
+ # Render
164
+ final_video.write_videofile("final_short.mp4", fps=24, threads=4, logger=None)
165
+ st.success("✅ ڤیدیۆکە بە سەرکەوتوویی دروست کرا!")
166
+
167
+ st.video("final_short.mp4")
168
+ with open("final_short.mp4", "rb") as file:
169
+ st.download_button(
170
+ label="داگرتنی ڤیدیۆکە (.mp4)",
171
+ data=file,
172
+ file_name="youtube_short.mp4",
173
+ mime="video/mp4"
174
+ )