Using ffmpeg-python to save Twitch video streams obtained via streamlink - getting bound method error

I’m trying to download Twitch videos using Python and running into issues with ffmpeg-python. Here’s my current approach:

import urllib.request
import streamlink
import ffmpeg

# Get the video stream URL
video_link = "https://www.twitch.tv/videos/783301562"
stream_data = streamlink.streams(video_link)['best'].url
print(stream_data)

# Download the m3u8 file
try:
    urllib.request.urlretrieve(stream_data, "downloaded_stream.m3u8")
except Exception as error:
    print(error)

# Try to convert using ffmpeg-python
conversion = (
    ffmpeg
    .input('downloaded_stream.m3u8')
    .output('final_video.mp4')
    .run
)
print(conversion)

The streamlink part works fine and gives me a working m3u8 URL. But when I try to use ffmpeg-python to convert it to mp4, I only get this weird output: <bound method run of output(filename='final_video.mp4')[None] <2606681a>> and no actual video file gets created.

I’ve tried both feeding the URL directly to ffmpeg and downloading the m3u8 file first, but both approaches give the same result. What am I missing here? How can I properly execute the ffmpeg conversion to get my mp4 file?

ClimbingLion nailed it, but there’s another issue with what you’re doing. You’re downloading the m3u8 file locally, but m3u8 files are just playlists - they point to video segments, they don’t actually contain video data. When you download only the playlist, ffmpeg can’t reach the video segments because they’re still sitting on the remote server. Skip downloading the m3u8 and just pass the stream URL straight to ffmpeg:

conversion = (
    ffmpeg
    .input(stream_data)
    .output('final_video.mp4')
    .run()
)

This way ffmpeg grabs all the segments from the playlist automatically. I’ve done this with tons of HLS streams and it handles all the downloading and stitching behind the scenes.

The fixes above nail the technical stuff, but you’ve got a bigger issue. Manual video downloads turn into a nightmare when you scale up or deal with different formats.

I’ve hit this same wall trying to grab content from multiple platforms regularly. What actually worked was building an automated pipeline that handles everything - stream detection, downloads, conversions, the whole thing.

Latenode makes this stupid easy. Set it to watch Twitch channels, auto-download new videos, run ffmpeg conversions, and sort your files. No more babysitting scripts or manual downloads.

Once it’s configured, it just works. I run similar automation for content processing and it saves me hours weekly. You can also build in error handling and retry logic that’s way more solid than your typical quick script.

Check out https://latenode.com - it’s perfect for this kind of media workflow stuff.

You’re missing the parentheses after .run - it should be .run() not just .run. Right now you’re just referencing the method instead of actually calling it. That’s why you see that bound method output instead of the conversion happening.

Heads up - Twitch VODs get chunked weirdly and can make ffmpeg spit out corrupted files even when it looks like everything worked. I’ve hit this with older VODs where the conversion finishes but the mp4 has sync issues or missing chunks.

Fix is adding -c copy to skip re-encoding and -bsf:a aac_adtstoasc for audio compatibility:

conversion = (
    ffmpeg
    .input(stream_data)
    .output('final_video.mp4', **{'c': 'copy', 'bsf:a': 'aac_adtstoasc'})
    .run()
)

This copies streams directly without transcoding - faster and dodges corruption from format mismatches. Only catch is you’re stuck with Twitch’s codec, but that’s fine for archiving.

Both answers are spot-on for the technical fixes, but I’ll throw in something from my own Twitch streaming experience. Even after you fix the .run() issue and pass the URL directly, you’ll probably hit problems with streams that need auth tokens or expire fast.

What saved me was adding error handling and timeout params to the ffmpeg call. These streams love to hang or crash halfway through, especially longer videos. Try options like -t for duration limits or -reconnect 1 to handle connection drops. Also check if the stream URL’s still valid before starting conversion - I’ve seen streamlink hand you a URL that works at first but dies before ffmpeg’s done with it.

Just adding that stream quality can cause issues too. Grabbing ‘best’ quality from streamlink usually means source quality - that’s massive and causes timeouts or memory problems. Use 720p or 480p instead of best if you hit problems, especially with long VODs. Saved me so many headaches downloading hour+ streams.