54 lines
8 KiB
XML
54 lines
8 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<?xml-stylesheet type="text/xsl" href="/simple-atom.xslt"?>
|
||
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
|
||
<title>joshua.seigler.net - ffmpeg</title>
|
||
<subtitle>Personal homepage of Joshua Seigler</subtitle>
|
||
<link href="https://joshua.seigler.net/feeds/ffmpeg.xml" rel="self" />
|
||
<link href="https://joshua.seigler.net/" />
|
||
<updated>2025-07-04T00:00:00Z</updated>
|
||
<id>https://joshua.seigler.net/</id>
|
||
<author>
|
||
<name></name>
|
||
</author>
|
||
<entry>
|
||
<title>FFmpeg audio cleanup</title>
|
||
<link href="https://joshua.seigler.net/posts/ffmpeg-audio-cleanup/" />
|
||
<updated>2025-06-26T00:00:00Z</updated>
|
||
<id>https://joshua.seigler.net/posts/ffmpeg-audio-cleanup/</id>
|
||
<content type="html"><p>I recently needed to process 20+ phone audio recordings. The files are mp3 recordings in stereo, made in an environment with echoes and noise from fans/heaters.</p>
|
||
<p>Although I could do it easily with <a href="https://tenacityaudio.org/" target="_blank" rel="noopener">Tenacity</a> I didn’t want to use a manual process, since it would take days. So I tried using FFmpeg filters and Bash scripting.</p>
|
||
<p>I found an FFmpeg filter called <a href="https://ffmpeg.org/ffmpeg-filters.html#compand" target="_blank" rel="noopener">compand</a> which lets you map an input decibel range to an output decibel range. I also used the <a href="https://ffmpeg.org/ffmpeg-filters.html#anlmdn" target="_blank" rel="noopener">anlmdn</a> filter to reduce noise, and the <a href="https://ffmpeg.org/ffmpeg-filters.html#highpass" target="_blank" rel="noopener">highpass</a> filter to help with clarity.</p>
|
||
<p>I ran into a couple gotchas.</p>
|
||
<ol>
|
||
<li><code>mpv</code> does something special for audio playback that prevents audio from clipping. <code>vlc</code> plays the file as it is.</li>
|
||
<li>Because the compressor has an attack and decay (which is necessary for things to sound good) it can cause clipping if the volume rises sharply. Applying a <code>delay</code> parameter with half the duration of the attack length fixed this.</li>
|
||
</ol>
|
||
<p>Here is the script:</p>
|
||
<p><code>process-audio.sh</code></p>
|
||
<pre class="language-bash"><code class="language-bash"><span class="token shebang important">#!/bin/bash</span>
|
||
<span class="token keyword">if</span> <span class="token punctuation">[</span> <span class="token string">"<span class="token variable">$#</span>"</span> <span class="token operator">==</span> <span class="token string">"0"</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">then</span>
|
||
<span class="token builtin class-name">echo</span> <span class="token string">"Error: no arguments provided."</span>
|
||
<span class="token builtin class-name">echo</span> <span class="token string">"Usage: <span class="token variable">$0</span> file1 file2 file3 ..."</span>
|
||
<span class="token builtin class-name">echo</span> <span class="token string">"or <span class="token variable">$0</span> *.ext"</span>
|
||
<span class="token builtin class-name">exit</span> <span class="token number">1</span>
|
||
<span class="token keyword">fi</span>
|
||
|
||
<span class="token builtin class-name">trap</span> <span class="token string">"exit"</span> INT
|
||
|
||
<span class="token keyword">while</span> <span class="token punctuation">[</span> <span class="token string">"<span class="token variable">$#</span>"</span> <span class="token operator">!=</span> <span class="token string">"0"</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">do</span>
|
||
<span class="token assign-left variable">path</span><span class="token operator">=</span><span class="token string">"<span class="token variable">${1<span class="token operator">%</span><span class="token operator">/</span>*}</span>"</span>
|
||
<span class="token assign-left variable">file</span><span class="token operator">=</span><span class="token string">"<span class="token variable">${1<span class="token operator">##</span>*<span class="token operator">/</span>}</span>"</span>
|
||
<span class="token assign-left variable">outfile</span><span class="token operator">=</span><span class="token string">"./normalized--<span class="token variable">$file</span>"</span>
|
||
<span class="token keyword">if</span> <span class="token punctuation">[</span> <span class="token operator">!</span> <span class="token parameter variable">-f</span> <span class="token string">"<span class="token variable">$outfile</span>"</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">then</span>
|
||
<span class="token builtin class-name">echo</span> <span class="token string">"Processing <span class="token variable">$1</span>"</span>
|
||
ffmpeg <span class="token parameter variable">-i</span> <span class="token string">"<span class="token variable">$1</span>"</span> <span class="token parameter variable">-v</span> warning <span class="token parameter variable">-ac</span> <span class="token number">1</span> <span class="token parameter variable">-af</span> <span class="token string">"compand=attacks=0.3:decays=0.3:delay=0.15:points=-80/-300|-45/-25|-27/-15|0/-12|20/-12,anlmdn=s=10,highpass=f=500"</span> <span class="token parameter variable">-threads</span> <span class="token number">4</span> <span class="token string">"<span class="token variable">$outfile</span>"</span>
|
||
<span class="token keyword">else</span>
|
||
<span class="token builtin class-name">echo</span> <span class="token string">"Skipping <span class="token variable">$1</span>, already processed."</span>
|
||
<span class="token keyword">fi</span>
|
||
<span class="token builtin class-name">shift</span>
|
||
<span class="token keyword">done</span>
|
||
</code></pre>
|
||
<p>If this is useful to you please leave a comment or send an email, I would love to hear about it.</p>
|
||
</content>
|
||
</entry>
|
||
</feed>
|