Search code examples
pythonphplaravelmoviepy

How can I send Subtitle Text to Python with Php Laravel?


I would like to send subtitle text from php controller to python program that create video with subtitles using movipy library. I managed to send subtitle text but subtitles only appear started of video. And the time & text informations didn't seperated properly with srt.parse function. I managed the created video from srt file but I would like to use text instead of file. Python program interpret whole posted text as a sentence like below. Can you give me an idea please for solving the problem?

[Subtitle(content=u'', index=None, proprietary='\\r\\n As someone with an AI background, \\r\\n\\r\\n 00:00:01,879 --> 00:00:04,277 \\r\\n I think you can probably explain to us', end=datetime.timedelta(0, 1, 879000), start=datetime.timedelta(0, 0, 319000))]

My php controller is below.

public function store()
{
    $str = <<<TEXT
                00:00:00,319 --> 00:00:01,879 As someone with an AI background, 00:00:01,879 --> 00:00:04,277 I think you can probably explain to us, 00:00:04,277 --> 00:00:06,916 you know, this whole hype of generative AI, right?   
            TEXT;
    $py_output = exec('python C:\\xampp\\htdocs\\xampp...\\main.py ' . json_encode($str) . '');
    var_dump($py_output);
    return view('videotest.store');
}

My main.py is below

import sys
from moviepy.editor import VideoFileClip, TextClip, CompositeVideoClip

textList = sys.argv[1]
subtitle_generator = srt.parse(textList)
subtitles = list(subtitle_generator)
mp4filename = "C:\\xampp\\htdocs\\xampp..\\myvideo.mp4"

def create_subtitle_clips(subtitles, videosize,fontsize=24, font='Arial', color='yellow', debug = False):
    subtitle_clips = []
    i = 0
    while subtitles[i:]:
        start_time = subtitles[i].start.seconds
        end_time = subtitles[i].end.seconds
        duration = end_time - start_time
        video_width, video_height = videosize
        text_clip = TextClip(subtitles[i].proprietary, fontsize=fontsize, font=font, color=color, bg_color = 'black',size=(video_width*3/4, None), method='caption').set_start(start_time).set_duration(duration)
        subtitle_x_position = 'center'
        subtitle_y_position = video_height* 4 / 5 
        text_position = (subtitle_x_position, subtitle_y_position)             
        subtitle_clips.append(text_clip.set_position(text_position))
        i = i + 1

    return subtitle_clips

video = VideoFileClip(mp4filename)

begin,end= mp4filename.split(".mp4")
output_video_file = begin+'_subtitled5'+".mp4"
subtitle_clips = create_subtitle_clips(subtitles,video.size)
final_video = CompositeVideoClip([video] + subtitle_clips)
final_video.write_videofile(output_video_file)

Solution

  • You need to ensure the subtitle text is correctly formatted and parsed into separate subtitles with their respective timings.

    Ensure your subtitle text is in a proper SRT format

    1
    00:00:00,500 --> 00:00:02,000
    Subtitle 1 text here.
    
    2
    00:00:02,500 --> 00:00:04,000
    Subtitle 2 text here.
    

    In Laravel properly escape and pass the subtitle text. You can use base64 encoding to ensure that newlines and other special characters are preserved when passing the string to Python.

    public function store()
    {
        $str = <<<TEXT
    1
    00:00:00,319 --> 00:00:01,879 As someone with an AI background,
    2
    00:00:01,879 --> 00:00:04,277 I think you can probably explain to us,
    3
    00:00:04,277 --> 00:00:06,916 you know, this whole hype of generative AI, right?
    TEXT;
        $encodedStr = base64_encode($str); // Encode the string
        $py_output = exec('python C:\\xampp\\htdocs\\xampp...\\main.py ' . escapeshellarg($encodedStr));
        var_dump($py_output);
        return view('videotest.store');
    }
    

    In your Python script, decode the input string before parsing it with srt.parse.

    import sys
    import base64
    import srt
    
    # Decode the input string
    encoded_text = sys.argv[1]
    decoded_text = base64.b64decode(encoded_text).decode('utf-8')
    
    subtitle_generator = srt.parse(decoded_text)
    subtitles = list(subtitle_generator)
    
    # your other code....