China Movies Speak Khmer.
May 03, 2026
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()
- Blogger Comment
- Facebook Comment
0 comments:
Post a Comment