File size: 8,148 Bytes
89328d3
56c7995
 
 
 
23669f0
56c7995
 
 
 
89328d3
56c7995
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import streamlit as st
import whisper
import os
import requests
from bs4 import BeautifulSoup
from moviepy.editor import *
import arabic_reshaper
from bidi.algorithm import get_display
from googletrans import Translator
import time

# --- فەنکشنە پێشکەوتووەکان ---

def apply_text_motion(clip, text, font_path, motion_type, duration):
    """دانانی مۆشنی تێکست بەپێی جۆری هەڵبژێردراو."""
    
    # چاککردنی فارسی/کوردی
    reshaped_text = arabic_reshaper.reshape(text)
    bidi_text = get_display(reshaped_text)
    
    # دانانی شێوازی بنەڕەتی بۆ تێکست
    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))
    
    if motion_type == "Fade In/Out":
        # دەرکەوتن و ونبوون
        clip = txt_clip.set_duration(duration).set_pos('bottom').fx(fadein, 0.5).fx(fadeout, 0.5)
        
    elif motion_type == "Zoom In":
        # زووم کردن و گەورەبوون
        def zoom_in_effect(t):
            scale = 1 + 0.5 * (t / duration)
            return txt_clip.set_scale(scale).get_frame(t)
        clip = txt_clip.set_duration(duration).set_pos('center').fl(zoom_in_effect, apply_to=['mask', 'video'])

    elif motion_type == "Slide Up":
        # هاتنەسەرەوە لە خوارەوە
        w, h = txt_clip.size
        clip = txt_clip.set_duration(duration)
        clip = clip.set_pos(lambda t: ('center', 100 + h * (1 - t / duration)))
        
    else: # Default (Simple Fade In/Out)
        clip = txt_clip.set_duration(duration).set_pos('bottom').fx(fadein, 0.5).fx(fadeout, 0.5)
        
    return clip.set_duration(duration)


def apply_image_motion(image_clip, motion_type):
    """دانانی ئیفێکتی Ken Burns و جوڵەی تری وێنە."""
    
    if motion_type == "Ken Burns (Zoom Out)":
        # زووم ئاوتێکی هێواش
        clip = image_clip.fx(vfx.resize, lambda t: 1.2 - 0.2 * (t / image_clip.duration))
        
    elif motion_type == "Ken Burns (Zoom In)":
        # زووم ئینێکی هێواش
        clip = image_clip.fx(vfx.resize, lambda t: 1 + 0.2 * (t / image_clip.duration))
        
    elif motion_type == "Slide Right":
        # خشاندن بۆ لای ڕاست
        w, h = image_clip.size
        clip = image_clip.set_pos(lambda t: ('-100+{}'.format(int(200 * t / image_clip.duration)), 'center'))
        
    else:
        clip = image_clip # بێ جوڵە
        
    # دڵنیابوون لە قەبارەی شۆرتی یوتیوب (9:16)
    clip = vfx.resize(clip, height=1280)
    clip = vfx.crop(clip, width=720, height=1280, x_center=clip.w / 2, y_center=clip.h / 2)
    return clip

# --- فەنکشنی دروستکردنی ڤیدیۆ (بۆ تێست) ---
# تێبینی: بەهۆی قورسی دروستکردنی AI Image لەسەر سێرڤەری خۆڕایی، ئێمە وێنەی ڕەنگینی سادە بەکاردێنین بۆ تێست
def create_ai_images(prompts):
    """لێرە کۆدی دروستکردنی وێنە بە AI (Stable Diffusion/Hugging Face API) دادەنرێت"""
    st.info("بەهۆی سنوورداربوونی سێرڤەری خۆڕایی، 5 وێنەی کاتی دروست دەکرێت.")
    images = []
    colors = [(255, 100, 100), (100, 255, 100), (100, 100, 255), (255, 255, 100), (100, 255, 255)]
    for i in range(5):
        # دروستکردنی وێنەی ڕەنگ بە پیلۆ
        img = ImageClip(np.array([colors[i]]*100*100, dtype=np.uint8).reshape(100, 100, 3), duration=3)
        images.append(img)
    return images


# --- UI سەرەکی ---
st.title("🎼 ئۆتۆمەیشنی شۆرتی گۆرانی فارسی (پڕۆ)")
st.caption("سیستەمی 'یەک کلیک' لەسەر Hugging Face Spaces + Streamlit")

