Skip to content

Instantly share code, notes, and snippets.

@ktosiu
Forked from docPhil99/ffmpeg_stream.md
Created August 25, 2020 09:11
Show Gist options
  • Save ktosiu/37f26912635945278486f617be785ae6 to your computer and use it in GitHub Desktop.
Save ktosiu/37f26912635945278486f617be785ae6 to your computer and use it in GitHub Desktop.
Streaming FFmpeg and Python

This is running on Linux Mint

  1. Install ffmpeg
sudo apt-get install ffmpeg
  1. A simple test: open two terminals, in first run ffplay udp://127.0.0.1:23000 and in the second ffmpeg -i sample.mp4 -vcodec mpeg4 -f mpegts udp://127.0.0.1:23000 . This should play the video sample.mp4 although the quality is rather blocky.
  2. The command line format is ffpeg [global options] {[input options] -i input_url} {[output options] output_url}. So here we have no input options, and -vcodec mpeg4 -f mpegts as output options. Tip: Adding -v 0 to ffmpeg sets the global log level to zero. By default, ffmpeg can be rather verbose.
  3. -vcodec mpeg4 sets the ouput codec to Mpeg4 part 2, we can improve on this with Mpeg4 part 10 or H.264. Change it to -vcodec libx264. -f mpegts forces the output format to be mpegts. Usually, this option is not needed since it can be guessed for the output file extension. However, we have not specified one here.
  4. Add -re to stream files at their native rate. Otherwise, they will play too fast.
  5. Add -b:v 500k or a higher number to the output options to control the bitrate. Or you can try -crf 30. This sets the Content Rate Factor. That's an x264 argument that tries to keep reasonably consistent video quality, while varying bitrate A value of 30 allows somewhat lower quality and bit rate.

Complete list of options - offsite

  1. With udp we still get lost packets. Instead try rtsp over tcp ffmpeg -stream_loop 5 -re -i OxfordStreet.avi -vf scale=320:240 -vcodec libx264 -f rtsp -rtsp_transport tcp rtsp://127.0.0.1:23000/live.sdp 8 To read this in python:
import numpy as np
import cv2
import ffmpeg  #ffmpeg-python
in_file='rtsp://127.0.0.1:23000/live.sdp?tcp'#?overrun_nonfatal=1?buffer_size=10000000?fifo_size=100000'
# ffmpeg -stream_loop 5 -re -i OxfordStreet.avi -vcodec libx264 -f rtsp -rtsp_transport tcp rtsp://127.0.0.1:23000/live.sdp

width = 320
height = 240
cv2.namedWindow("test")

process1 = (
    ffmpeg
    .input(in_file,rtsp_flags= 'listen')
    .output('pipe:', format='rawvideo', pix_fmt='bgr24')
    .run_async(pipe_stdout=True)
)
while True:
    in_bytes = process1.stdout.read(width * height * 3)
    if not in_bytes:
        break
    in_frame = (
        np
        .frombuffer(in_bytes, np.uint8)
        .reshape([height, width, 3])
    )
    cv2.imshow("test", in_frame)
    cv2.waitKey(10)

process1.wait()

See Also

@ashiskumarsahu
Copy link

Hi @ktosiu,
Is this possible to take multiple mpegts input from ffmpeg like bit-rate specific and pass it to a third party program. What I want to achieve is:

ffmpeg -i original.mkv -c:v h264 -c:a aac -f mpegts - | myprogam \\ -c:v h264 -c:a aac -vf "scale=1280:720" -f mpegts - | myprogam \\ -c:v h264 -c:a aac -vf "scale=854:480" -f mpegts - | myprogam \\
This command will not work but can explain my requirement. Is there any alternative to do this with a single command.
I tried python threading but in that case I have to run multiple ffmpeg command.

Any help is highly appreciated.

Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment