0

I've made a telegram bot and basically, when you send a video to it, it downloads its edits and then sends it back (edited). I have made it work but when someone is editing a video, which is a subprocess Python script, then the whole bot pauses until the editing is done and continues as normal. I have then re-wrote my telegram bot to work asynchronously however now it doesn't even wait for the file to be downloaded. Therefore it cannot process the filehash and runs the entire editing script before the file has even downloaded. then it sends the video which doesn't exist because the editing script hasn't finished or anything and it just breaks my entire editing script and doesn't work. can anyone help? I can provide any code. here is where my editing function is being run.

                edit_video(message_text, f"{download_folder}/{str(chat_id)}/{profile}/{file_hash}.mp4", file_hash)
                download_path = f"./exported/{str(chat_id)}/{profile}/{file_hash}.mp4"

                await bot.send_video(chat_id=chat_id, video=open(download_path, 'rb'))

and this is the edit_video function

async def edit_video(title, the_hash, user_id):
    subprocess.run(["python", "./editor.py", profile, title, the_hash, str(user_id)])

I've tried putting the entire editing script inside the function instead but it still doesn't work.

corvusMidnight
  • 518
  • 1
  • 4
  • 19
Pady
  • 9
  • 2
  • Well, that's the tradeoff, isn't it? If you want the bot to stay responsive, then you have to allow the editing to run in the background, so your handler can return to the main loop. That means you will need some OTHER mechanism for sending the finished video back to the user, because the original message will already have been handled. Yes, it's complicated. – Tim Roberts Aug 27 '23 at 18:25
  • Does this answer your question? [How can I run an external command asynchronously from Python?](https://stackoverflow.com/questions/636561/how-can-i-run-an-external-command-asynchronously-from-python) – CallMeStag Aug 27 '23 at 18:37

1 Answers1

0

I've fixed the code!

I basically now have 2 functions 1 which actually does the whole subproccesing thing and the second which handles a queue system i've made.

Here is an insight into what i did in my subprocessing function.

async def run_external_script(user_id, profile, random_id, temp_download):
    script_path = r"G:\Code\video-maker\dev\editor.py"
    
    proc = await asyncio.create_subprocess_exec(
        sys.executable, script_path, str(user_id), str(profile), str(random_id), str(temp_download),
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE
    )

    stdout_bytes, stderr_bytes = await proc.communicate()

    # Decode stdout and stderr individually
    stdout_str = stdout_bytes.decode('utf-8')
    stderr_str = stderr_bytes.decode('utf-8')

    #print(stderr_str)

    output_lines = []
    for line in stdout_str.splitlines():
        output_lines.append(line.strip())

    await proc.wait()
    return output_lines

here is how called the function and recieved the download path once the editing process has finished

output = await run_external_script(user_id, profile, random_id, temp_download_path)
        if output:
            video_out = open(output[-1], "rb")
            await bot.send_video(chat_id=user_id, video=video_out)
        else:
            print("Output is empty")
Pady
  • 9
  • 2