I'm trying to capture video from an Elikliv UVC microscope in Linux.
We can do direct frame-by-frame capture using this command:
v4l2-ctl --device /dev/video0 --stream-mmap --stream-to=stream.mjpg ... and I can see it live using this big crazy command:
v4l2-ctl --device /dev/video0 --stream-mmap --stream-to=/proc/self/fd/1 | \ ffmpeg -i - -fflags discardcorrupt -c:v copy -f matroska - | \ mpv --profile=low-latency - ..but I can't get it to work directly with V4L2-aware software (ie, MPV, VLC, OBS) without the help of v4l2-ctl to stream it into ffmpeg and then mpv.
Question:
Is there a way I can tell configure the V4L2 device to work in a "normal" way, directly from /dev/video0, without a big crazy pipe?
MPV says
# mpv /dev/video0 [lavf] avformat_open_input() failed Failed to recognize file format. VLC says
Your input can't be opened: VLC is unable to open the MRL 'v4l2:///dev/video0'. Check the log for details. [00007efbdc001120] v4l2 demux error: cannot set format: Input/output error [00007efbdc001120] v4l2 demux error: not a radio tuner device [00007efbdc003710] v4l2 stream error: cannot set format: Input/output error Other misc info:
# dmesg [ +0.078764] usb 1-4.3: New USB device found, idVendor=05e3, idProduct=f12b, bcdDevice= 1.00 [ +0.000019] usb 1-4.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0 [ +0.000008] usb 1-4.3: Product: GENERAL - UVC [ +0.000006] usb 1-4.3: Manufacturer: GENERAL [ +0.002536] usb 1-4.3: Found UVC 1.00 device GENERAL - UVC (05e3:f12b) [ +0.000287] usb 1-4.3: UVC non compliance - GET_DEF(PROBE) not supported. Enabling workaround. [ +5.549774] retire_capture_urb: 233 callbacks suppressed [ +5.000996] retire_capture_urb: 4991 callbacks suppressed [ +5.000956] retire_capture_urb: 4991 callbacks suppressed [ +5.001062] retire_capture_urb: 4991 callbacks suppressed ... <lots of these, 1000/sec> ... [ +3.438372] uvcvideo 1-4.3:1.1: Failed to query (130) UVC probe control : -32 (exp. 26). # v4l2-ctl --list-devices GENERAL - UVC : GENERAL - UVC (usb-0000:00:14.0-4.3): /dev/video0 /dev/video1 /dev/media0 # v4l2-ctl --list-formats -d /dev/video0 ioctl: VIDIOC_ENUM_FMT Type: Video Capture [0]: 'MJPG' (Motion-JPEG, compressed) # v4l2-ctl --list-formats -d /dev/video1 ioctl: VIDIOC_ENUM_FMT Type: Video Capture # v4l2-ctl --list-formats -d /dev/media0 Unable to detect what device /dev/media0 is, exiting. # v4l2-ctl -D -d /dev/video0 Driver Info: Driver name : uvcvideo Card type : GENERAL - UVC : GENERAL - UVC Bus info : usb-0000:00:14.0-4.3 Driver version : 6.7.6 Capabilities : 0x84a00001 Video Capture Metadata Capture Streaming Extended Pix Format Device Capabilities Device Caps : 0x04200001 Video Capture Streaming Extended Pix Format Media Driver Info: Driver name : uvcvideo Model : GENERAL - UVC : GENERAL - UVC Serial : Bus info : usb-0000:00:14.0-4.3 Media version : 6.7.6 Hardware revision: 0x00000100 (256) Driver version : 6.7.6 Interface Info: ID : 0x03000002 Type : V4L Video Entity Info: ID : 0x00000001 (1) Name : GENERAL - UVC : GENERAL - UVC Function : V4L2 I/O Flags : default Pad 0x01000007 : 0: Sink Link 0x02000010: from remote pad 0x100000a of entity 'Processing 5': Data, Enabled, Immutable # v4l2-ctl -D -d /dev/video1 Driver Info: Driver name : uvcvideo Card type : GENERAL - UVC : GENERAL - UVC Bus info : usb-0000:00:14.0-4.3 Driver version : 6.7.6 Capabilities : 0x84a00001 Video Capture Metadata Capture Streaming Extended Pix Format Device Capabilities Device Caps : 0x04a00000 Metadata Capture Streaming Extended Pix Format Media Driver Info: Driver name : uvcvideo Model : GENERAL - UVC : GENERAL - UVC Serial : Bus info : usb-0000:00:14.0-4.3 Media version : 6.7.6 Hardware revision: 0x00000100 (256) Driver version : 6.7.6 Interface Info: ID : 0x03000005 Type : V4L Video Entity Info: ID : 0x00000004 (4) Name : GENERAL - UVC : GENERAL - UVC Function : V4L2 I/O MPV Verbose output:
# mpv av://v4l2:/dev/video0 --profile=low-latency --untimed --demuxer-lavf-o=video_size=1280x720,input_format=mjpeg -v -v [cplayer] Command line options: 'av://v4l2:/dev/video0' '--profile=low-latency' '--untimed' '--demuxer-lavf-o=video_size=1280x720,input_format=mjpeg' '-v' '-v' [cplayer] mpv 0.35.1 Copyright © 2000-2023 mpv/MPlayer/mplayer2 projects [cplayer] built on UNKNOWN [cplayer] FFmpeg library versions: [cplayer] libavutil 57.28.100 [cplayer] libavcodec 59.37.100 [cplayer] libavformat 59.27.100 [cplayer] libswscale 6.7.100 [cplayer] libavfilter 8.44.100 [cplayer] libswresample 4.7.100 [cplayer] FFmpeg version: 5.1.3 [cplayer] [cplayer] Configuration: /usr/bin/waf configure --prefix=/usr --bindir=/usr/bin --libdir=/usr/lib64 --mandir=/usr/share/man --docdir=/usr/share/doc/mpv --confdir=/etc/mpv --disable-build-date --enable-libmpv-shared --enable-sdl2 --enable-libarchive --enable-dvdnav --enable-cdda --enable-html-build --enable-dvbin --enable-gl-x11 --enable-wayland [cplayer] List of enabled features: alsa asm av-channel-layout caca cdda cplayer cplugins cuda-hwaccel cuda-interop debug-build dmabuf-interop-gl dmabuf-interop-pl dmabuf-wayland drm drm-is-kms dvbin dvdnav egl egl-drm egl-helpers egl-x11 ffmpeg ffnvcodec gbm gbm.h gl gl-wayland gl-x11 glibc-thread-name glob glob-posix gpl iconv jack javascript jpeg jpegxl lcms2 libarchive libass libavdevice libbluray libdl libm libmpv-shared libplacebo librt linux-fstatfs linux-input-event-codes lua lua_5_1 memfd_create optimize pipewire plain-gl posix posix-or-mingw pthreads pulse rubberband rubberband-3 sdl2 sdl2-audio sdl2-gamepad sdl2-video shaderc shaderc-shared stdatomic uchardet vaapi vaapi-drm vaapi-egl vaapi-libplacebo vaapi-wayland vaapi-x-egl vaapi-x11 vapoursynth vdpau vdpau-gl-x11 vector vt.h vulkan wayland wayland-protocols wayland-protocols-1-24 x11 xv zimg zlib [global] config path: '' -> '/root/.config/mpv' [global] user path: '~~home/' -> '/root/.config/mpv' [global] user path: '~~old_home/' -> '/root/.mpv' [global] config path: 'encoding-profiles.conf' -/-> '/root/.config/mpv/encoding-profiles.conf' [global] config path: 'encoding-profiles.conf' -/-> '/root/.mpv/encoding-profiles.conf' [global] config path: 'encoding-profiles.conf' -> '/etc/mpv/encoding-profiles.conf' [cplayer] Reading config file /etc/mpv/encoding-profiles.conf [cplayer] Applying profile 'default'... [global] config path: 'mpv.conf' -/-> '/root/.config/mpv/mpv.conf' [global] config path: 'config' -/-> '/root/.config/mpv/config' [global] config path: 'mpv.conf' -/-> '/root/.mpv/mpv.conf' [global] config path: 'config' -/-> '/root/.mpv/config' [global] config path: 'mpv.conf' -/-> '/etc/mpv/mpv.conf' [global] config path: 'config' -/-> '/etc/mpv/config' [cplayer] Setting option 'profile' = 'low-latency' (flags = 8) [cplayer] Applying profile 'low-latency'... [cplayer] Setting option 'audio-buffer' = '0' (flags = 12) [cplayer] Setting option 'vd-lavc-threads' = '1' (flags = 12) [cplayer] Setting option 'cache-pause' = 'no' (flags = 12) [cplayer] Setting option 'demuxer-lavf-o-add' = 'fflags=+nobuffer' (flags = 12) [cplayer] Setting option 'demuxer-lavf-probe-info' = 'nostreams' (flags = 12) [cplayer] Setting option 'demuxer-lavf-analyzeduration' = '0.1' (flags = 12) [cplayer] Setting option 'video-sync' = 'audio' (flags = 12) [cplayer] Setting option 'interpolation' = 'no' (flags = 12) [cplayer] Setting option 'video-latency-hacks' = 'yes' (flags = 12) [cplayer] Setting option 'stream-buffer-size' = '4k' (flags = 12) [cplayer] Setting option 'untimed' = '' (flags = 8) [cplayer] Setting option 'demuxer-lavf-o' = 'video_size=1280x720,input_format=mjpeg' (flags = 8) [cplayer] Setting option 'v' = '' (flags = 8) [cplayer] Setting option 'v' = '' (flags = 8) [global] config path: 'input.conf' -/-> '/root/.config/mpv/input.conf' [global] config path: 'input.conf' -/-> '/root/.mpv/input.conf' [global] config path: 'input.conf' -/-> '/etc/mpv/input.conf' [osc] Loading lua script @osc.lua... [ytdl_hook] Loading lua script @ytdl_hook.lua... [stats] Loading lua script @stats.lua... [console] Loading lua script @console.lua... [osc] loading mp.defaults [auto_profiles] Loading lua script @auto_profiles.lua... [ytdl_hook] loading mp.defaults [global] config path: 'scripts' -/-> '/root/.config/mpv/scripts' [stats] loading mp.defaults [global] config path: 'scripts' -/-> '/root/.mpv/scripts' [global] config path: 'scripts' -/-> '/etc/mpv/scripts' [cplayer] Waiting for scripts... [auto_profiles] loading mp.defaults [console] loading mp.defaults [osc] loading @osc.lua [stats] loading @stats.lua [auto_profiles] loading @auto_profiles.lua [console] loading @console.lua [auto_profiles] Exiting... [console] reading options for console [global] config path: 'script-opts/console.conf' -/-> '/root/.config/mpv/script-opts/console.conf' [global] config path: 'script-opts/console.conf' -/-> '/root/.mpv/script-opts/console.conf' [global] config path: 'script-opts/console.conf' -/-> '/etc/mpv/script-opts/console.conf' [console] script-opts/console.conf not found. [global] config path: 'lua-settings/console.conf' -/-> '/root/.config/mpv/lua-settings/console.conf' [global] config path: 'lua-settings/console.conf' -/-> '/root/.mpv/lua-settings/console.conf' [global] config path: 'lua-settings/console.conf' -/-> '/etc/mpv/lua-settings/console.conf' [console] lua-settings/console.conf not found. [stats] reading options for stats [global] config path: 'script-opts/stats.conf' -/-> '/root/.config/mpv/script-opts/stats.conf' [global] config path: 'script-opts/stats.conf' -/-> '/root/.mpv/script-opts/stats.conf' [global] config path: 'script-opts/stats.conf' -/-> '/etc/mpv/script-opts/stats.conf' [stats] script-opts/stats.conf not found. [global] config path: 'lua-settings/stats.conf' -/-> '/root/.config/mpv/lua-settings/stats.conf' [global] config path: 'lua-settings/stats.conf' -/-> '/root/.mpv/lua-settings/stats.conf' [global] config path: 'lua-settings/stats.conf' -/-> '/etc/mpv/lua-settings/stats.conf' [stats] lua-settings/stats.conf not found. [ytdl_hook] loading @ytdl_hook.lua [global] config path: 'fonts' -/-> '/root/.config/mpv/fonts' [global] config path: 'fonts' -/-> '/root/.mpv/fonts' [global] config path: 'fonts' -/-> '/etc/mpv/fonts' [osd/libass] ASS library version: 0x1701000 (runtime 0x1701000) [osd/libass] libass API version: 0x1701000 [osd/libass] libass source: tarball: 0.17.1 [osd/libass] Shaper: FriBidi 1.0.10 (SIMPLE) HarfBuzz-ng 2.7.4 (COMPLEX) [global] config path: 'subfont.ttf' -/-> '/root/.config/mpv/subfont.ttf' [global] config path: 'subfont.ttf' -/-> '/root/.mpv/subfont.ttf' [global] config path: 'subfont.ttf' -/-> '/etc/mpv/subfont.ttf' [global] config path: 'fonts.conf' -/-> '/root/.config/mpv/fonts.conf' [global] config path: 'fonts.conf' -/-> '/root/.mpv/fonts.conf' [global] config path: 'fonts.conf' -/-> '/etc/mpv/fonts.conf' [osd/libass] Setting up fonts... [ytdl_hook] reading options for ytdl_hook [global] config path: 'script-opts/ytdl_hook.conf' -/-> '/root/.config/mpv/script-opts/ytdl_hook.conf' [global] config path: 'script-opts/ytdl_hook.conf' -/-> '/root/.mpv/script-opts/ytdl_hook.conf' [global] config path: 'script-opts/ytdl_hook.conf' -/-> '/etc/mpv/script-opts/ytdl_hook.conf' [ytdl_hook] script-opts/ytdl_hook.conf not found. [global] config path: 'lua-settings/ytdl_hook.conf' -/-> '/root/.config/mpv/lua-settings/ytdl_hook.conf' [global] config path: 'lua-settings/ytdl_hook.conf' -/-> '/root/.mpv/lua-settings/ytdl_hook.conf' [global] config path: 'lua-settings/ytdl_hook.conf' -/-> '/etc/mpv/lua-settings/ytdl_hook.conf' [ytdl_hook] lua-settings/ytdl_hook.conf not found. [osc] reading options for osc [global] config path: 'script-opts/osc.conf' -/-> '/root/.config/mpv/script-opts/osc.conf' [global] config path: 'script-opts/osc.conf' -/-> '/root/.mpv/script-opts/osc.conf' [global] config path: 'script-opts/osc.conf' -/-> '/etc/mpv/script-opts/osc.conf' [osc] script-opts/osc.conf not found. [global] config path: 'lua-settings/osc.conf' -/-> '/root/.config/mpv/lua-settings/osc.conf' [global] config path: 'lua-settings/osc.conf' -/-> '/root/.mpv/lua-settings/osc.conf' [global] config path: 'lua-settings/osc.conf' -/-> '/etc/mpv/lua-settings/osc.conf' [osc] lua-settings/osc.conf not found. [osd/libass] Using font provider fontconfig [osd/libass] Done. [cplayer] Run command: define-section, flags=64, args=[name="input_stats", contents="", flags="default"] [cplayer] Run command: enable-section, flags=64, args=[name="input_stats", flags="allow-hide-cursor+allow-vo-dragging"] [cplayer] Run command: define-section, flags=64, args=[name="input_forced_stats", contents="", flags="force"] [cplayer] Run command: enable-section, flags=64, args=[name="input_forced_stats", flags="allow-hide-cursor+allow-vo-dragging"] [cplayer] Run command: define-section, flags=64, args=[name="input_console", contents="", flags="default"] [cplayer] Run command: enable-section, flags=64, args=[name="input_console", flags="allow-hide-cursor+allow-vo-dragging"] [cplayer] Run command: define-section, flags=64, args=[name="input_forced_console", contents="", flags="force"] [cplayer] Run command: enable-section, flags=64, args=[name="input_forced_console", flags="allow-hide-cursor+allow-vo-dragging"] [cplayer] Run command: define-section, flags=64, args=[name="showhide", contents="mouse_move script-binding osc/__keybinding1\nmouse_leave script-binding osc/__keybinding2\n", flags="force"] [cplayer] Run command: define-section, flags=64, args=[name="showhide_wc", contents="mouse_move script-binding osc/__keybinding3\nmouse_leave script-binding osc/__keybinding4\n", flags="force"] [cplayer] Run command: enable-section, flags=64, args=[name="showhide", flags="allow-hide-cursor+allow-vo-dragging"] [cplayer] Run command: enable-section, flags=64, args=[name="showhide_wc", flags="allow-hide-cursor+allow-vo-dragging"] [cplayer] Run command: define-section, flags=64, args=[name="input", contents="mbtn_left script-binding osc/__keybinding5\nshift+mbtn_left script-binding osc/__keybinding6\nmbtn_right script-binding osc/__keybinding7\nmbtn_mid script-binding osc/__keybinding8\nwheel_up script-binding osc/__keybinding9\nwheel_down script-binding osc/__keybinding10\nmbtn_left_dbl ignore\nshift+mbtn_left_dbl ignore\nmbtn_right_dbl ignore\n", flags="force"] [cplayer] Run command: enable-section, flags=64, args=[name="input", flags=""] [cplayer] Run command: define-section, flags=64, args=[name="window-controls", contents="mbtn_left script-binding osc/__keybinding11\n", flags="force"] [cplayer] Run command: enable-section, flags=64, args=[name="window-controls", flags=""] [cplayer] Run command: change-list, flags=64, args=[name="shared-script-properties", operation="append", value="osc-visibility=auto"] [cplayer] Set property: shared-script-properties -> 1 [cplayer] Run command: disable-section, flags=64, args=[name="input"] [cplayer] Run command: disable-section, flags=64, args=[name="window-controls"] [cplayer] Run command: change-list, flags=64, args=[name="shared-script-properties", operation="append", value="osc-margins=0.000000,0.000000,0.000000,0.000000"] [cplayer] Set property: shared-script-properties -> 1 [cplayer] Done loading scripts. [global] config path: 'watch_later' -> '/root/.config/mpv/watch_later' [cplayer] Running hook: ytdl_hook/on_load [ytdl_hook] ytdl:// hook [ytdl_hook] not a ytdl:// url [cplayer] Run command: change-list, flags=64, args=[name="shared-script-properties", operation="append", value="osc-margins=0.000000,0.000000,0.000000,0.000000"] [avdevice] Opening av://v4l2:/dev/video0 [avdevice] resize stream to 4096 bytes, drop 0 bytes [cplayer] Set property: shared-script-properties -> 1 [osc] osc_init [avdevice] Stream opened successfully. [demux] Trying demuxers for level=request. [demux] Trying demuxer: lavf (force-level: request) [cplayer] Run command: change-list, flags=64, args=[name="shared-script-properties", operation="append", value="osc-margins=0.000000,0.000000,0.000000,0.000000"] [cplayer] Set property: shared-script-properties -> 1 [global] config path: 'fonts' -/-> '/root/.config/mpv/fonts' [global] config path: 'fonts' -/-> '/root/.mpv/fonts' [global] config path: 'fonts' -/-> '/etc/mpv/fonts' [osd/libass] ASS library version: 0x1701000 (runtime 0x1701000) [osd/libass] libass API version: 0x1701000 [osd/libass] libass source: tarball: 0.17.1 [lavf] Found 'video4linux2,v4l2' at score=100 size=0 (forced). [osd/libass] Shaper: FriBidi 1.0.10 (SIMPLE) HarfBuzz-ng 2.7.4 (COMPLEX) [global] config path: 'subfont.ttf' -/-> '/root/.config/mpv/subfont.ttf' [global] config path: 'subfont.ttf' -/-> '/root/.mpv/subfont.ttf' [global] config path: 'subfont.ttf' -/-> '/etc/mpv/subfont.ttf' [global] config path: 'fonts.conf' -/-> '/root/.config/mpv/fonts.conf' [global] config path: 'fonts.conf' -/-> '/root/.mpv/fonts.conf' [global] config path: 'fonts.conf' -/-> '/etc/mpv/fonts.conf' [osd/libass] Setting up fonts... [ffmpeg/demuxer] video4linux2,v4l2: fd:6 capabilities:84a00001 [lavf] avformat_open_input() failed [cplayer] Opening failed or was aborted: av://v4l2:/dev/video0 [osd/libass] Using font provider fontconfig [osd/libass] Done. [cplayer] Running hook: ytdl_hook/on_load_fail [ytdl_hook] full hook [cplayer] Run command: define-section, flags=64, args=[name="input_osc", contents="", flags="default"] [cplayer] Run command: enable-section, flags=64, args=[name="input_osc", flags="allow-hide-cursor+allow-vo-dragging"] [cplayer] Run command: define-section, flags=64, args=[name="input_forced_osc", contents="", flags="force"] [cplayer] Run command: enable-section, flags=64, args=[name="input_forced_osc", flags="allow-hide-cursor+allow-vo-dragging"] [cplayer] finished playback, unrecognized file format (reason 4) [cplayer] Failed to recognize file format. [cplayer] [cplayer] Exiting... (Errors when loading file) [ytdl_hook] Exiting... [cplayer] Run command: change-list, flags=64, args=[name="shared-script-properties", operation="remove", value="osc-margins"] [cplayer] Set property: shared-script-properties -> 1 [stats] Exiting... [console] Exiting... [osc] Exiting...