# ئیختیاراتی بەکاربەر
st.sidebar.header("🎨 هەڵبژاردەی کوالێتی")
text_motion = st.sidebar.selectbox("جوڵەی تێکست (Text Motion):", ["Fade In/Out", "Zoom In", "Slide Up", "بێ جوڵە"])
image_motion = st.sidebar.selectbox("جوڵەی وێنە (Image Motion):", ["Ken Burns (Zoom Out)", "Ken Burns (Zoom In)", "Slide Right", "بێ جوڵە"])

uploaded_file = st.file_uploader("فایلی گۆرانییەکە ئەپلۆد بکە (.mp3, .wav)", type=["mp3", "wav"])

if uploaded_file is not None:
    st.audio(uploaded_file, format='audio/mp3')
    
    if st.button('◀️ دروستکردنی ڤیدیۆ (دەستپێکردن)', key='start_button'):
        
        # دڵنیابوون لە سڕینەوەی فایلی پێشوو
        if os.path.exists("temp_audio.mp3"): os.remove("temp_audio.mp3")
        if os.path.exists("final_short.mp4"): os.remove("final_short.mp4")

        # 1. خەزنکردنی دەنگ
        with open("temp_audio.mp3", "wb") as f:
            f.write(uploaded_file.getbuffer())
        
        # 2. Transcribe & Search (هەنگاوەکان)
        with st.spinner('1. ساغکردنەوەی دەنگ و دۆزینەوەی شعر...'):
            model = whisper.load_model("base")
            result = model.transcribe("temp_audio.mp3")
            transcribed_text = result["text"]
            
            # لێرە کۆدی گەڕان لە گوگڵ و بەراوردکردن دادەنرێت
            
            # دابەشکردنی تێکست بۆ دێڕی کورت بۆ نیشاندان
            lyrics_lines = final_lyrics.split('\n') 
            if len(lyrics_lines) < 5: lyrics_lines = [final_lyrics] * 5
            st.success(f"شعرەکە دۆزرایەوە (نموونە): {lyrics_lines[0]}...")


        # 3. AI Image Generation (یاخود وێنەی کاتی)
        with st.spinner('2. دروستکردنی وێنەکانی چیرۆکەکە...'):
            image_clips = create_ai_images(lyrics_lines)
            st.success(f"5 وێنەی کاتی دروست کرا.")

        
        # 4. Video Construction
        with st.spinner('3. مۆنتاژکردن و دانانی مۆشنی پڕۆفیشناڵ...'):
            
            final_clips = []
            segment_duration = audio_clip.duration / len(image_clips) # دابەشکردنی کات

            # دروستکردنی ڤیدیۆی سەرەکی
            for i, img_clip in enumerate(image_clips):
                
                # دانانی کات بۆ وێنەکە
                img_clip = img_clip.set_duration(segment_duration)
                
                # دانانی جوڵە بۆ وێنە (Ken Burns, Slide)
                motion_clip = apply_image_motion(img_clip, image_motion)
                
                # دانانی تێکست لەسەر وێنەکە
                if i < len(lyrics_lines):
                    text_segment = lyrics_lines[i]
                    # دانانی جوڵە بۆ تێکست
                    text_clip = apply_text_motion(motion_clip, text_segment, 'Arial', text_motion, segment_duration)
                    final_clip = CompositeVideoClip([motion_clip, text_clip])
                else:
                    final_clip = motion_clip

                final_clips.append(final_clip)

            # یەکخستنی هەموو بەشەکان
            final_video = concatenate_videoclips(final_clips)
            
            # دانانی دەنگەکە لەسەر ڤیدیۆ کۆتاییەکە
            audio_clip = AudioFileClip("temp_audio.mp3")
            final_video = final_video.set_audio(audio_clip)

            # Render
            final_video.write_videofile("final_short.mp4", fps=24, threads=4, logger=None)
            st.success("✅ ڤیدیۆکە بە سەرکەوتوویی دروست کرا!")
            
            st.video("final_short.mp4")
            with open("final_short.mp4", "rb") as file:
                st.download_button(
                    label="داگرتنی ڤیدیۆکە (.mp4)",
                    data=file,
                    file_name="youtube_short.mp4",
                    mime="video/mp4"
                )