PowerShell script ffmpeg

2019-04-02 00:56发布

问题:

Being the good Windows systems admin that I am, I'm finally getting around to learning PowerShell. With that being said, I have no idea what I'm doing (surprise, surprise).

I thought that it would be a good learning experience for me to play around with PowerShell at home, far away from my production environment. Recently, I've begun using FFMPEG to convert all of my .mkv files to .mp4 so I could have better playback support to my PlayStation 3 via Plex, and thought that this would be a good learning experience.

The command I've been running is as follows:

ffmpeg -i OldVideoName.mkv -vcodec copy -acodec ac3 OldVideoName.mp4

What I want is have a PowerShell script that will run once, scanning a folder and all sub-folders for .mkv files (Get-ChildItem ".*.mkv"), transcode them to .mp4 via the above command, and place them in the same location as the .mkv with the same naming scheme.

Example of running the script with D:\Videos as the target directory:

D:\Videos\home_dvr\movies\video1.mkv --> D:\Videos\home_dvr\video1.mp4 D:\Videos\home_dvr\tv\video2.mkv --> D:\Videos\home_dvr\tv\video2.mp4

As you can guess, I can't figure it out for the life of me. Here's the latest attempt before giving up.

    $oldvid = Get-ChildItem .\*.mkv -Recurse
    $newvid = $oldvid.Name.split(‘.’)[0]; ForEach-Object {
            .\ffmpeg.exe -i $oldvid -y -vcodec copy -acodec ac3 $newvid".mp4”
    }

Any help would be appreciated!

回答1:

Try this:

$oldvids = Get-ChildItem *.mkv -Recurse
foreach ($oldvid in $oldvids) {
    $newvid = [io.path]::ChangeExtension($oldvid.FullName, '.mp4')
    .\ffmpeg.exe -i $oldvid.FullName -y -vcodec copy -acodec ac3 $newvid
}

$oldvid is a .NET FileInfo object and when it needs to be converted to a string, it can be just the filename and not the whole path. That won't work for files not in the current dir. So just use the FullName property to get the full path.



回答2:

It seems as if with the current version of powershell the behaviour has changed a bit. The Answer suggested by Keith Hill doesn't work anymore, it needs to have the .FullName removed in order to work with PS 5.1 (Build 14393). So the current answer would be:

$oldvids = Get-ChildItem -Filter "*.mkv" -Recurse
foreach ($oldvid in $oldvids) {
    $newvid = [io.path]::ChangeExtension($oldvid, '.mp4')
    .\ffmpeg.exe -i $oldvid-y -map 0 -c:v copy -c:a ac3 $newvid
}

Also -c:v -c:a are now preferred over -vcodec and -acodec. If you want to keep all your tracks instead of just one audio and one video track the -map 0 flag is needed.