0

I am looking for a good and simple solution to record both audio and video from my Logitech webcam using python.
I tried using ffmpeg but I can't get it to work well.
also, I am using this on windows so the solution should work on windows.

dahan raz
  • 332
  • 2
  • 7
  • Is there a reason you haven't tried `cv2` (considering it's the top result when Googling "python record webcam", and even returns a code example on the search page)? – Grismar Dec 13 '20 at 22:54
  • cv2 for itself cannot record sound, so they use pyaudio as well, and then it's getting complicated and very slow... – dahan raz Dec 13 '20 at 22:55
  • Does this answer your question? [How to capture a video (AND audio) in python, from a camera (or webcam)](https://stackoverflow.com/questions/14140495/how-to-capture-a-video-and-audio-in-python-from-a-camera-or-webcam) – Grismar Dec 13 '20 at 23:07

2 Answers2

1

Use ffmpeg.

List devices using dshow (DirectShow) input:

ffmpeg -list_devices true -f dshow -i dummy

Example command to capture video and audio:

ffmpeg -f dshow -i video="Camera name here":audio="Microphone name here" -vf format=yuv420p output.mp4

See dshow documentation and FFmpeg Wiki: DirectShow for more info and examples.

llogan
  • 87,794
  • 21
  • 166
  • 190
0

As mentioned above, there is a solution from JRodrigoF that uses openCV to record video and pyaudio to record audio. I used it for a while on a project; however, I noticed that sometimes the threads would hang and it would cause the program to crash. Another issue is that openCV does not capture video frames at a reliable rate and ffmpeg would distort the video when re-encoding.

I came up with a new solution that records much more reliably and with much higher quality. However, it will only work on Windows because it uses pywinauto and the built-in Windows Camera app. The last bit of the script does some error-checking to confirm the video successfully recorded by checking the timestamp of the name of the video.

https://gist.github.com/mjdargen/956cc968864f38bfc4e20c9798c7d670

import pywinauto
import time
import subprocess
import os
import datetime

def win_record(duration):
    subprocess.run('start microsoft.windows.camera:', shell=True)  # open camera app

    # focus window by getting handle using title and class name
    # subprocess call opens camera and gets focus, but this provides alternate way
    # t, c = 'Camera', 'ApplicationFrameWindow'
    # handle = pywinauto.findwindows.find_windows(title=t, class_name=c)[0]
    # # get app and window
    # app = pywinauto.application.Application().connect(handle=handle)
    # window = app.window(handle=handle)
    # window.set_focus()  # set focus
    time.sleep(2)  # have to sleep

    # take control of camera window to take video
    desktop = pywinauto.Desktop(backend="uia")
    cam = desktop['Camera']
    # cam.print_control_identifiers()
    # make sure in video mode
    if cam.child_window(title="Switch to Video mode", auto_id="CaptureButton_1", control_type="Button").exists():
        cam.child_window(title="Switch to Video mode", auto_id="CaptureButton_1", control_type="Button").click()
    time.sleep(1)
    # start then stop video
    cam.child_window(title="Take Video", auto_id="CaptureButton_1", control_type="Button").click()
    time.sleep(duration+2)
    cam.child_window(title="Stop taking Video", auto_id="CaptureButton_1", control_type="Button").click()

    # retrieve vids from camera roll and sort
    dir = 'C:/Users/michael.dargenio/Pictures/Camera Roll'
    all_contents = list(os.listdir(dir))
    vids = [f for f in all_contents if "_Pro.mp4" in f]
    vids.sort()
    vid = vids[-1]
    # compute time difference
    vid_time = vid.replace('WIN_', '').replace('_Pro.mp4', '')
    vid_time = datetime.datetime.strptime(vid_time, '%Y%m%d_%H_%M_%S')
    now = datetime.datetime.now()
    diff = now - vid_time
    # time different greater than 2 minutes, assume something wrong & quit
    if diff.seconds > 120:
        quit()
    
    subprocess.run('Taskkill /IM WindowsCamera.exe /F', shell=True)  # close camera app
    print('Recorded successfully!')

win_record(2)
mjdargen
  • 51
  • 3