import os, whisper, asyncio, edge_tts, re, torch from googletrans import Translator from moviepy.editor import VideoFileClip, AudioFileClip, CompositeAudioClip import moviepy.video.fx.all as vfx # --- ⚙️ ការកំណត់ (ម្ចាស់គ្រូកែឈ្មោះ File នៅទីនេះ) --- Video_Name = "movie.mp4" VIDEO_PATH = f"input_video/{Video_Name}" OUTPUT_PATH = f"final_result/BM7_ANGKOR_PRO_{Video_Name}" translator = Translator() # --- 🧠 មុខងារបែងចែកភេទ និងចម្រោះពាក្យឡប់ --- def detect_gender(text): female_keywords = ['នាង', 'ស្រី', 'អូន', 'អ្នកនាង', 'កញ្ញា', 'ម៉ាក់', 'យាយ', 'ព្រះនាង'] if any(word in text for word in female_keywords): return "km-KH-SreymomNeural" return "km-KH-PisethNeural" def clean_repetition(text): # លុបពាក្យដែលលោតដដែលៗ (ឧទាហរណ៍៖ "នៅទីនោះ នៅទីនោះ" -> "នៅទីនោះ") return re.sub(r'\b(\w+)( \1\b)+', r'\1', text) 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) # ចម្រោះពាក្យដដែលៗ និងនិមិត្តសញ្ញា clean_text = clean_repetition(raw_kh) return re.sub(r'[.,!?]', ' ', clean_text).strip() except: return "" async def generate_voice(text, start, duration, index): try: kh_text = professional_khmer_filter(text) if not kh_text or len(kh_text) < 2: return None, None selected_voice = detect_gender(kh_text) tmp = f"tmp_{index}.mp3" # កែសម្រួលល្បឿន និងសម្លេងឱ្យមានជីវិត communicate = edge_tts.Communicate(kh_text, selected_voice, rate="+8%", pitch="-1Hz") await communicate.save(tmp) audio = AudioFileClip(tmp).set_start(start).volumex(5.0) 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(f"❌ រកមិនឃើញ File: {VIDEO_PATH}") return print("🚀 កំពុងដាស់ម៉ាស៊ីន AI (Whisper Medium)...") device = "cuda" if torch.cuda.is_available() else "cpu" model = whisper.load_model("medium").to(device) # បន្ថែម Parameters ការពារការនិយាយឡប់ដដែលៗ print("🔍 កំពុងវិភាគសាច់រឿង (ទប់ស្កាត់ Hallucination)...") transcribe = model.transcribe( VIDEO_PATH, task="transcribe", language="zh", temperature=0, # កាត់បន្ថយការទាយខុស beam_size=5, # បង្កើនភាពហ្មត់ចត់ compression_ratio_threshold=2.4, # លុបពាក្យដដែលៗ no_speech_threshold=0.6 # មិនបកប្រែបើលឺតែភ្លេង ) segments = transcribe['segments'] video = VideoFileClip(VIDEO_PATH) audio_tracks = [video.audio.volumex(0.12)] temp_files = [] print(f"🎙️ ចាប់ផ្ដើមផលិតសម្លេងតួអង្គចំនួន {len(segments)} ឃ្លា...") for i, s in enumerate(segments): aud, path = await generate_voice(s['text'], s['start'], s['end']-s['start'], i) if aud: audio_tracks.append(aud) temp_files.append(path) if i % 25 == 0: print(f"⏳ ដំណើរការបាន {round((i/len(segments))*100)}% ...") print("🎬 កំពុងបូកបញ្ចូលគ្នា និង Export វីដេអូ (Threads=4)...") final_audio = CompositeAudioClip(audio_tracks) final_video = video.set_audio(final_audio) final_video.write_videofile( OUTPUT_PATH, codec="libx264", audio_codec="aac", fps=video.fps, threads=4, logger=None # បិទការបង្ហាញ log រញ៉េរញ៉ៃ ) video.close() for f in temp_files: try: os.remove(f) except: pass print(f"✅ សម្រេចមហាជោគជ័យ! ម្ចាស់គ្រូអាចមើលវីដេអូបាននៅ៖ {OUTPUT_PATH}") # រត់ដំណើរការ if __name__ == "__main__": 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