MacOS自动化录屏:$screencapture获取Audio Device ID

WARNING: This article may be obsolete
This post was published in 2021-01-26. Obviously, expired content is less useful to users if it has already pasted its expiration date.

自动截图

我下载了一些能在Mac上玩的游戏,比如Minecraft、Don't Starve、Subnautica。由于个人喜好,在玩这些游戏的时候,我希望能够时不时保存一些游戏截图作为记录和纪念。因此最初的时候我希望能写一个简单的程序,在我玩游戏的时候定时在后台静默截图,同时完全不打扰游戏操作。

说干就干。使用schedule Package作为定时工具,很快就能写出一个简单的python程序,用于每隔一段时间截图一次:

import schedule
import time

def job():
    print("Take screenshot...")
    # Do Something about screenshot
    # Screenshot code

schedule.every(10).minutes.do(job)

while True:
    schedule.run_pending()
    time.sleep(1)

def job()里面用什么代码呢?很快我就发现了 screencapture 命令,它是OSX自带的命令,位于 /usr/sbin/screencapture 。一个最简单的截图命令如下:

$    screencapture demo.png

可以对这条命令添加一些参数,比如输出jpg、截图的时候不发出声音、自定义输出路径,等等。

这样一个挂在后台运行的游戏静默截图工具就做好了。

P.S. 我对这个工具进行了一点小改动,见这篇文章:对macOS: $screencapture命令的一些其他改进

自动录制屏幕

查看 $ man screencapture 帮助文档的时候,我发现 screencapture 命令不仅可以截图,还可以录屏。我开始逐渐感觉“自动截图”还差点意思,应该升级为“自动录制短视频”。

为什么不开一个OBS或者QuickTime Player一直录呢?因为高画质录屏实在是太占空间了。为了节省硬盘空间和寿命,应当“每隔一段时间,比如20分钟,后台静默录制20秒的视频并自动保存”。

看起来也很简单。根据 $ man screencapture 的帮助文档,我应当修改命令如下:

$    screencapture -v -V 20 demo.mov

但是,这样录制的视频是没有声音的。如果硬要用 $ screencapture -v -V 20 -g demo.mov 试图加入声音,会发现加进来的声音是Macbook麦克风的声音。

这样肯定是不行的,我需要加入的是游戏里面的声音。这个任务在windows上面可能比较简单,但是在OSX要麻烦一些,以至于我放弃并搁置了这个功能长达1年之久。本文接下来将首先介绍实现这个功能需要额外安装的程式(Soundflower),然后介绍如何用正确的方式找到Soundflower对应的Audio device ID.

SoundFlower

为了使 screencapture 命令捕获到macOS内部的声音,我们首先需要找到一个分离系统内部音频的程式,比如SoundFlower .

相信许多尝试在Mac上面录制视频的人都安装过这个系统插件(这个可能算是MAC新用户的几个必搜问题之一):mattingalls/Soundflower: MacOS system extension that allows applications to pass audio to other applications. Soundflower works on macOS Catalina,互联网上有很多SoundFlower相关的教程。

安装完SoundFlower以后,如果打开QuickTime Player以后发现能够捕获Mac内部音频,说明它就起作用了,接下来就要考虑如何把SoundFlower加入我的程序里。

根据 $ screencapture --help  ->  -G captures audio during a video recording using audio id specified. 可以得知,如果我们使用命令 $ screencapture -v -V 20 -G ? demo.mov ,并把?替换为SoundFlower的audio id,就成功了!

寻找这个SoundFlower audio device id花费了我相当长的时间。我尝试了很多开源工具,包括:

karaggeorge/macos-audio-devices: Get, set and configure the Audio Devices on macOS

deweller/switchaudio-osx: Change the audio source for Mac OS X from the command line

甚至还有 $ mplayer -ao coreaudio:device_id=list 这样的命令,但是获取的ID全都对不上,screencapture永远会返回类似 screencapture: Capture audio device 114 not found. 这样的错误。

过了一年,我终于成功获取了正确的audio device ID:写在本文后面[↓]

FFmpeg(效果太差)

我开始怀疑screencapture根本就没有正确的audio device ID(我写了一个程序去暴力尝试int 1~10000的ID,全是错的),所以我开始求助于其他命令。

根据社区的回答,FFmpeg也可以做到录制屏幕。当然,在此之前要 $ brew install ffmpeg 

首先获取所有可用的video/audio devices:

$    ffmpeg -f avfoundation -list_devices true -i ""

然后自由组合video device index和audio device index进行录屏:

$    ffmpeg -f avfoundation -i "1:0" -vsync 2  moviecapture.avi

但是(可能是我完全不懂怎么调优ffmpeg),用这种方法录制得到的视频拥有全损且完全失去同步的音频,完全没法用。

Audio Device ID

* 在开始调试screencapture命令之前,你可以使用QuickTime Player来检查一下自己的SoundFlower配置是否正确。

* 如果你发现自己输入的Audio Device ID正确,但screencapture录制出来的视频没有音频轨(多见于Big Sur和Monterey),那么这多半是MacOS TCC权限的问题,你可能需要参考这条解决方案去重置TCC[↓]

因为死活找不到Audio Device ID,自动录屏的计划被我晾在一边超过1年了。后来我终于发现了一个社区comment,找到了正确答案:

🔗 [mediaplayer - List core audio devices - Ask Different] https://apple.stackexchange.com/questions/226674/list-core-audio-devices

这个命令需要改为:

$    grep key /Library/Preferences/Audio/com.apple.audio.DeviceSettings.plist

然后从里面挑选出类似这样的字符:<key> ??? </key>,而 ??? 才是 screencapture 命令需要填入的audio device ID .

<key>BuiltInHeadphoneInputDevice</key>
<key>BuiltInHeadphoneOutputDevice</key>
<key>BuiltInMicrophoneDevice</key>
<key>BuiltInSpeakerDevice</key>
<key>SoundflowerEngine:0</key>
<key>SoundflowerEngine:1</key>
    
............

(难怪我无法用暴力查找数字的方法找到ID)

最后把需要的audio device ID(比如录制内部声音:SoundflowerEngine:0)填入screencapture命令里:

$    screencapture -v -V 20  -G SoundflowerEngine:0  output.mov

把命令稍加修改加入python代码里,这样就得到了最终想要的结果:玩游戏的时候运行这个录制视频程序并挂在后台,既可以每隔5分钟静默截图1次并保存,又可以每隔20分钟静默录制20秒的视频并保存。

其他可选方案(未尝试)

我猜,大概也可以通过QuickTime Player和AppleScript完成自动录屏的功能,理论上得到的结果和 screencapture 命令是一样的,但我没有尝试过。

2022年更新:重置TCC权限系统,解决没有音频的问题

近几年MacOS越做越糟糕的TCC权限系统可能会导致通过screencapture命令录制出来的视频没有音频轨。你可以尝试 手动重置TCC Microphone 权限,然后重新给terminal授权一次:

 注意:该命令会重置所有的Microphone权限 

$  /usr/bin/tccutil reset Microphone

然后重新运行screencapture命令,一般来说你会看到一个熟悉的授权弹窗:

iTerm.app是我使用的终端程序,这个东西因人而异

授权以后再次运行一遍screencapture命令,大概就可以重新录入音频了。


 Last Modified in 2023-07-07 


1 thought on “MacOS自动化录屏:$screencapture获取Audio Device ID”

Leave a Comment Anonymous comment is allowed / 允许匿名评论