3

I'm trying to record webcam video from python using ffmpeg. The following ffmpeg works properly when run from the cmd

ffmpeg -f dshow -rtbufsize 2000M -i video="HP HD Camera":audio="Headset (realme Buds Wireless 2 Neo Hands-Free AG Audio)" -y -vcodec libx264 -crf 24 output.mp4 

I have checked the audio and video inputs with

ffmpeg -list_devices true -f dshow -i dummy

Now when I try to call the command using subprocess problem happens. I can just pass the whole command like this

import subprocess, time
recorder = subprocess.Popen('ffmpeg -f dshow -rtbufsize 2000M -i video="HP HD Camera":audio="Headset (realme Buds Wireless 2 Neo Hands-Free AG Audio)" -y -vcodec libx264 -crf 24 output.mp4', shell=True)
time.sleep(10)
recorder.terminate()
recorder.kill()

Now, as this is run with shell=True this won't terminate the recording and I have checked different solution, but they won't work either. So, I opted for shell=False. I tried with

recorder = subprocess.Popen(['ffmpeg', '-f', 'dshow', '-rtbufsize', '2000M', '-t', '60', '-i', 'video="HP HD Camera":audio="Headset (realme Buds Wireless 2 Neo Hands-Free AG Audio)"', '-y', '-vcodec', 'libx264', '-crf', '24', 'output.mp4'],shell=False)

This throws the error

[dshow @ 0000024f2becd540] Could not find video device with name ["HP HD Camera"] among source devices of type video.
video="HP HD Camera":audio="Headset (realme Buds Wireless 2 Neo Hands-Free AG Audio)": I/O error

Then, I tried

recorder = subprocess.Popen(['ffmpeg', '-f', 'dshow', '-rtbufsize', '2000M', '-t', '60', '-i', 'video=HP HD Camera:audio=Headset (realme Buds Wireless 2 Neo Hands-Free AG Audio)', '-y', '-vcodec', 'libx264', '-crf', '24', 'output.mp4'],shell=False)

This creates the output, but the video is not playable.
How to fix this?

1 Answer 1

6

We may add double quotes for letting Python subprocess know the string is one argument, and we have to close FFmpeg gracefully.

Adding double quotes:
Replace the following part video="HP HD Camera":audio="Headset (realme Buds Wireless 2 Neo Hands-Free AG Audio)" with:
"video=""HP HD Camera"":audio=""Headset (realme Buds Wireless 2 Neo Hands-Free AG Audio)"""
Doubling the quotes "" is required because " is between quotes " ... ".

We may also use it without the "": "video=HP HD Camera:audio=Headset (realme Buds Wireless 2 Neo Hands-Free AG Audio)".


For getting a playable file, we have to close FFmpeg gracefully.
For simply recording 10 seconds, we may add -t 10 argument.

For closing FFmpeg gracefully programmatically, we may write 'q'.encode("GBK") to stdin pipe of FFmpeg sub-process.
Writing q simulates that q key is pressed by the user (stop recording).

  • Add stdin=subprocess.PIPE argument to subprocess.Popen.

  • After time.sleep(10) add:

     recorder.stdin.write('q'.encode("GBK"))  # Simulate user pressing q key
     recorder.communicate()
    
  • Add recorder.wait() (instead of recorder.terminate() and recorder.kill()).


As good practice we may also add shlex.split(...) for converting the command line to a list of arguments.
In Windows it supposed to work without it, but in Linux it's not.

Code sample:

import subprocess, time, shlex

recorder = subprocess.Popen(shlex.split('ffmpeg -f dshow -rtbufsize 2000M -t 60 -i """video=HP HD Camera:audio=Headset (realme Buds Wireless 2 Neo Hands-Free AG Audio)"":""audio=Headset (realme Buds Wireless 2 Neo Hands-Free AG Audio)"""'
                                        ' -y -vcodec libx264 -crf 24 output.mp4'), stdin=subprocess.PIPE, shell=False)

time.sleep(10)

recorder.stdin.write('q'.encode("GBK"))  # Simulate user pressing q key
recorder.communicate()
recorder.wait()
Sign up to request clarification or add additional context in comments.

3 Comments

gracefully closing solved my problem. Thanks
I need to know one thing,ifyou can help. this ffmpeg command write the whole video at when the command is closed/completed. Is there a way to write the buffer continuously to the disk?
Take a look at this post. I don't know if it's working... Windows may update the file size only when it is closed. What is the purpose?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.