需求
Windows 平台,录音。
任务
用 Windows 的 IAudioCaptureClient 对象采集音频,然后用 ffmpeg 编码。
困难
一些类型定义不一样,比如 SampleFormat。
解决方案
1 | inline AVSampleFormat GetSampleFormat(const WAVEFORMATEX *wave_format) |
相关书籍
京东联盟购买链接:
FFmpeg从入门到精通 出版时间:2018-04-01 用纸:胶版纸
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 个多小时……
在“上街”停车休息,下车踩了水雷,做梦穿越。
牵拖:拖鞋。
2009-04-17 22:06 在百度空间上发表过一次,后来百度空间倒闭了……最近给自己家里搭建家庭文件共享服务器用到,所以在这边再发一次。
2009 年时,由于项目需要,用过 Hyper-V Server 2008。到了 2012-09-25 升级为 Hyper-V Server 2012。这次(2017-03-22)用的是 Hyper-V Server 2016。这么多年一直还是完全免费的。
Hyper-V Server 是基于 Windows Server Server Core x64 的虚拟机服务器系统,要正常提供虚拟机服务, CPU 必须满足三个条件:x64、DEP (Data Execution Prevention)、HV (Hardware Virtualization),但 UMU 不需要它的专业本领——虚拟机服务,所以只需要有 x64 CPU 就可以了。目前只使用他的副业,作为网上邻居(SMB)服务器和静态文件 HTTP Server,就家用而言,绝对够用,前者是系统自带的共享功能,用 net share
命令开启,后者安装 node.js + http-server 模块。
但它不是完整的 Windows Server,比如您想跑 IIS,那就不能使用它了。它最适合的情况是您开发了一些系统服务(NT Service)类的应用,比如游戏服务端、聊天软件服务端,想发布到 Windows Server 上。
Hyper-V Server 2019 是最后一个免费的 Hyper-V Server。
主流支持到 2024-01-09,扩展支持到 2029-01-09。
参考:https://learn.microsoft.com/en-us/lifecycle/products/hyperv-server-2019
在之前的文章《跟 UMU 一起玩 OpenWRT(入门篇10):穿透内网》,介绍了 autossh 的使用,现在多个需求:想在内网打通多条隧道,即让 autossh 能运行多个 ssh 实例。
1 | config autossh |
1 | export SERVICE_MATCH_NAME=1 |
1 | start_instance() { |
这样改是有副作用的,您反复启动多次就知道了……启动的命令是:
1 | /etc/init.d/autossh start |
在之前的文章《跟 UMU 一起玩 OpenWRT(入门篇10):穿透内网》,介绍了从家里连到公司内网,现在需求反过来了,想在公司代理到家里,让公司的 QQ 使用家里的网络出口。
还是那些熟悉的工具!首先,家里的路由器要刷好 OpenWRT,绑定一个动态域名,记为 HomeRouter。
2020/04/05 23:59 添加:
绑定动态域名的方法可以参考:https://github.com/UMU618/openwrt-ipv6-addresses
在 Windows 下用 putty 连到 HomeRouter,基本就大功告成!开 tunnels 方法如图:
或者用:
1 | PLINK.EXE -N -D 1080 root@HomeRouter |
最后是 QQ 的设置:
《#诗盗#·量子邪说2》:生物奇,化学危。最恨物理,量子邪说!
改编自霹雳角色“恨吾峰”的诗号。
孤月冷,夜刀寒,最恨无敌,天下吾峰。
《#诗盗#·非正常人类》:一觉好梦游仙,管它屋冷床寒!参编善恶演幻,听尽庸人说谗。
写于软件非正常人类研究中心。改编自霹雳角色“人觉·非常君”和“禅剑一如寄昙说”的诗号。
一觉游仙好梦,任它竹冷松寒。
轩辕事,古今谈,风流河山。
沉醉负白首,舒怀成大观。
醒,亦在人间;梦,亦在人间。
看红尘冉冉,须臾无间,参遍昙华演换。
问法珠玄玄,方寸有变,听尽默剑说禅。
UMU 认为有一个目的是:需求细分(另外还有优化的目的)。考虑以下代码:
1 | class Movable |
因为 Movable& m 没有用 const 修饰,所以可以在内部改变 m 的状态。如果加上 const 则不行:
1 | Movable(const Movable& m) : i(m.i) |
那么没加 const 的集合,减去有 const 的集合,等于什么?答案就是:移动构造函数
1 | Movable(Movable&& m) : i(m.i) |
分成 const Movable& 和 Movable&& 两个,更严格、更清晰,这是好事。而 std::move 做的事情是为了正确调用移动构造函数(Movable&&),而不是被隐式转为 const 而错误地调用了复制构造函数(const Movable&),不要在意什么左值、右值的,太烧脑了……
扩展阅读:《从4行代码看右值引用》,https://www.cnblogs.com/qicosmos/p/4283455.html