《#诗盗#·有朋自远方来》:写诗浑似画虎卵,不用古精与酒坛。今日相逢无限饮,老婆太多七次难。
注解
画虎卵:闽南语,吹牛侃大山。
古精:古经的通假字,古典经书。
《#诗盗#·有朋自远方来》:写诗浑似画虎卵,不用古精与酒坛。今日相逢无限饮,老婆太多七次难。
画虎卵:闽南语,吹牛侃大山。
古精:古经的通假字,古典经书。
《#诗盗#·绿艹囧》:绿草横四空,网兔分六笼。骑虎三流灵,科技万花捅。
最近 KJ 四个绿色的 +,大花园的乖乖兔们终于迎来六个办公室~
用了三流灵就是骑虎难下,虽然人人喊打,然并卵。
在云游戏和云桌面项目中,总结了几类声音采集技术,把录音做到极致。
最典型的就是麦克风,内置麦克风、外置麦克风,其实还有一种通过 LineIn 插入的其它播放器设备,比如 CD、DVD 等。
采集这种音频的方法可以只用 ffmpeg 搞定:av_find_input_format(“dshow”)…,也可以用 CoreAudio 搞定:
1 | enumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE, ... |
采集方式是用 CoreAudio:
1 | enumerator->(eRender, DEVICE_STATE_ACTIVE, ... |
这种方式会混音,比如说您开个 foobar 播歌,再开个 QQ 影音看电影,则会录到这两个应用程序的混音,嗯,如果 QQ 再嘀嘀嘀,也是会混进去的……
有个叫 Virtual Audio Cable 的虚拟声卡,能虚拟多张声卡,并且可以把声音转发到对应的虚拟 LineIn 设备,供应用程序采集。
比前一种更先进一些,多个播放器同时播歌,我们可以只录其中一个。
采集方法是:Hook CoreAudio。
另一个思路是:Hook 到这个应用,给它单独指定一个输出设备,其它应用不能用,否则还是混音了,然后用前面的回放录音技术录制这个独占的输出设备。您可能要说,哪有那么多输出设备?这个问题可以用前面提到的虚拟声卡解决,分分秒虚拟出 64 个是没问题的。而且用 VAC 的好处是,可以在这 64 个对应的 LineIn 通道直接录制,不需要用 CoreAudio,兼容性会更好。
一般情况下操作 AVAudioFifo/AVFrame 都是用全套 ffmpeg API,内部自己管理内存,不需要了解它们内部怎么组织内存。比如:
1 | inline int InitFrame(AVFrame *&frame, int frame_size = kTargetSamplesPerFrame) |
这里读了一个 AVFrame 出来,并不需要知道具体的内存布局,但如果要写入 FileMapping 对象里,就得知道了! 参考以下函数:
1 | int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples) |
和 AVFrame 定义:
1 | typedef struct AVFrame { |
以 AV_SAMPLE_FMT_S16 为例,发现 InitFrame() 里的 av_frame_get_buffer() 之后只有 linesize[0] 是非 0,即 data[0] 的分配长度,其它 7 个都是 0,即 data[1] -> data[7] 都没有分配,于是猜测就是读 data[0],长度 linesize[0],尝试把它写到 FileMapping 里,果然是对的。如果 SampleFormat 是带 P 的,就不是只有 data[0] 了,有几个 channel 就有几个 data,要相应改变。
京东联盟购买链接:
FFmpeg从入门到精通 出版时间:2018-04-01 用纸:胶版纸
最近写录音程序,发现 MBP 的扬声器是 4 频道的,然后在抓音频保存时,Opus 编码器居然不支持 4 个频道,avcodec_open2() 会返回错误码 -22,Invalid argument。解决方法就是 resample 成 AV_CH_LAYOUT_STEREO。搞定后就顺便细研了这个 ChannelLayout,UMU 的代码里需要把微软 CoreAudio 的一些参数转成 ffmpeg 的,比如之前写的《Windows 的 WAVEFORMATEX 转 ffmpeg 的 AVSampleFormat 类型》,这次写 ChannelLayout 的转换。
ffmpeg 的 channel layouts 定义:
1 | /** |
ffmpeg 的频道位置信息:
1 |
微软的频道位置信息:
1 | // Speaker Positions for dwChannelMask in WAVEFORMATEXTENSIBLE: |
经过对比可以发现两者是一致的,只是微软的 dwChannelMask 是 DWORD,ffmpeg 用的是 int64_t。所以我们可以写个函数来转换他们:
1 | // 微软的 ChannelMask 值转为 ffmpeg 的 channel_layout |
京东联盟购买链接:
FFmpeg从入门到精通 出版时间:2018-04-01 用纸:胶版纸
今天进 UEFI 看到集显的两个设置选项:IGD Minimum Memory 和 IGD Aperture Size,想着 UMU 的 NUC 有 32G 内存,要不要改大点?然后搜一下他们的作用,结果发现最好不要改……
Adjusting the minimum memory can impact graphics performance in legacy operating systems (Windows 7/8/8/1).
The default value (64 MB) is recommended for Windows 10. Windows 10 will allocate graphics memory dynamically when it loads, so setting the IGD minimal memory to higher value may not improve performance.
Keep the default BIOS setting for IGD Aperture Size and IGD Min Memory. This values are used only during POST and to boot of the Windows.
Window 10 assigns automatically the maximum available graphics memory and it depends off how much RAM you have. Usually it assigns about half of available RAM.
Windows 平台,录音。
用 Windows 的 IAudioCaptureClient 对象采集音频,然后用 ffmpeg 编码。
一些类型定义不一样,比如 SampleFormat。
1 | inline AVSampleFormat GetSampleFormat(const WAVEFORMATEX *wave_format) |
京东联盟购买链接:
FFmpeg从入门到精通 出版时间:2018-04-01 用纸:胶版纸
最近参考 ffmpeg 的 transcoding_aac 示例代码,写了一个 transcoding_opus,并拿 MP3 测试转码,结果发现转完的 opus 文件的 SampleFormat 和指定的并不一样。UMU 的代码是把源文件解码出来的 sample 先 resample 成 AV_SAMPLE_FMT_S16 格式,然后再交给 opus encoder 去编码的,但是编完用 ffprobe 查看,发现 SampleFormat 变成 AV_SAMPLE_FMT_FLTP。
那么第一个问题来了,为什么会这样?
开始研究,首先 UMU 把 opus encoder 支持的 sample_fmt 打印出来,发现只有两种:AV_SAMPLE_FMT_S16、AV_SAMPLE_FMT_FLT,压根就没有 AV_SAMPLE_FMT_FLTP,强行指定 AV_SAMPLE_FMT_FLTP 之后,直接报错,不支持这种 sample_fmt。
推测,真的被编码为 AV_SAMPLE_FMT_S16 了,是 ffprobe 的问题,于是自己写了个简化版的 ffprobe,流程几乎是一样的,出来的结果——果然一模一样……打印出 AV_SAMPLE_FMT_FLTP。
接着怀疑 ffprobe 用的 decoder,于是去看了 avcodec_find_decoder 返回的 AVCodec,打印一下 name 和 long_name,和 transcoding_opus 的 avcodec_find_encoder 返回的一比,果然不一样……
选用的编码器是这样的:
1 | AVCodec ff_libopus_encoder = { |
而选用的解码器是这样的:
1 | AVCodec ff_opus_encoder = { |
问题清楚了,看来用 ID 查找编解码器并不靠谱,因为这个 ID 是 Type ID,不是 Item ID,还是改为用 name 来找:
1 | //AVCodec *output_codec = avcodec_find_encoder(AV_CODEC_ID_OPUS); |
那么,第二个问题顺势而来——哪个比较牛?
用 AV_SAMPLE_FMT_FLTP 后 frame_size 是 120,用其它是 960,frame_size 小有小的好处,比如在做实时编码直播时,理论延迟会更小。
经过测试,用 AV_SAMPLE_FMT_FLTP 的 opus 比 libopus 压缩率普遍略高一些,但它只支持 48000Hz 一种 sample_rate,libopus 支持的更多:48000, 24000, 16000, 12000, 8000。
京东联盟购买链接:
FFmpeg从入门到精通 出版时间:2018-04-01 用纸:胶版纸
《#诗盗#·科技傲娇爹》:股市两桶我四桶,阿里一桶爹三桶。前年科技蹭得累,今年集体来做空。
股市两桶我四桶:股市两桶油,最近都是绿的,我门口放着四桶油……
一桶:一捅
三桶:伤痛
蹭得累:多傲娇
《#诗盗#·熵增熵稣屎里掏花》:天增岁月房增值,物价如熵人作死。当年科技不买楼,如今只能搬三期。
《#诗盗#·科技变化太快》:当初不买楼,如今望天愁。当初不卖出,如今爹成猪。
《#诗盗#·213》:上街街上行人稀,下车车下雨水积。两脚牵拖做好湿,一觉穿越三生世!
213 是车牌号,雨天开高速,开了 5 个多小时……
在“上街”停车休息,下车踩了水雷,做梦穿越。
牵拖:拖鞋。