import os, whisper, asyncio, edge_tts, re from googletrans import Translator from moviepy.editor import VideoFileClip, AudioFileClip, CompositeAudioClip import moviepy.video.fx.all as vfx # --- ⚙️ កំណត់រចនាសម្ព័ន្ធ --- Video_Name = "movie.mp4" VIDEO_PATH = f"input_video/{Video_Name}" OUTPUT_PATH = f"final_result/LONG_DUB_{Video_Name}" translator = Translator() def professional_khmer_filter(text): try: raw_kh = translator.translate(text, src='zh-cn', dest='km').text corrections = { "អ្នក": "ឯង", "ខ្ញុំ": "យើង", "របស់ខ្ញុំ": "របស់បង", "តើអ្នកកំពុងធ្វើអ្វី": "ឯងធ្វើស្អីហ្នឹង?", "សួស្តី": "ជម្រាបសួរ", "អរគុណ": "អរគុណច្រើន", "បាទ": "បាទ/ចា៎", "មែនទេ": "មែនអត់?", "តើមានរឿងអ្វី": "មានរឿងអី?", "ពិតជា": "ពិតមែនហើយ", "មិនអាច": "មិនបានទេ", } for old, new in corrections.items(): raw_kh = raw_kh.replace(old, new) return re.sub(r'[.,!?]', ' ', raw_kh).strip() except: return "" async def generate_smooth_audio(text, start, duration, index): try: kh_text = professional_khmer_filter(text) if not kh_text: return None, None voice = "km-KH-PisethNeural" # ម្ចាស់គ្រូអាចកែជា Sreymom បើជាតួស្រី tmp = f"tmp_{index}_{start}.mp3" communicate = edge_tts.Communicate(kh_text, voice, rate="+7%") await communicate.save(tmp) audio = AudioFileClip(tmp).set_start(start).volumex(4.5) if audio.duration > duration: return vfx.speedx(audio, factor=audio.duration/duration).set_duration(duration), tmp return audio, tmp except: return None, None async def start_dubbing(): if not os.path.exists(VIDEO_PATH): print("❌ រកមិនឃើញ File វីដេអូទេម្ចាស់គ្រូ!") return # ១. ប្រើ Whisper ស្កែន (សម្រាប់រឿងវែង គួរប្រើ 'base' បើ RAM តិច ឬ 'medium' បើមាន GPU ខ្លាំង) print("🔍 កំពុងវិភាគសាច់រឿងវែង... (សូមរង់ចាំបន្តិច)") model = whisper.load_model("medium") transcribe = model.transcribe(VIDEO_PATH, task="transcribe", language="zh") # ២. រៀបចំ Segment merged_segments = transcribe['segments'] video = VideoFileClip(VIDEO_PATH) audio_tracks = [video.audio.volumex(0.15)] temp_files = [] print(f"🎙️ ចាប់ផ្ដើម Dubbing ចំនួន {len(merged_segments)} ឃ្លា...") # ៣. ប្រើ Loop ធម្មតាជំនួសឱ្យ asyncio.gather ដើម្បីការពារការគាំង RAM for i, s in enumerate(merged_segments): # បង្កើតសំឡេងម្ដងមួយៗ aud, path = await generate_smooth_audio(s['text'], s['start'], s['end']-s['start'], i) if aud: audio_tracks.append(aud) temp_files.append(path) # បង្ហាញ Progress ឱ្យម្ចាស់គ្រូដឹង if i % 10 == 0: print(f"⏳ ធ្វើបាន {i}/{len(merged_segments)} ឃ្លាហើយ...") # ៤. រួមបញ្ចូលគ្នា print("🎬 កំពុងបូកបញ្ចូលសំឡេង និង Export វីដេអូកម្រិតច្បាស់...") final_audio = CompositeAudioClip(audio_tracks) final_video = video.set_audio(final_audio) # ប្រើ threads=4 ដើម្បីឱ្យវា Export លឿន final_video.write_videofile(OUTPUT_PATH, codec="libx264", audio_codec="aac", fps=video.fps, threads=4) # ៥. សម្អាត File video.close() # បិទ File ដើម្បីឱ្យលុប Temp បាន for f in temp_files: try: os.remove(f) except: pass print(f"✅ រួចរាល់ហើយម្ចាស់គ្រូ! វីដេអូរឿងវែងស្ថិតនៅ៖ {OUTPUT_PATH}") # រត់កម្មវិធី await start_dubbing()
    Blogger Comment
    Facebook Comment

0 comments:

Post a Comment

 
Copyright © 2026. BM7//ANGKOR - All Rights Reserved
Template Created by ThemeXpose | BM7//ANGKOR