Zulko / moviepy

Video editing with Python
https://zulko.github.io/moviepy/
MIT License
12.09k stars 1.51k forks source link

Issue in writing Textclip in Hindi Language #2038

Open mondalayan96 opened 9 months ago

mondalayan96 commented 9 months ago

While writing the text clip for Hindi language the writing is getting changed.

Caption:  "ऐसी दुनिया में आपका स्वागत है जहां दृष्टि उद्देश्य से मिलती है।"
text_clip = TextClip(caption, fontsize=40, color="white", font="Tiro-Devanagari-Hindi", method='caption',
                                  size=(subtitle_width*0.94, subtitle_height*0.94)).set_duration(total_scene_duration-2*interval_time)

-->

Expected Behavior

Caption: ऐसी दुनिया में आपका स्वागत है जहां दृष्टि उद्देश्य से मिलती है।

Actual Behavior (see the 8th word)

image

Steps to Reproduce the Problem

def generate_scene(image_path, audio_path,
                   caption, scene_id,
                   account_id, video_title,
                   subtitle_position,
                   subtitle_font_style, subtitle_font_size,
                   subtitle_font_color, subtitle_bg_color,
                   interval_time, fps):
    """
    Generate a scene video for the specified scene.
    Parameters:
    :param scene_id: The ID of the scene to be generated.
    :param subtitle_position: The position of the subtitle.
    :param subtitle_font_style: The style of the subtitle.
    :param subtitle_font_size: The size of the subtitle.
    :param subtitle_font_color: The color of the subtitle.
    :param subtitle_bg_color: The background color of the subtitle.
    :param interval_time: The interval time between the video and the audio.
    Returns:
    None
    """
    print(caption)
    print("==========Ayan============",subtitle_font_style)
    # Load the image and audio clips
    image_clip = VideoFileClip(image_path)
    audio_clip = AudioFileClip(audio_path)
    audio_clip.fps = fps

    interval_multiplication = 1

    # Calculate the total duration of the scene
    audio_clip_duration = audio_clip.duration
    total_scene_duration = audio_clip_duration + interval_multiplication*interval_time

    # print("==========================")
    # print(f"Audio Duration: {audio_clip_duration}, Total:  {total_scene_duration},  Interval: {interval_time}")

    audio_clip.set_start(interval_time)
    audio_clip.set_end(interval_time + audio_clip_duration)

    # Set the duration of the image clip to match the total duration
    image_clip = image_clip.set_duration(total_scene_duration)

    # if subtitle_position == "left" or subtitle_position == "right":
    # Load the subtitle
    text_clip = TextClip(caption, fontsize=subtitle_font_size, color=subtitle_font_color,
                         font=subtitle_font_style, method='caption',
                         size=(subtitle_width*0.94, subtitle_height*0.94)).set_duration(total_scene_duration-2*interval_time)
    text_clip = text_clip.set_position(("center", "center"), relative=True)
    text_clip = text_clip.crossfadein(1)
    text_clip = text_clip.crossfadeout(1)
    text_clip.set_audio(None)
    text_clip.set_start(interval_time)
    text_clip.set_end(interval_time + text_clip.duration)

    # Create a color clip for the subtitle background
    color_clip = ColorClip(color=subtitle_bg_color, size=(subtitle_width, subtitle_height), duration=total_scene_duration)

    # Composite the color clip and text clip to create the subtitle clip
    subtitle_clip = CompositeVideoClip([color_clip.set_audio(None), text_clip.set_audio(None).set_start(interval_time)])
    # subtitle_clip = subtitle_clip.margin(1)

    # print(f"Audio Duration: {audio_clip.duration}, Image Clip: {image_clip.duration}, "
    #       f"Subtitle Clip: {subtitle_clip.duration}, Text Clip: {text_clip.duration}, ")

    if subtitle_position == "right":
        # Composite the image and subtitle clips
        combined_clip = clips_array([[image_clip, subtitle_clip]])
    if subtitle_position == "left":
        # Composite the subtitle and image clips
        combined_clip = clips_array([[subtitle_clip, image_clip]])
        # Create the composite clip with the combined clip
    composite_clip = CompositeVideoClip([combined_clip], size=(total_video_width, total_video_height))
    # else:
    #     # TODO: Need to do this, wrong implementation here
    #     # Load the subtitle
    #     text_clip = TextClip(caption, fontsize=35, color=subtitle_font_color,
    #                          font=subtitle_font_style, method='caption', stroke_color='black', kerning=1.5,
    #                          stroke_width=0.5, size=(subtitle_width, subtitle_height)).set_duration(total_scene_duration)
    #     text_clip = text_clip.set_position(("center", 0.85), relative=True)
    #     text_clip = text_clip.crossfadein(1)
    #     text_clip = text_clip.crossfadeout(1)

        # Composite the image and subtitle clips
        # combined_clip = clips_array([[image_clip, text_clip]])
        # Create the composite clip with the combined clip
        # composite_clip = CompositeVideoClip([image_clip, text_clip], size=(total_video_width, total_video_height))

    # Set the audio for the composite clip
    composite_clip = composite_clip.set_audio(CompositeAudioClip([audio_clip.set_start(interval_time)]))

    # Set the frames per second (fps) for the final video
    composite_clip.fps = fps

    # Export the final video
    scene_target_path = f"{local_scene_video_dir_path}/{account_id}_{video_title}/{scene_id}.mp4"
    # print(scene_target_path)
    # scene_path = f"{scene_target_path}/{scene_id}.mp4"
    composite_clip.write_videofile(scene_target_path, codec="libx264", audio_codec="aac", preset="ultrafast")

    # Close the clips
    text_clip.close()
    image_clip.close()
    audio_clip.close()
    # check if the position is left or right then only there will be subtitle clip
    if subtitle_position == "left" or subtitle_position == "right":
        subtitle_clip.close()
    combined_clip.close()
    composite_clip.close()

    return scene_target_path

Specifications

MoBanerjee commented 9 months ago

Can you kindly assign me this open issue? Thanks

sayanarijit commented 8 months ago

Facing this exact issue. Interesting to note that it's not only limited to moviepy. I have tried PIL and ffmpeg directly. The same problem persists.

sayanarijit commented 8 months ago

If we're willing to compromise on the choice of font, we can install a Hindi font (globally) and pass method="pango". It gets the job done. However, a more robust solution would be cool.

TheJimIT commented 3 weeks ago

I am also getting this issue but it is only on macOS. Same code gives expected output for Hindi fonts on Windows 11 but like above in macOS.