From ad4803182671fc47c5b7402a239d74a6d439170d Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 14 Feb 2020 17:30:54 -0500 Subject: [PATCH] v4.1 - Fixed bug with forced stereo audio track cloning (#54) - Improved metadata title parsing - Plex library no longer refreshes on "compliant mp4" condition, should save some CPU cycles - Moov atom now always moved to the beginning of the file for quicker streaming (more info can be found @ https://www.adobe.com/devnet/video/articles/mp4_movie_atom.html for the curious) - Fixed progress bar counter during interactive file discovery process - Various minor code improvements --- conv2mp4-ps.ps1 | 14 +++++++--- docs/{guidelines => }/CONTRIBUTING.md | 4 +-- docs/{guidelines => }/ISSUE_TEMPLATE.md | 2 +- .../{guidelines => }/PULL_REQUEST_TEMPLATE.md | 0 docs/{guidelines => }/STRUCTURE.md | 3 +-- files/func/CloneStereoStream.ps1 | 8 +++--- files/func/ConvertFile.ps1 | 7 +++++ files/func/GetAudioStreams.ps1 | 9 ++++--- files/func/PrintEncodeError.ps1 | 5 ++-- files/func/PrintEncodeFailure.ps1 | 3 ++- files/func/PrintStatistics.ps1 | 26 +++++++++++++++++-- files/init/buildqueue.ps1 | 18 +++++++------ files/prop/properties | 2 +- 13 files changed, 73 insertions(+), 28 deletions(-) rename docs/{guidelines => }/CONTRIBUTING.md (79%) rename docs/{guidelines => }/ISSUE_TEMPLATE.md (89%) rename docs/{guidelines => }/PULL_REQUEST_TEMPLATE.md (100%) rename docs/{guidelines => }/STRUCTURE.md (86%) diff --git a/conv2mp4-ps.ps1 b/conv2mp4-ps.ps1 index 5a82036..ed8850d 100644 --- a/conv2mp4-ps.ps1 +++ b/conv2mp4-ps.ps1 @@ -1,5 +1,5 @@ <#====================================================================================================================== -conv2mp4-ps v4.0 - https://github.com/BrianDMG/conv2mp4-ps +conv2mp4-ps v4.1 - https://github.com/BrianDMG/conv2mp4-ps This Powershell script will recursively search through a user-defined file path and convert all videos of user-specified include_file_types to MP4 with H264 video and AAC audio using ffmpeg. If a conversion failure is detected, the script re-encodes @@ -39,7 +39,9 @@ $cumulativeVideoDuration = [timespan]::fromseconds(0) # Begin performing operations of files ForEach ($file in $fileList) { + $title = $file.BaseName + $sourceFile = $file.DirectoryName + "\" + $file.BaseName + $file.Extension; $fileSubDirs = ($file.DirectoryName).Substring($cfg.media_path.Length, ($file.DirectoryName).Length - $cfg.media_path.Length); @@ -74,6 +76,7 @@ ForEach ($file in $fileList) { Remove-Item $sourceFile -Force Log "$($time.Invoke()) Already exists: $targetFileRenamed" Log "$($time.Invoke()) Deleted: $sourceFile." + $duplicatesDeleted += @($sourceFile) } Else { #Codec discovery to determine whether video, audio, or both needs to be encoded @@ -91,10 +94,12 @@ ForEach ($file in $fileList) { If ($file.Extension -ne ".mp4") { Log "$($time.Invoke()) Video: $($getVideoCodec.ToUpper()), Audio: $($getAudioCodec.ToUpper()). Performing simple container conversion to MP4." ConvertFile -ConvertType Simple -KeepSubs:$cfg.keep_subtitles + $simpleConversion += @($sourceFile) $skipFile = $False } Else { $getVideoDuration = "00:00:00" + $fileCompliant += @($sourceFile) $skipFile = $True } } @@ -102,18 +107,21 @@ ForEach ($file in $fileList) { ElseIf ($getVideoCodec -eq 'h264' -AND $getAudioCodec -ne 'aac') { Log "$($time.Invoke()) Video: $($getVideoCodec.ToUpper()), Audio: $($getAudioCodec.ToUpper()). Encoding audio to AAC" ConvertFile -ConvertType Audio -KeepSubs:$cfg.keep_subtitles + $audioConversion += @($sourceFile) $skipFile = $False } # Video is not H264, Audio is already AAC ElseIf ($getVideoCodec -ne 'h264' -AND $getAudioCodec -eq 'aac') { Log "$($time.Invoke()) Video: $($getVideoCodec.ToUpper()), Audio: $($getAudioCodec.ToUpper()). Encoding video to H264." ConvertFile -ConvertType Video -KeepSubs:$cfg.keep_subtitles + $videoConversion += @($sourceFile) $skipFile = $False } # Video is not H264, Audio is not AAC ElseIf ($getVideoCodec -ne 'h264' -AND $getAudioCodec -ne 'aac') { Log "$($time.Invoke()) Video: $($getVideoCodec.ToUpper()), Audio: $($getAudioCodec.ToUpper()). Encoding video to H264 and audio to AAC." ConvertFile -ConvertType Both -KeepSubs:$cfg.keep_subtitles + $bothConversion += @($sourceFile) $skipFile = $False } @@ -122,7 +130,7 @@ ForEach ($file in $fileList) { } # Refresh Plex libraries - If ($cfg.use_plex) { + If ($cfg.use_plex -AND (-Not($skipFile))) { PlexRefresh } @@ -194,7 +202,7 @@ ForEach ($file in $fileList) { } #Running tally of session container duration (cumulative length of video processed) - $script:cumulativeVideoDuration = $script:cumulativeVideoDuration + $getVideoDuration + $script:cumulativeVideoDuration = $cumulativeVideoDuration + $getVideoDuration } } # End foreach loop diff --git a/docs/guidelines/CONTRIBUTING.md b/docs/CONTRIBUTING.md similarity index 79% rename from docs/guidelines/CONTRIBUTING.md rename to docs/CONTRIBUTING.md index ffa2d90..df3d58d 100644 --- a/docs/guidelines/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -1,10 +1,10 @@ ## Contributing -* When contributing to this repository, please first discuss the change you wish to make by creating a new issue. Please label and assign your issue according to the **[issue guidelines](/docs/guidelines/ISSUE_TEMPLATE.md)** +* When contributing to this repository, please first discuss the change you wish to make by creating a new issue. Please label and assign your issue according to the **[issue guidelines](/docs/ISSUE_TEMPLATE.md)** ## Pull Request Process -* Before submitting your pull request, please review to the **[pull request guidelines](/docs/guidelines/PULL_REQUEST_TEMPLATE.md)** +* Before submitting your pull request, please review to the **[pull request guidelines](/docs/PULL_REQUEST_TEMPLATE.md)** * The pull request will be merged once the code has been reviewed. **Thanks for contributing!** diff --git a/docs/guidelines/ISSUE_TEMPLATE.md b/docs/ISSUE_TEMPLATE.md similarity index 89% rename from docs/guidelines/ISSUE_TEMPLATE.md rename to docs/ISSUE_TEMPLATE.md index eb01068..39bf037 100644 --- a/docs/guidelines/ISSUE_TEMPLATE.md +++ b/docs/ISSUE_TEMPLATE.md @@ -2,7 +2,7 @@ #### **Review this checklist before filing an issue:** -- [ ] Is this something you can **debug and fix**? Send a [pull request](/docs/guidelines/PULL_REQUEST_TEMPLATE.md)! Bug fixes and documentation fixes are always welcome. +- [ ] Is this something you can **debug and fix**? Send a [pull request](/docs/PULL_REQUEST_TEMPLATE.md)! Bug fixes and documentation fixes are always welcome. - [ ] Have a usage question? Please label your issue as "question". - [ ] Have an idea for a feature? Please label your issue as "enhancement". diff --git a/docs/guidelines/PULL_REQUEST_TEMPLATE.md b/docs/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from docs/guidelines/PULL_REQUEST_TEMPLATE.md rename to docs/PULL_REQUEST_TEMPLATE.md diff --git a/docs/guidelines/STRUCTURE.md b/docs/STRUCTURE.md similarity index 86% rename from docs/guidelines/STRUCTURE.md rename to docs/STRUCTURE.md index 1960f1f..658fdc7 100644 --- a/docs/guidelines/STRUCTURE.md +++ b/docs/STRUCTURE.md @@ -3,8 +3,7 @@ - **.gitignore**: list of files and directories to be ignored by git - **conv2mp4-ps.ps1**: Main executable script - **README.md**: Main readme documentation -- **docs**: Contains script documentation - - **guidelines**: Contains code contribution guidelines and templates +- **docs**: Contains script documentation, code contribution guidelines, and templates - **files**: Contains all other script-related files - **cfg**: Contains configuration-related files - `config.template` diff --git a/files/func/CloneStereoStream.ps1 b/files/func/CloneStereoStream.ps1 index 877db00..d502ebd 100644 --- a/files/func/CloneStereoStream.ps1 +++ b/files/func/CloneStereoStream.ps1 @@ -8,9 +8,11 @@ Function CloneStereoStream { If ($copyStereo) { mkdir $($prop.tmp_dir) -Force + $ffmpeg = Join-Path $cfg.fmmpeg_bin_dir "ffmpeg.exe" + #ffmpeg pull audio track from file $ffmpegArgs = "-i " - $ffmpegArgs += "$targetFileRenamed " + $ffmpegArgs += "$targetFile " $ffmpegArgs += "-vn " $ffmpegArgs += "-acodec " $ffmpegArgs += "copy " @@ -26,7 +28,7 @@ Function CloneStereoStream { $ffmpegCMD = cmd.exe /c "$ffmpeg $ffmpegArgs" #Rename original source file, necessary to avoid corrupting by using same file as input and output - Move-Item $targetFileRenamed $tempFileName -Force + Move-Item $targetFile $tempFileName -Force #ffmpeg inject stereo audio track back into file $ffmpegArgs = "-y " @@ -42,7 +44,7 @@ Function CloneStereoStream { $ffmpegArgs += "copy " $ffmpegArgs += "-metadata:s:a " $ffmpegArgs += "handler=Stereo " - $ffmpegArgs += "$targetFileRenamed" + $ffmpegArgs += "$targetFile" $ffmpegCMD = cmd.exe /c "$ffmpeg $ffmpegArgs" Remove-Item $tempFileName -Force diff --git a/files/func/ConvertFile.ps1 b/files/func/ConvertFile.ps1 index 5af208d..6948289 100644 --- a/files/func/ConvertFile.ps1 +++ b/files/func/ConvertFile.ps1 @@ -68,8 +68,15 @@ Function ConvertFile { $ffArgs += "`"$sourceFile`" " #Input file $ffArgs += "-threads " #Flag to set maximum number of threads (CPU) to use $ffArgs += "6 " #Maximum number of threads (CPU) to use + $ffArgs += "-movflags" + $ffArgs += "+faststart" If ($cfg.use_set_metadata_title){ + $remove= $title | Select-String -Pattern '^(.*?)(19|20)[0-9]{2}(.*$)' | ForEach-Object { "$($_.matches.groups[3])" } + $title = $title -replace "$remove",'' + $title = $title -replace '\W',' ' + $title = $title -replace '(\d{4})$', '($1)'; + $ffArgs += "-metadata " #Flag to specify key/value pairs for encoding metadata $ffArgs += "title=`"$title`" " #Use $title variable as metadata 'Title' } diff --git a/files/func/GetAudioStreams.ps1 b/files/func/GetAudioStreams.ps1 index 228330e..554fbb8 100644 --- a/files/func/GetAudioStreams.ps1 +++ b/files/func/GetAudioStreams.ps1 @@ -1,6 +1,9 @@ Function GetAudioStreams { - $ffprobeArgs = "-i " - $ffprobeArgs += "`"$targetFileRenamed`" " + $ffprobe = Join-Path $cfg.fmmpeg_bin_dir "ffprobe.exe" + + $ffprobeArgs += "-v " + $ffprobeArgs += "error " + $ffprobeArgs += "`"$targetFile`" " $ffprobeArgs += "-show_entries " $ffprobeArgs += "stream=channels " $ffprobeArgs += "-select_streams " @@ -11,7 +14,7 @@ Function GetAudioStreams { [int[]] $audioStreamArray = cmd.exe /c "$ffprobe $ffprobeArgs" #If last channel is not stereo, create one - If ($audioStreamArray[$audioStreamArray.Length-1] -ne 2) { + If ($audioStreamArray[$audioStreamArray.Length-1] -gt 2 ) { return $True } #If not, skip stream clone diff --git a/files/func/PrintEncodeError.ps1 b/files/func/PrintEncodeError.ps1 index 16032a7..265a914 100644 --- a/files/func/PrintEncodeError.ps1 +++ b/files/func/PrintEncodeError.ps1 @@ -4,11 +4,12 @@ Function PrintEncodeError { $fileSizeDelta = [Math]::Round($fileSizeDelta, 2) Try { Remove-Item -LiteralPath $targetFile -Force -ErrorAction Stop - Log "$($time.Invoke()) EXCEPTION: New file is over 25% smaller ($($fileSizeDelta)MB). $targetFile deleted." + Log "$($time.Invoke()) EXCEPTION: New file is over 25% smaller ($($fileSizeDelta)MB)." + Log "$($time.Invoke()) $targetFileRenamed deleted." Log "$($time.Invoke()) FAILOVER: Re-encoding $sourceFile with Handbrake." } Catch { - Log "$($time.Invoke()) ERROR: $targetFile could not be deleted. Full error below." + Log "$($time.Invoke()) ERROR: $targetFileRenamed could not be deleted. Full error below." Log $_ } } \ No newline at end of file diff --git a/files/func/PrintEncodeFailure.ps1 b/files/func/PrintEncodeFailure.ps1 index a27bacf..7308388 100644 --- a/files/func/PrintEncodeFailure.ps1 +++ b/files/func/PrintEncodeFailure.ps1 @@ -14,7 +14,8 @@ Function PrintEncodeFailure { encodeFailure { $script:failedEncodes += @($sourceFile) Remove-Item $targetFile -Force -ErrorAction Stop - Log "$($time.Invoke()) ERROR: Failover threshold exceeded even after failover: ($($fileSizeDelta)MB). $targetFile deleted." + Log "$($time.Invoke()) ERROR: Failover threshold exceeded even after failover: ($($fileSizeDelta)MB)." + Log "$($time.Invoke()) $targetFileRenamed deleted." Log "$($time.Invoke()) Deleted new file and retained $sourceFile." } } diff --git a/files/func/PrintStatistics.ps1 b/files/func/PrintStatistics.ps1 index da70453..68fe80b 100644 --- a/files/func/PrintStatistics.ps1 +++ b/files/func/PrintStatistics.ps1 @@ -30,12 +30,34 @@ Function PrintStatistics { Try { $averageConversionRate = $cumulativeVideoDuration.Ticks / $scriptExecutionDuration.Ticks $averageConversionRate = [math]::Round($averageConversionRate, 2) - Log "Average conversion speed of $($averageConversionRate)x" + Log "Average conversion speed of $($averageConversionRate)x`n" } Catch { Log "$_" - Log "No time elapsed." + Log "No time elapsed.`n" } + + #Print process type totals + If ($duplicatesDeleted.Count -ge 1) { + Log "Duplicates deleted: $($duplicatesDeleted.Count)" + } + If ($simpleConversion.Count -ge 1) { + Log "Simple container conversions: $($simpleConversion.Count)" + } + If ($videoConversion.Count -ge 1) { + Log "Video-only encodes: $($videoConversion.Count)" + } + If ($audioConversion.Count -ge 1) { + Log "Audio-only encodes: $($audioConversion.Count)" + } + If ($bothConversion.Count -ge 1) { + Log "Video and audio encodes: $($bothConversion.Count)" + } + If ($fileCompliant.Count -ge 1) { + Log "Compliant files: $($fileCompliant.Count)" + } + + Log "`n$($prop.final_stat_divider)" } Else { diff --git a/files/init/buildqueue.ps1 b/files/init/buildqueue.ps1 index ea039f8..8552ac2 100644 --- a/files/init/buildqueue.ps1 +++ b/files/init/buildqueue.ps1 @@ -5,17 +5,19 @@ Write-Output "`nBuilding file list, please wait. This may take a while, especial If ($cfg.use_ignore_list) { $cfg.include_file_types += ", *.mp4" $fileList = Get-ChildItem "$((Get-Item -Path $cfg.media_path).FullName)" -Include ( $cfg.include_file_types -split ',' ).trim() -Exclude $(Get-Content $prop.ignore_path) -Recurse | - ForEach-Object { - Write-Progress "`rFound $(@($fileList).indexOf($file)+1) file(s) so far..." - $_ - } + ForEach-Object {$counter = 1} { + Write-Progress -Activity "Found $($counter) file(s) so far..." -Status "Processing..." -CurrentOperation "$($_.FullName)" + $_ + $counter++ + } } Else { $fileList = Get-ChildItem "$((Get-Item -Path $cfg.media_path).FullName)" -Include ( $cfg.include_file_types -split ',' ).trim() -Recurse | - ForEach-Object { - Write-Progress "`rFound $(@($fileList).indexOf($file)+1) file(s) so far..." - $_ - } + ForEach-Object {$counter = 1} { + Write-Progress -Activity "Found $($counter) file(s) so far..." -Status "Processing..." -CurrentOperation "$($_.FullName)" + $_ + $counter++ + } } PrintFileQueue \ No newline at end of file diff --git a/files/prop/properties b/files/prop/properties index 40d8961..1d05387 100644 --- a/files/prop/properties +++ b/files/prop/properties @@ -1,5 +1,5 @@ #Version -version=4.0 +version=4.1 platform=ps #URLs