[Windows/Linux] GC553 的 Switch 完美采集之路

趁着假期摸了一块采集卡,准备在笔记本上愉快地莱莎2。本来基本已经放弃在 Linux 上玩耍了[1],但 Reddit 上的一篇帖子[2]重新勾起了我的兴趣。

正面照

帖子中的描述非常简单,好像楼主也并没有做太多的操作。但正是由于过于简单,导致后续的研究过程耗费了比较多的时间。

虽说是勾起的 Linux 下的兴趣,这篇文章中同样包含 Windows 下的部分配置内容。虽然 Windows 用得少,但不代表完全不用。Windows 下的采集非常简单,基本上可以说是完全无坑;Linux 下则是完全靠着摸索得到的方案,也算是收获颇丰吧(笑)

什么?你说 mac?你给我买一台我就写(逃

Windows

Windows 下有着官方的技术支持,过程非常简单,但我使用的并不是官方方案。一来官方方案需要额外下载软件,二是官方方案主要是为直播而生,对于直接在笔记本上使用并没有特别优化过。因此我最终选择了 PotPlayer

虽然它被钉在了耻辱柱上,但谁让它是真的香呢(悲)

PotPlayer 的主菜单中,选择「打开设备」,然后选中设备就可以了。视频输入一般是开箱即用,音频输入可能需要在下面的设置里调整一下,或者直接在 Windows 设置里把采集卡的音频输入设置成默认(?

总之就是这种不需要怎么说就能简单实现的平台

有空把这部分补补齐吧(懒

Linux

Linux 下的问题就相对复杂些了。由于官方没有提供任何 Linux 相关的技术支持,我们只能自己摸索。为了方便观察,下面的截图里使用了很多 grep 来产生高亮。

视频

首先需要解决的问题是视频源。我们插入 USB,看看 lsusb

设备成功显示。然后使用 v4l2-ctl 查看设备列表:

可以看到有两个 /dev/video,我暂且蒙在鼓里(

尝试:VLC

尝试使用 VLC 打开:

第一次打开发现提示了神秘的错误:

第二次出现了神秘的影像:

看起来要手动调整一下分辨率:

然而修改之后再尝试连接什么反应都没有了,非常神秘。重新开启 VLC,连之前的神秘影像都显示不出来了。拔掉 USB 重来,看来是不能指望 VLC 了。

尝试:OBS-Studio

OBSWindows 上的表现还是值得称道的,但在 Linux 下好像就不大行了……

不知道发生了什么事情,总之就是绿了。不大行(

尝试:mpv

mpv 在它的 Wiki 中有专门的一篇文章叙述 v4l2[3]。我们直接使用 Wiki 上提供的第一行命令:

mpv av://v4l2:/dev/video0 --profile=low-latency

然后就没有然后了,hmm……并且延迟非常可以,个人感觉比 Windows 下还低。完全没有问题了。

顺带一提,在 mpv 成功播放之后,OBS 它也可以了(

这合理吗

嘛,不管专门说,视频问题都解决了(

那么,音频……

解决完视频问题,问题就解决了一大半了。毕竟你可以直接把耳机接 NS 上(逃

音频在哪里?

我们先通过 pactl 来观察一下情况:

可以发现,音频源是作为一个输入设备接入的。通过 arecord 也可以看到:

同样是通过 arecord,获得设备的 ID

现在我们来尝试录制一下:

耳机里出现了熟悉的 BGM

mpv 播放视频+音频

同样是在那篇 Wiki 中,mpv 提供了和 v4l2 一起播放音频的方案:通过 --audio-file 指定音频文件为 pulseaudio 设备。

但这个方案在测试中发现并不能让 mpv 发出声音。文章最后的 untested suggestion 倒是可以播放音频,但发出声音的代价是视频的延迟激增到了 2 秒以上,并且伴随着极低的 FPS。这条路可以算是彻底不可行了。

mpv 播放音频

和上面一条路有点像,但又有所区别。既然 mpv 一起放不行,那分开放呢?

事实证明,分开播放确实可行。由于视频采集和音频采集各自的延时都很低,因此分开播放并不会产生太大的 desync 问题。但是在播放过程中,时常会有扰人的 Audio device underrun 出现,伴随着由此产生的爆音:

日志输出

于是,这条路也只好放弃了。

OBS 播放音频

既然是 PulseAudio 源,那么使用 OBS 的音频输入捕获怎么样呢?我们来尝试一下。首先是音频源,直接选中我们的设备:

可以看到,底部已经有声音的标识了:

但这时候我们还不能听到声音,需要在高级音频属性里打开音频设备的监听:

此时桌面音频就和音频输入捕获保持同步了,我们也可以听到音乐了:

经过测试,OBS 的音频输入捕获工作得非常完美,不存在 mpv 的爆音问题。但为了播放音频而多打开一个软件实在是太不优雅,于是这条路作为备用方案,暂时搁置。

PulseAudio 音频 loopback

到了这里,我们不妨想一想,绕了这么多圈,用了这么多软件,我们这个需求的本质是什么?

在我之前翻译的 ALSA 音频 API 使用教程 中较为详细地描述了 ALSA 工作的一些基本概念,而 PulseAudio 则是在 ALSA 和应用程序之间充当着代理的角色。

回到正题,我们希望能够将采集卡采集到的音频在计算机上播放,此时采集卡相当于一个输入设备。对于我们而言,平时最常用的音频输入设备麦克风,此时的采集卡也充当着这样的角色。

回过头来,在很多情况下,我们都能听到麦克风录制的自己的声音,这通常用在麦克风测试的过程中,通过播放麦克风录制的音频,确保麦克风配置正确。这样的行为就是 loopback

PulseAudio 中,通过 module-loopback 模块开启音频源的 loopback,我们可以通过 pactl 来启用它:

启用过程中要指定 sourceid

随着 BGM 的响起,这场和采集卡斗智斗勇的旅程也就这样告下帷幕了。

Bash Script

最后就是一键脚本时间了。保存脚本为 ccp.sh,你就可以通过 ccp 直接开始摸鱼了。

幸福往往是摸得透彻,而敬业的心却常常隐藏

简单来说,功能有:

  • 双击全屏
  • ESC 退出全屏
  • Ctrl+C 退出
  • F10 截屏到 pwd 或指定目录

具体实现看源码就是了(笑

实际使用中有一个问题,就是在 USB 刚刚接入的时候就运行脚本,有大概率音频回放没有声音。我个人的猜测是采集卡还没有进入工作状态,所以建议等待一段时间(也不用太长)再运行就没有问题了。

#!/bin/bash

PROGNAME="$(basename $0)"

# mpv settings
MPV_FULLSCREEN=no
MPV_VIDEO_SIZE=1920x1080
MPV_TITLE="Live Gamer Ultra-Video"
MPV_SCREENSHOT_DIR="$(pwd)"

GETOPT_ARGS=$(getopt -o hc:w:g:de:nm: -l "help","fullscreen","fs" -n "$PROGNAME" -- "$@")
[[ $? -ne 0 ]] && exit 1
eval set -- "$GETOPT_ARGS"

while :; do
    case "$1" in
        -h|--help)
            usage
            exit 0
            ;;
        --video-size)
            shift
            VIDEO_SIZE="$1"
            shift
            ;;
        --video-device)
            shift
            MPV_VIDEO_SIZE="$1"
            shift
            ;;
        --fullscreen|--fs)
            shift
            MPV_FULLSCREEN=yes
            ;;
        --screenshot-directory)
            shift
            MPV_SCREENSHOT_DIR="$1"
            shift
            ;;
        --title)
            shift
            MPV_TITLE="$1"
            SHIFT
            ;;
        --)
            shift
            break
            ;;
    esac
done

function requirement_check() {
  which lsusb    > /dev/null 2>&1 &&
  which pactl    > /dev/null 2>&1 &&
  which v4l2-ctl > /dev/null 2>&1 &&
  which mpv      > /dev/null 2>&1 ||
  (echo "Please make sure lsusb, pactl, v4l2-ctl and mpv exist in your system!"; exit 1)
}

function device_check() {
  lsusb | grep -q AVerMedia
  [[ $? -ne 0 ]] && echo "No capture card found!" && exit 1
}

function get_source() {
  PACTL_SOURCE=$(LC_ALL=C pactl list sources | grep AVerMedia -B 3 | grep Source | cut -d '#' -f 2)
}

function audio_on() {
  # get audio source id
  get_source
  # retry once
  # may fail if audio source has not been initialized
  [[ -z "$PACTL_SOURCE" ]] && sleep 1 && get_source
  [[ -z "$PACTL_SOURCE" ]] && echo "Failed to get audio source!" && exit 1

  # enable audio loopback
  PACTL_MODULE_ID=$(pactl load-module module-loopback source="$PACTL_SOURCE")
  [[ $? -ne 0 ]] && echo "Failed to initialize audio playback!" && exit 1
}

function audio_off() {
  if [ ! -z "$PACTL_MODULE_ID" ]; then
    pactl unload-module $PACTL_MODULE_ID
  fi
}

function video_config() {
  # create tmp config dir
  CONFIG_DIR=$(mktemp -d -t ccplay-XXXXXXXX)

  # create tmp config file
  CONFIG_FILE=$(cat << EOF
osc=no
input-default-bindings=no
osd-font-size=24

profile=low-latency
untimed=yes

# screenshot
screenshot-format=png
screenshot-template=screenshot-%tY-%tm-%td-%tH:%tM:%tS
screenshot-directory=$MPV_SCREENSHOT_DIR

title=$MPV_TITLE
fullscreen=$MPV_FULLSCREEN
demuxer-lavf-o=video_size=$MPV_VIDEO_SIZE
EOF
)
  echo "$CONFIG_FILE" > "$CONFIG_DIR/mpv.conf"

  # create tmp input config
  CONFIG_FILE=$(cat << EOF
MBTN_LEFT_DBL  cycle fullscreen
ESC            set fullscreen no
ctrl+c         quit 0
F10            screenshot
EOF
)
  echo "$CONFIG_FILE" > "$CONFIG_DIR/input.conf"
}

function video_on() {
  # default video device
  if [ -z "$VIDEO_DEVICE" ]; then
    VIDEO_DEVICE=$(v4l2-ctl --list-devices | grep 'Live Gamer Ultra-Video' -A 5 | grep '/dev' | head -n 1 | xargs)
  fi

  # launch mpv
  mpv "av://v4l2:$VIDEO_DEVICE" --config-dir="$CONFIG_DIR" &>/dev/null &
}

function start() {
  requirement_check
  device_check
  audio_on
  video_config
  video_on
  wait $!

  # https://github.com/mpv-player/mpv/blob/master/DOCS/man/mpv.rst#exit-codes
  # file could not be played, retry once
  if [ $? -eq 2 ]; then
    video_on
    wait
  fi
}

function clean() {
  audio_off
  yes | rm "$CONFIG_DIR"/*.conf &>/dev/null
  yes | rmdir "$CONFIG_DIR" &>/dev/null
}

trap clean EXIT
start

参考

  1. https://forum.manjaro.org/t/trying-to-connect-avermedia-capture-card/38613
  2. https://www.reddit.com/r/linux/comments/c0vy1c/recording_4k_linux_including_gaming_footage_using/
  3. https://github.com/mpv-player/mpv/wiki/Video4Linux2-Input

评论

  1. lll
    3年前
    2021-9-18 20:19:43

    大神你好,我们也想将gc553连在Ubuntu上使用,但是我们使用照文中提到的mpv方法发现依然不行,我们输入了mpv av://v4l2:/dev/video1 的指令,但是报错:[ffmpeg/demuxer] video4linux2,v4l2: ioctl(VIDIOC_STREAMON): No such file or directory。不知道能否加下您的联系方式,详细交流下

    • 某昨P
      博主
      lll
      3年前
      2021-9-18 20:45:52

      你可能需要去 /dev/ 下面看看有没有这个文件。以及接入之后要先等一会,等到 lsusb 里能显示出设备之后再去 /dev 里找找

    • 某昨P
      博主
      lll
      3年前
      2021-9-18 20:47:40

      以及虽然确实会同时出现 video0 和 video1,但我这边只能用 video0,这部分我也没有详细研究过(

    • Leo
      lll
      2年前
      2021-12-14 23:34:06

      I’m using Jetson Nano and MPV with the same error you mention above, I found that GC553 can draw more than 5W and the USB port can’t provide enough amps, so make sure the USB port have enough power to drive your video capture card.

  2. Leo
    2年前
    2021-12-15 23:30:22

    And I found that the audio problem in MPV is PulseAudio config problem, following this tutorial:
    https://wiki.archlinux.org/title/PulseAudio/Troubleshooting#Setting_the_default_fragment_number_and_buffer_size_in_PulseAudio
    To config the fragment number and buffer size then reboot, now MPV can play both video and audio smoothly.

发送评论 编辑评论


				
上一篇
下一篇