Recent Videos
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()
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()

Clone voice

# ១. ដំឡើងបណ្ណាល័យចាំបាច់ (រង់ចាំប្រហែល ២-៣ នាទី) !pip install coqui-tts openai-whisper moviepy==1.0.3 googletrans==4.0.0-rc1 torch torchvision torchaudio import os, whisper, asyncio, torch from TTS.api import TTS from googletrans import Translator from moviepy.editor import VideoFileClip, AudioFileClip, CompositeAudioClip import moviepy.video.fx.all as vfx # ២. កំណត់ផ្លូវ File (ម្ចាស់គ្រូអាចប្តូរឈ្មោះតាមចិត្ត) VIDEO_IN = "jade_video.mp4" MALE_VOICE = "male_ref.wav" FEMALE_VOICE = "female_ref.wav" OUTPUT_NAME = "BM7_CLONED_COLAB.mp4" # ៣. ដាស់ម៉ាស៊ីន AI (ប្រើ GPU ឥតគិតថ្លៃរបស់ Google) device = "cuda" if torch.cuda.is_available() else "cpu" print(f"🚀 កំពុងប្រើអំណាច GPU: {device}") tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2").to(device) translator = Translator() model = whisper.load_model("medium") # ៤. មុខងារក្លូនសំឡេង def clone_voice(text, start, gender): ref_path = MALE_VOICE if gender == "MALE" else FEMALE_VOICE out_path = f"tmp_{start}.wav" tts.tts_to_file(text=text, speaker_wav=ref_path, language="kh", file_path=out_path) return out_path # ៥. ចាប់ផ្ដើមដំណើរការ Dubbing print("🔍 កំពុងវិភាគសាច់រឿង និងបកប្រែ...") transcribe = model.transcribe(VIDEO_IN, language="zh") video = VideoFileClip(VIDEO_IN) audio_tracks = [video.audio.volumex(0.15)] for s in transcribe['segments']: kh_text = translator.translate(s['text'], src='zh-cn', dest='km').text # បែងចែកភេទតួអង្គ (Logic BM7 ម្ចាស់គ្រូ) gender = "FEMALE" if any(w in kh_text for w in ['នាង', 'ស្រី', 'អូន', 'អ្នកនាង']) else "MALE" print(f"🎙️ [{s['start']}s] កំពុងក្លូន៖ {kh_text}") wave_file = clone_voice(kh_text, s['start'], gender) if wave_file: duration = s['end'] - s['start'] clip = AudioFileClip(wave_file).set_start(s['start']).volumex(4.5) # សម្រួលល្បឿនឱ្យត្រូវមាត់ (Lip-sync) if clip.duration > duration: clip = vfx.speedx(clip, factor=clip.duration/duration).set_duration(duration) audio_tracks.append(clip) # ៦. រួមបញ្ចូល និងទាញយកវីដេអូ print("🎬 កំពុងផលិតវីដេអូចុងក្រោយ...") final_video = video.set_audio(CompositeAudioClip(audio_tracks)) final_video.write_videofile(OUTPUT_NAME, codec="libx264", audio_codec="aac") print(f"✅ រួចរាល់! ម្ចាស់គ្រូអាច Download File {OUTPUT_NAME} បានហើយ!")
import os, whisper, asyncio, re import edge_tts from googletrans import Translator from moviepy.editor import VideoFileClip, AudioFileClip, CompositeAudioClip import moviepy.video.fx.all as vfx # --- ⚙️ ការកំណត់ (Configuration) --- VIDEO_INPUT = "input_video/your_video.mp4" # ដាក់ឈ្មោះ File វីដេអូម្ចាស់គ្រូ OUTPUT_NAME = "final_result/BM7_DUBBED_V3.mp4" translator = Translator() # --- 🎙️ មុខងារបែងចែកភេទតួអង្គ និងកែសម្រួលភាសា --- def filter_and_improve_khmer(text): # ១. បកប្រែពីចិន មកខ្មែរ translation = translator.translate(text, src='zh-cn', dest='km').text # ២. កំណត់ភេទតួអង្គតាមពាក្យគន្លឹះ (Keywords) female_words = ['នាង', 'ស្រី', 'ព្រះនាង', 'អ្នកនាង', 'ម៉ាក់', 'បងស្រី', 'អូន', 'ម្ចាស់ក្សត្រី'] gender = "FEMALE" if any(word in translation for word in female_words) else "MALE" # ៣. កែសម្រួលពាក្យឱ្យសមជារឿងភាគ (Drama Style) replacements = { "អ្នក": "ឯង", "ខ្ញុំ": "យើង", "តើអ្នកសុខសប្បាយទេ": "ឯងសុខសប្បាយទេ?", "តើមានរឿងអ្វី": "មានរឿងអីហ្នឹង?", "ពិតជា": "ពិតមែនហើយ", "អរគុណ": "អរគុណហើយ" } for old, new in replacements.items(): translation = translation.replace(old, new) return translation.strip(), gender # --- 🔊 មុខងារបង្កើតសំឡេង AI --- async def generate_voice(text, start, duration): try: kh_text, gender = filter_and_improve_khmer(text) if not kh_text: return None, None # ជ្រើសរើសសំឡេង (Piseth សម្រាប់ប្រុស, Sreymom សម្រាប់ស្រី) voice = "km-KH-PisethNeural" if gender == "MALE" else "km-KH-SreymomNeural" tmp_path = f"temp_audio_{start}.mp3" communicate = edge_tts.Communicate(kh_text, voice, rate="+5%") # បន្ថែមល្បឿន ៥% ឱ្យសមស្រប await communicate.save(tmp_path) audio = AudioFileClip(tmp_path).set_start(start).volumex(5.0) # បង្កើនកម្រិតសំឡេងឱ្យច្បាស់ # ធ្វើឱ្យសំឡេងត្រូវនឹងរូបភាព (Lip-sync Adjustment) if audio.duration > duration: return vfx.speedx(audio, factor=audio.duration/duration).set_duration(duration), tmp_path return audio, tmp_path except Exception as e: print(f"Error creating voice: {e}") return None, None async def run_dubbing_process(): # ១. វិភាគវីដេអូជាមួយ Whisper (ប្រើភាសាចិន) print("🔍 កំពុងស្កែនសាច់រឿង... (Whisper Medium)") model = whisper.load_model("medium") result = model.transcribe(VIDEO_INPUT, task="transcribe", language="zh") video = VideoFileClip(VIDEO_INPUT) audio_tracks = [video.audio.volumex(0.2)] # បន្ថយសំឡេងដើម ២០% ដើម្បីឱ្យឮសំឡេង AI ច្បាស់ # ២. បង្កើតសំឡេងខ្មែរដាក់ចូលវីដេអូ print("🎬 កំពុងបញ្ចូលសំឡេងខ្មែរដោយ AI...") temp_files = [] for segment in result['segments']: aud, path = await generate_voice(segment['text'], segment['start'], segment['end'] - segment['start']) if aud: audio_tracks.append(aud) temp_files.append(path) # ៣. រួមបញ្ចូល និង Export វីដេអូចុងក្រោយ final_audio = CompositeAudioClip(audio_tracks) final_video = video.set_audio(final_audio) final_video.write_videofile(OUTPUT_NAME, codec="libx264", audio_codec="aac") # លុប File បណ្តោះអាសន្ន for f in temp_files: if os.path.exists(f): os.remove(f) print(f"✅ រួចរាល់ហើយម្ចាស់គ្រូ! វីដេអូស្ថិតនៅ៖ {OUTPUT_NAME}") if __name__ == "__main__": asyncio.run(run_dubbing_process())
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 = "PRO_AI_DUB_BM7.mp4" VIDEO_PATH = f"input_video/{Video_Name}" OUTPUT_PATH = f"final_result/CHARACTER_DUB_SLOW_{Video_Name}" translator = Translator() # --- 🎙️ បញ្ជីសំឡេងតួអង្គ --- VOICES = { "MALE": "km-KH-PisethNeural", "FEMALE": "km-KH-SreymomNeural" } # --- 🧠 ម៉ាស៊ីនវិភាគតួអង្គ និងកែសម្រួលភាសា --- def identify_and_filter(text): raw_kh = translator.translate(text, src='zh-cn', dest='km').text female_keywords = ['នាង', 'ស្រី', 'ព្រះនាង', 'អ្នកនាង', 'ម៉ាក់', 'បងស្រី', 'អូន'] gender = "MALE" if any(word in raw_kh for word in female_keywords): gender = "FEMALE" corrections = { "អ្នក": "ឯង", "ខ្ញុំ": "យើង", "តើអ្នកកំពុងធ្វើអ្វី": "ឯងកំពុងធ្វើស្អី?", "ពិតជា": "ពិតមែនហើយ", "មិនអាច": "មិនបានទេ", "តើមានរឿងអ្វី": "មានរឿងអី?" } for old, new in corrections.items(): raw_kh = raw_kh.replace(old, new) return raw_kh.strip(), gender async def generate_character_audio(text, start, duration): try: kh_text, gender = identify_and_filter(text) if not kh_text: return None, None selected_voice = VOICES[gender] # បន្ថយល្បឿនមកត្រឹម +0% (ល្បឿនដើម) ដើម្បីឱ្យស្ដាប់បានច្បាស់ល្អ # ម្ចាស់គ្រូអាចប្តូរជា "+3%" បើចង់ឱ្យលឿនជាងនេះបន្តិច rate_setting = "+0%" tmp = f"tmp_{start}.mp3" communicate = edge_tts.Communicate(kh_text, selected_voice, rate=rate_setting) 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 Exception as e: print(f"Error: {e}") return None, None async def start_multi_dubbing(): model = whisper.load_model("medium") print("🔍 កំពុងវិភាគសាច់រឿង (ល្បឿនធម្មជាតិ)...") transcribe = model.transcribe(VIDEO_PATH, task="transcribe", language="zh") segments = transcribe['segments'] video = VideoFileClip(VIDEO_PATH) audio_tracks = [video.audio.volumex(0.15)] print(f"🎬 កំពុងបញ្ចូលសំឡេងតួអង្គក្នុងល្បឿនសមល្មម...") tasks = [generate_character_audio(s['text'], s['start'], s['end']-s['start']) for s in segments] results = await asyncio.gather(*tasks) temp_files = [] for aud, path in results: if aud: audio_tracks.append(aud) temp_files.append(path) final_audio = CompositeAudioClip(audio_tracks) final_video = video.set_audio(final_audio) final_video.write_videofile(OUTPUT_PATH, codec="libx264", audio_codec="aac") for f in temp_files: if os.path.exists(f): os.remove(f) print(f"✅ រួចរាល់! វីដេអូសំឡេងរលូន៖ {OUTPUT_PATH}") if __name__ == "__main__": await start_multi_dubbing()
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/SMOOTH_AI_DUB_{Video_Name}" translator = Translator() # --- 🧠 ម៉ាស៊ីនប៉ូឡាបកប្រែ (Fluency Engine) --- def professional_khmer_filter(text): # បកប្រែដោយផ្ដោតលើអត្ថន័យ 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) # បច្ចេកទេស Joiner: លុបដកឃ្លាដែលមិនចាំបាច់ ដើម្បីកុំឱ្យ AI អានដាច់ៗ final_text = re.sub(r'[.,!?]', ' ', raw_kh) # ប្តូរសញ្ញាខណ្ឌមកជាដកឃ្លាខ្លីវិញ return final_text.strip() async def generate_smooth_audio(text, start, duration): try: kh_text = professional_khmer_filter(text) if not kh_text: return None, None # កំណត់កម្រិតសំឡេងឱ្យស្រទន់ និងល្បឿនថេរ # ប្រើ "km-KH-SreymomNeural" សម្រាប់ស្រី ឬ "km-KH-PisethNeural" សម្រាប់ប្រុស voice = "km-KH-PisethNeural" tmp = f"tmp_{start}.mp3" communicate = edge_tts.Communicate(kh_text, voice, rate="+5%", pitch="-1Hz") await communicate.save(tmp) audio = AudioFileClip(tmp).set_start(start).volumex(4.0) # រក្សាល្បឿននិយាយឱ្យត្រូវនឹងពេលវេលា (Time-Stretching) 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(): # ១. ស្ដាប់ និងបំប្លែងសំឡេងចិន (Whisper Medium - ខ្លាំងជាងមុន) model = whisper.load_model("medium") transcribe = model.transcribe(VIDEO_PATH, task="transcribe", language="zh") # ២. ចងក្រងឃ្លាដែលនៅជិតគ្នា (Smart Merging) segments = transcribe['segments'] merged_segments = [] if segments: curr = segments[0] for next_seg in segments[1:]: # បើឃ្លាពីរនៅឆ្ងាយគ្នាលើសពី ០.៥ វិនាទី ចាំផ្ដាច់ឃ្លា if next_seg['start'] - curr['end'] < 0.5: curr['text'] += " " + next_seg['text'] curr['end'] = next_seg['end'] else: merged_segments.append(curr) curr = next_seg merged_segments.append(curr) # ៣. បង្កើតសំឡេងខ្មែរ video = VideoFileClip(VIDEO_PATH) audio_tracks = [video.audio.volumex(0.15)] # បន្ថយសំឡេងដើម print(f"🎙️ កំពុងដំណើរការ Dubbing លើ {len(merged_segments)} ឃ្លាធំៗ...") tasks = [generate_smooth_audio(s['text'], s['start'], s['end']-s['start']) for s in merged_segments] results = await asyncio.gather(*tasks) temp_files = [] for aud, path in results: if aud: audio_tracks.append(aud) temp_files.append(path) # ៤. រួមបញ្ចូលគ្នា និង Export final_audio = CompositeAudioClip(audio_tracks) final_video = video.set_audio(final_audio) final_video.write_videofile(OUTPUT_PATH, codec="libx264", audio_codec="aac") # សម្អាត File បណ្ដោះអាសន្ន for f in temp_files: if os.path.exists(f): os.remove(f) print(f"✅ ជោគជ័យ! វីដេអូបានកែសម្រួលឱ្យរលូនជាងមុនរួចរាល់៖ {OUTPUT_PATH}") await start_dubbing()
1 # ដំឡើងគ្រឿងបន្លាស់ដែលបាត់ (ម្ចាស់គ្រូត្រូវរត់អាហ្នឹងមុនគេ) !pip install openai-whisper edge-tts googletrans==4.0.0-rc1 moviepy==1.0.3 2 #@title 🪄 ម៉ាស៊ីនបកប្រែវីដេអូ - គ្រូអាគម AI import os # --- ផ្នែកបង្កើតប៊ូតុងសម្រាប់បញ្ចូលឈ្មោះ (Forms) --- Video_Name = "movie.mp4" #@param {type:"string"} Language = "Khmer" #@param ["Khmer", "English", "Chinese"] def create_project_folders(): folders = ['input_video', 'output_audio', 'final_result'] for folder in folders: if not os.path.exists(folder): os.makedirs(folder) print(f"✅ បង្កើត Folder: {folder} រួចរាល់!") else: print(f"📂 Folder: {folder} មានរួចហើយ។") if __name__ == "__main__": print(f"--- 🧙‍♂️ ចាប់ផ្ដើមរៀបចំសម្រាប់វីដេអូ: {Video_Name} ---") create_project_folders() # បង្ហាញផ្លូវដែលត្រូវដាក់វីដេអូឱ្យមិត្តភក្តិឃើញច្បាស់ៗ path = os.path.join('input_video', Video_Name) print(f"--- 👉 friend ត្រូវយកវីដេអូទៅដាក់ក្នុង: {path} ---") 3 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 = "PRO_AI_DUB_BM7.mp4" VIDEO_PATH = f"input_video/{Video_Name}" OUTPUT_PATH = f"final_result/CHARACTER_DUB_{Video_Name}" translator = Translator() # --- 🎙️ បញ្ជីសំឡេងតួអង្គ --- VOICES = { "MALE": "km-KH-PisethNeural", "FEMALE": "km-KH-SreymomNeural" } # --- 🧠 ម៉ាស៊ីនវិភាគតួអង្គ និងកែសម្រួលភាសា --- def identify_and_filter(text): # ១. បកប្រែជាមុនសិន raw_kh = translator.translate(text, src='zh-cn', dest='km').text # ២. កំណត់ភេទតួអង្គតាមរយៈពាក្យគន្លឹះ (Heuristic Detection) # បើមានពាក្យ "នាង" "ស្រី" "ព្រះនាង" យើងនឹងប្រើសំឡេងស្រី female_keywords = ['នាង', 'ស្រី', 'ព្រះនាង', 'អ្នកនាង', 'ម៉ាក់', 'បងស្រី', 'អូន'] gender = "MALE" if any(word in raw_kh for word in female_keywords): gender = "FEMALE" # ៣. កែសម្រួលពាក្យឱ្យសមជាតួអង្គក្នុងរឿង (Drama Style) corrections = { "អ្នក": "ឯង", "ខ្ញុំ": "យើង", "តើអ្នកកំពុងធ្វើអ្វី": "ឯងកំពុងធ្វើស្អី?", "ពិតជា": "ពិតមែនហើយ", "មិនអាច": "មិនបានទេ", "តើមានរឿងអ្វី": "មានរឿងអី?" } for old, new in corrections.items(): raw_kh = raw_kh.replace(old, new) return raw_kh.strip(), gender async def generate_character_audio(text, start, duration): try: kh_text, gender = identify_and_filter(text) if not kh_text: return None, None selected_voice = VOICES[gender] # កំណត់ Pitch ឱ្យខុសគ្នាបន្តិចៗតាមឃ្លា ដើម្បីកុំឱ្យសំឡេងដូចគ្នាច្រើនពេក pitch = "-1Hz" if gender == "MALE" else "+1Hz" tmp = f"tmp_{start}.mp3" communicate = edge_tts.Communicate(kh_text, selected_voice, rate="+7%", pitch=pitch) 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 Exception as e: print(f"Error: {e}") return None, None async def start_multi_dubbing(): # ១. ស្កែនវីដេអូ model = whisper.load_model("medium") print("🔍 កំពុងវិភាគសាច់រឿង និងតួអង្គ...") transcribe = model.transcribe(VIDEO_PATH, task="transcribe", language="zh") # ២. រៀបចំ Segment segments = transcribe['segments'] video = VideoFileClip(VIDEO_PATH) audio_tracks = [video.audio.volumex(0.15)] # ៣. បង្កើតសំឡេងតាមតួអង្គ print(f"🎬 កំពុងបញ្ចូលសំឡេងតួអង្គក្នុង {Video_Name}...") tasks = [generate_character_audio(s['text'], s['start'], s['end']-s['start']) for s in segments] results = await asyncio.gather(*tasks) temp_files = [] for aud, path in results: if aud: audio_tracks.append(aud) temp_files.append(path) # ៤. បញ្ចប់ការងារ final_audio = CompositeAudioClip(audio_tracks) final_video = video.set_audio(final_audio) final_video.write_videofile(OUTPUT_PATH, codec="libx264", audio_codec="aac") for f in temp_files: if os.path.exists(f): os.remove(f) print(f"✅ រួចរាល់! វីដេអូបំបែកសំឡេងតួអង្គ៖ {OUTPUT_PATH}") if __name__ == "__main__": await start_multi_dubbing()
 
Copyright © 2026. BM7//ANGKOR - All Rights Reserved
Template Created by ThemeXpose | BM7//ANGKOR