RUBICK
RUBICK

Reputation: 1

Combining Video and Audio Buffers in Memory Using FFmpeg and Python

I need to combine video and audio streams into a single MP4 file. My goal is to handle this entirely in memory and then send the resulting file directly to the user without storing any files on disk.

I am consistently facing problems with the FFmpeg process when trying to combine the video and audio streams

@bot.callback_query_handler(func=lambda call: call.data.startswith("download_mp4"))
def handle_download_mp4(call):
    itag, url = call.data.split("|")[1:]
    yt = YouTube(url)
    
    video_stream = yt.streams.get_by_itag(itag)
    audio_stream = yt.streams.filter(only_audio=True).first()

    video_buffer = io.BytesIO()
    audio_buffer = io.BytesIO()

    # downloading video and audio to memory
    video_stream.stream_to_buffer(video_buffer)
    audio_stream.stream_to_buffer(audio_buffer)

    video_buffer.seek(0)
    audio_buffer.seek(0)
    combined_buffer = io.BytesIO()

    process = None
    try:
        process = (
            ffmpeg
            .input('pipe:0')
            .input('pipe:1')
            .output('pipe:2', format='mp4', vcodec='libx264', acodec='aac')
            .run_async(pipe_stdin=True, pipe_stdout=True, pipe_stderr=True)
        )

        # video and audio buffers to ffmpeg stdin
        process.stdin.write(video_buffer.read())
        process.stdin.write(audio_buffer.read())
        process.stdin.close()

        combined_buffer.write(process.stdout.read())
        process.wait()
        combined_buffer.seek(0)
        
    except Exception as e:
        bot.send_message(call.message.chat.id, f"Error during processing: {str(e)}")
        if process:
            process.kill()
        return

    file_size = combined_buffer.getbuffer().nbytes

    if file_size > MAX_FILE_SIZE:
        bot.send_message(call.message.chat.id, "The combined file is too large to download :(")
        combined_buffer.close()
        return

    # sending combined bufer to user
    bot.send_document(call.message.chat.id, combined_buffer, visible_file_name=f"{yt.title}.mp4")

Here's the workflow I'm aiming for:

1. Download video and audio streams from YouTube. 2. Combine these streams in memory using FFmpeg. 3. Send the combined MP4 file to the user.

Im using pytube to download the video and audio streams and ffmpeg to merge them. However, I'm encountering issues with the combination process. Specifically, I’m struggling with how to correctly handle merging the video and audio streams using in-memory buffers

Upvotes: 0

Views: 121

Answers (0)

Related Questions