2

I'm trying to stream FFmpeg with audio.
I will show my code below:


Import module

import subprocess as sp

Create variables

rtmpUrl = "rtmp://a.rtmp.youtube.com/live2/key"
camera_path = "BigBuckBunny.mp4"
cap = cv.VideoCapture(camera_path)

# Get video information
fps = int(cap.get(cv.CAP_PROP_FPS))
width = int(cap.get(cv.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv.CAP_PROP_FRAME_HEIGHT))

Command param

# ffmpeg command
command = ['ffmpeg',
        '-y',
        '-f', 'rawvideo',
        '-vcodec','rawvideo',
        '-pix_fmt', 'bgr24',
        '-s', "{}x{}".format(width, height),
        '-r', str(fps),
        '-i', '-',
        '-c:v', 'libx264',
        '-pix_fmt', 'yuv420p',
        '-preset', 'ultrafast',
        '-f', 'flv', 
        rtmpUrl]

Create subprocess to ffmpeg command

# Pipeline configuration
p = sp.Popen(command, stdin=sp.PIPE)

Send frame to RTMP server

# read webcamera
while(cap.isOpened()):
    ret, frame = cap.read()
    if not ret:
        print("Opening camera is failed")
        break

    # write to pipe
    p.stdin.write(frame.tobytes())

I hope you can help me to be able to live stream via FFmpeg over RTMP with audio. Thanks!

KevinTran
  • 25
  • 9
  • 1
    OpenCV is only supplying video. Add the mp4 as a direct input to ffmpeg i.e. `-vn -i BigBuckBunny.mp4` – Gyan Dec 24 '21 at 12:32

1 Answers1

2

Assuming you actually need to use OpenCV for the video, you have to add the audio directly to FFmpeg as Gyan commented, because OpenCV does not support audio.

-re argument is probably required for live streaming.


For testing, I modified the RTMP URL from YouTube to localhost.
FFplay sub-process is used for capturing the stream (for testing).

Complete code sample:

import subprocess as sp
import cv2

#rtmpUrl = "rtmp://a.rtmp.youtube.com/live2/key"
rtmp_url = "rtmp://127.0.0.1:1935/live/test"  # Use localhost for testing
camera_path = "BigBuckBunny.mp4"
cap = cv2.VideoCapture(camera_path)

# Get video information
fps = int(cap.get(cv2.CAP_PROP_FPS))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

# Start the TCP server first, before the sending client (for testing).
ffplay_process = sp.Popen(['ffplay', '-listen', '1', '-i', rtmp_url])  # Use FFplay sub-process for receiving the RTMP video.

# ffmpeg command
# OpenCV does not support audio.
command = ['ffmpeg',
        '-y',
        '-re', # '-re' is requiered when streaming in "real-time"
        '-f', 'rawvideo',
        #'-thread_queue_size', '1024',  # May help https://stackoverflow.com/questions/61723571/correct-usage-of-thread-queue-size-in-ffmpeg
        '-vcodec','rawvideo',
        '-pix_fmt', 'bgr24',
        '-s', "{}x{}".format(width, height),
        '-r', str(fps),
        '-i', '-',
        '-vn', '-i', camera_path,  # Get the audio stream without using OpenCV
        '-c:v', 'libx264',
        '-pix_fmt', 'yuv420p',
        '-preset', 'ultrafast',
        # '-c:a', 'aac',  # Select audio codec
        '-bufsize', '64M',  # Buffering is probably required
        '-f', 'flv', 
        rtmp_url]

# Pipeline configuration
p = sp.Popen(command, stdin=sp.PIPE)

# read webcamera
while (cap.isOpened()):
    ret, frame = cap.read()
    if not ret:
        print("End of input file")
        break

    # write to pipe
    p.stdin.write(frame.tobytes())

p.stdin.close()  # Close stdin pipe
p.wait()

ffplay_process.kill()  # Forcefully close FFplay sub-process
Rotem
  • 30,366
  • 4
  • 32
  • 65
  • Thank you very much, but I have one more question. How can I get the microphone sound in FFmpeg? – KevinTran Dec 25 '21 at 10:29
  • Please do some research. You have to identify the device first. After that add the device after the '-i' – Rotem Dec 25 '21 at 12:50
  • Hello, I'm having a problem where the sound is coming out faster than the image frame and vice versa, so how do I fix it? – KevinTran Dec 25 '21 at 15:48
  • I think the '-re' supposed to fix it. Try to add '-re' twice - before each '-i'. If it's not working you may post a new question. – Rotem Dec 25 '21 at 17:07
  • "Microphone Array (Intel® Smart Sound Technology for Digital Microphones)" That is the name of my audio device; how do I add it to command? – KevinTran Dec 26 '21 at 03:15
  • For DirectShow device (in Windows)? You may look at the following [page](https://scribbleghost.net/2019/01/09/record-microphone-with-ffmpeg-in-windows/). For testing try: `ffmpeg -y -f dshow -i audio="Microphone Array (Intel® Smart Sound Technology for Digital Microphones)" -t 60 test.mp3` – Rotem Dec 26 '21 at 06:45
  • I add the following line in the command: '-i', 'audio="xxx"', and ffmpeg : audio="xxx": Invalid argument. so what's the correct way to make the command and pipe it in the while loop? Thanks. – ttkrpink May 11 '22 at 09:29
  • @ttkrpink I don't know, your question is out of context. – Rotem May 11 '22 at 11:16