@Author : Lewis Tian ([email protected])
@Link : github.com/taseikyo
@Range : 2024-04-07 - 2024-04-13
本文总字数 3991 个,阅读时长约:6 分 22 秒~12 分 43 秒,统计数据来自:算筹字数统计。
*Photo by Ulrich & Mareli Aspeling on Unsplash
不缘天上云龙会,谁解湘南𧑐蚌持? —— 刘三吾《湘南杂咏三首 其一》
algorithm 🔝
review 🔝
作者介绍他使用短链的经历,在短链被重定向到真正链接之前,被广告公司设置了 cookie,而这些 cookie 能在使用其广告技术的所有其他网站上跟踪:
$ curl -v https://tinyurl.com/examplezoom
...
> GET /examplezoom HTTP/2
> Host: tinyurl.com
...
< location: https://redirect.viglink.com?key=a7e37b5f6ff1de9cb410158b1013e54a&u=https%3A%2F%2Fzoom.us%2Fj%2F123456789&prodOvrd=RAC
$ curl -v 'https://redirect.viglink.com?key=a7e37b5f6ff1de9cb410158b1013e54a&u=https%3A%2F%2Fzoom.us%2Fj%2F123456789&prodOvrd=RAC'
> GET /?key=a7e37b5f6ff1de9cb410158b1013e54a&u=https%3A%2F%2Fzoom.us%2Fj%2F123456789&prodOvrd=RAC HTTP/1.1
> Host: redirect.viglink.com
...
< Set-Cookie: vglnk.PartnerRfsh.p=; Domain=.viglink.com; Path=/; SameSite=None; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Secure
< Set-Cookie: vglnk.Agent.p=v-c935c520ecc561fe60a9418874e023b7; Domain=.viglink.com; Path=/; SameSite=None; Expires=Mon, 01 Feb 2021 16:52:34 GMT; Secure
果然是只要有盈利的地方,就有空子钻。
tip 🔝
1、问题描述
打电话的对话,被拆分成了两个 PCM 文件。其中主叫的录音文件 A.pcm,被叫的录音为 B.pcm。
问题是怎么合成一个混音的对话文件 AB.wav。
2、WAV 文件的录音格式
常见的声音文件主要有两种,分别对应于单声道(11.025KHz 采样率、8Bit 的采样值)和双声道(44.1KHz 采样率、16Bit 的采样值)。
采样率是指:声音信号在“模→数”转换过程中单位时间内采样的次数。采样值是指每一次采样周期。WAVE 文件数据块包含以脉冲编码调制(PCM)格式表示的样本。WAVE 文件是由样本组织而成的。在单声道 WAVE 文件中,声道0代表左声道,声道1代表右声道。在多声道WAVE文件中,样本是交替出现的。
WAV 文件的格式:
endian | field name | Size | 说明 | 计算方式 |
---|---|---|---|---|
big | ChunkID | 4 | 文件头标识,一般就是 "RIFF" 四个字母 | ASCII 码表示的 “RIFF”。(0x52494646) |
little | ChunkSize | 4 | 整个数据文件的大小,不包括上面 ID 和 Size 本身 | 36+SubChunk2Size,或是 4 + (8 + SubChunk1Size) + ( 8 + SubChunk2Size ),这是整个数据块的大小(不包括 ChunkID 和 ChunkSize 的大小) |
big | Format | 4 | 一般就是 "WAVE" 四个字母 | ASCII 码表示的 “WAVE”。 (0x57415645) |
big | SubChunk1ID | 4 | 格式说明块,本字段一般就是 "fmt" | 新的数据块(格式信息说 明块)ASCII 码表示的 “fmt”—— 最后是一个空格。(0x666d7420) |
little | SubChunk1Size | 4 | 本数据块的大小,不包括 ID 和 Size 字段本身 | 本块数据的大小(对于 PCM,值为 16)。 |
little | AudioFormat | 2 | 音频的格式说 明 | PCM = 1 (比如,线性采样),如果是其它值的话,则可能是一些压缩形式 |
little | NumChannels | 2 | 声道数 | 1 => 单声道 |
little | SampleRate | 4 | 采样率 | 采样率,如 8000,44100 等值 |
little | ByteRate | 4 | 比特率,每秒所需要的字节数 | 等于 : SampleRate * numChannels * BitsPerSample / 8 |
little | BlockAlign | 2 | 数据块对齐单元 | 等于:NumChannels * BitsPerSample / 8 |
little | BitsPerSample | 2 | 采样时模数转换的分辨率 | 采样分辨率 ,也就是每个样本用几位来表示,一般是 8bits 或是 16bits |
big | SubChunk2ID | 4 | 真正的声音数据块,本字段一般是 "data" | 新数据块,真正的声音数据。ASCII 码表示的 “data “(0x64617461) |
little | SubChunk2Size | 4 | 本数据块的大小,不包括 ID 和 Size 字段本身 | 数据大小,即,其后跟着的采样数据的大小。 |
little | Data | N | 音频的采样数据 | 真正的声音数据 |
3、查看录音的 PCM 文件
# pcm转立体声mp3
ffmpeg -i input1.pcm -i input2.pcm -filter_complex "amovie=input1.pcm [l]; amovie=input2.pcm [r]; [l] [r] amerge" output.mp3
# amr转混音amr
ffmpeg -i input1.amr -i input2.amr -filter_complex amix=inputs=2:duration=longest -ab 12.2k -ar 8000 -ac 1 output.amr
# 在后面加上 -loglevel quiet -y, 可以覆盖输出文件,避免输出日志,如:
ffmpeg -i input1.amr -i input2.amr -filter_complex amix=inputs=2:duration=longest -ab 12.2k -ar 8000 -ac 1 output.amr -loglevel quiet -y
4、测试效果
4.1、1.amr 和 2.amr 是左右声道的录音,现在合成混音 1_2.amr
ffmpeg -i 1.amr -i 2.amr -filter_complex amix=inputs=2:duration=longest:dropout_transition=2 -ab 12.2k -ar 8000 -ac 1 1_2.amr
4.2、1.wav 和 2.wav 是左右声道的录音,现在合成立体声 1_2.mp3,即左声道是 1 的声音,右声道是 2 的声音。
ffmpeg -i 1.wav -i 2.wav -filter_complex "amovie=1.wav [l]; amovie=2.wav [r]; [l] [r] amerge" 1_2.mp3
4.3、双声道的pcm转换为单声道的amr,指定编解码器
ffmpeg -y -f s16le -ar 8000 -ac 2 -i 1.pcm -acodec amr_nb -ab 12.2k -ar 8000 -ac 1 1.amr
2. 如何生成键盘输入统计看板
其实这个东西也不难,就是监听键盘的输入并保存,然后使用一个可视化框架将其可视化即可。
share 🔝
上面的文章讲述了作者的重构代码的经历,将同时重复冗余的代码进行了精简重构,结果他老板让他把代码改回了老版本。这里就引出一个话题:代码是否越简洁抽象越好?
很显然,如果是自己维护的代码,自己知道其逻辑,当然是越简洁抽象越好的,但是作为公司的某个产品,你要知道维护这个代码的是你与你的同事,如果你高度简洁抽象,代码确实减少了,但是理解成本却大大提升了,随着人员变动,新来的同事需要去花费很多时间去理解原来的代码逻辑,从公司层面来讲,这显然是得不偿失的。即便某款产品背后是一堆屎山代码,但是它能跑,能给用户提供服务并且未出错,它就是好的不是吗?