Hello 👋,

A while ago I wrote an article on how to separate audio from video with ffmpeg on Linux using bash. The article can be read here:

Separate Audio from Video (with ffmpeg) Now I want to introduce you to the Windows version with some little Powershell functions that I’ve wrote.

But why?

If you’re a content creator and you are not using the free program Audacity for editing your audio files, I believe you’re missing out on some great features. In my opinion, the noise gate feature is very usefull for eliminating background sounds and breaths from your audio. My PC fan and keyboard strokes are pretty loud and I can easily eliminate them with these settings:

I tested both the Final Cut Pro and Davinci’s Resolve voice isolation feature and I find that the Noise Gate from Audacity works best for me.

My Workflow

I have an raw and unedited video which I record with OBS, then I split the audio by running:

1
 Split-Video .\InstallDockerAndDockerCompose.mkv

Then I open up the audio file InstallPythonAndPycharmTemp.aup3 in Audacity, apply my desired effects and save the file in the same directory with the name InstallDockerAndDockerComposeTemp.wav.

Then I run:

1
Join-Video .\InstallDockerAndDockerCompose.mkv

And it will give me the final video named InstallDockerAndDockerComposeFinal.mp4 with the audio edited in Audacity! 😄

Powershell Functions

You can add these functions to your PowerShell profile by typing code $PROFILE. It should open a Visual Studio Code instance and your PS profile file.

Then paste the following functions into the file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
function global:Split-Video {
  [CmdletBinding()]
  [Alias('vsplit')]
  param (
    [Parameter(Mandatory=$True,Position=0,ValueFromRemainingArguments=$False)]
    [String] $VideoPath
  )
  begin {
    $filename = Get-ChildItem -Path $VideoPath
    $filename_wo_extension = $filename.basename
  }
  process {
    ffmpeg -i "$VideoPath" -vn -c:a copy "${filename_wo_extension}Temp.m4a"
    ffmpeg -i "$VideoPath" -an -c:v copy "${filename_wo_extension}Temp.mp4"
  }
}

function global:Join-Video {
  [CmdletBinding()]
  [Alias('vjoin')]
  param (
    [Parameter(Mandatory=$True,Position=0,ValueFromRemainingArguments=$False)]
    [String] $VideoPath,
    [Parameter(Mandatory=$False,Position=1,ValueFromRemainingArguments=$False)]
    [String] $AudioPath
  )
  begin {
    $filename = Get-ChildItem -Path $VideoPath
    $filename_wo_extension = $filename.basename
    # Test AudioPath for Null
    if ($AudioPath -notmatch '\S') {
      $audio_file = "./${filename_wo_extension}Temp.wav"
    } else {
      $audio_file = $AudioPath
    }
  }
  process {
    ffmpeg -i "./${filename_wo_extension}Temp.mp4" -i "$audio_file" -c:v copy -c:a aac "./${filename_wo_extension}AudioFix.mp4"
    Remove-Item -Force "./${filename_wo_extension}Temp.mp4"
    Remove-Item -Force "./${filename_wo_extension}Temp.m4a"
  }
}

Ensure that you have ffmpeg installed. I’ve installed it with:

1
choco install ffmpeg

Conclusion

Thanks for reading!

What do you think about this workflow, do you have any ideas how it can be improved?

Denis