sjigoow 4 Posted January 6, 2017 Posted January 6, 2017 (edited) Hello forum members, I am using Emby for a few days now, and my not very powerful Atom Windows server can't encode 2 users on-the-fly. For that reason I wanted to convert my entire video library to h264+aac mp4 files. I couldn't find any program that converts a folder+subfolders automatically, so I made a simple vbs file that does. So for everyone with the same problem, this is the code: Option Explicit Const ForWriting = 2 Dim objFSO, oShell, curFile, curName, curExt, curFol, tempNum, tempFn, param, fullCom, baseFol Set objFSO = CreateObject("Scripting.FileSystemObject") Set oShell = CreateObject ("WScript.Shell") Recurse objFSO.GetFolder(oShell.CurrentDirectory) Sub Recurse(objFolder) Dim objFile, objSubFolder For Each objFile In objFolder.Files If ((LCase(objFSO.GetExtensionName(objFile.Name)) = "mkv") OR (LCase(objFSO.GetExtensionName(objFile.Name)) = "mp4") OR (LCase(objFSO.GetExtensionName(objFile.Name)) = "avi") OR (LCase(objFSO.GetExtensionName(objFile.Name)) = "wmv") OR (LCase(objFSO.GetExtensionName(objFile.Name)) = "m4v") OR (LCase(objFSO.GetExtensionName(objFile.Name)) = "m4p") OR (LCase(objFSO.GetExtensionName(objFile.Name)) = "mpg") OR (LCase(objFSO.GetExtensionName(objFile.Name)) = "mpeg") OR (LCase(objFSO.GetExtensionName(objFile.Name)) = "3gp")) Then curFile = objFile.Path curName = Replace(objFile.Name,"." & objFSO.GetExtensionName(objFile.Path),"") curExt = objFSO.GetExtensionName(objFile.Name) curFol = objFolder tempFn = "temp_" & curName & "." & curExt objFSO.GetFile(curFile).Name = tempFn param = "-i """ & curFol & "\" & tempFn & """ -o """ & curFol & "\" & curName & ".mp4"" -f av_mp4 -O -e x264 -E av_aac -X 1280 -Y 720" fullCom = """C:\Program Files\HandBrake\HandBrakeCLI.exe """ & param oShell.run fullCom, 1, true objFSO.DeleteFile(curFol & "\" & tempFn) End If Next For Each objSubFolder In objFolder.SubFolders Recurse objSubFolder Next End Sub A vbs file with this script is in the zip in the attachment. Usage: Place the file in the folder that you want to convert, and dubble click it. It converts mkv, mp4, avi, wmv, m4v, m4p, mpg, mpeg and 3gp files using the handbrake cli, so having that installed is a requirement. Change 'C:\Program Files\HandBrake\HandBrakeCLI.exe' to the path of the 'HandBrakeCLI.exe' file. Note the space after the file path, this should not be removed! Note: It also converts mp4 files that are alread in the correct format! The script does not check the file. It is very basic. Another very important note; THIS SCRIPT DELETES THE ORIGINAL FILE. Place a ' in front of the line 'objFSO.DeleteFile(curFol & "\" & tempFn)' to prevent that from happening. The original file will have its original name with 'temp_' in front of it. Questions are welcome. Feel free to edit the code and post the updated version here. I know the currect code is very basic but it is good enough for me. Hope to help someone with this Edit: The max resolution it converts to is 1280x720 (720p). If the input file has a lower resolution it will keep the same resolution. Aspect ratio will always be the same in the output file. Encode_sub_dir.zip Edited January 6, 2017 by sjigoow 2
mastrmind11 722 Posted January 6, 2017 Posted January 6, 2017 Pretty cool, but the built in Sync feature of the server already does this
sjigoow 4 Posted January 6, 2017 Author Posted January 6, 2017 That's true, but you need a premium account for that. I want to make sure my NAS works good before putting more money in it.
x88dually 9 Posted January 12, 2017 Posted January 12, 2017 How could you make it to add 5.1 sound and 1920x1080 ??
sjigoow 4 Posted January 12, 2017 Author Posted January 12, 2017 (edited) Simply changing '720' to '1080', '1280' to '1920' should do the trick for the resolution. HandbrakeCLI however tells me that AAC only goes up to 2.0 audio. To be able to use 5.1, the used codec should be 'ac3', 'eac3', 'flac16', 'flac24' or 'opus'. To go up to 7.1, you should use one of the last 3 options. Option Explicit Const ForWriting = 2 Dim objFSO, oShell, curFile, curName, curExt, curFol, tempNum, tempFn, param, fullCom, baseFol Set objFSO = CreateObject("Scripting.FileSystemObject") Set oShell = CreateObject ("WScript.Shell") Recurse objFSO.GetFolder(oShell.CurrentDirectory) Sub Recurse(objFolder) Dim objFile, objSubFolder For Each objFile In objFolder.Files If ((LCase(objFSO.GetExtensionName(objFile.Name)) = "mkv") OR (LCase(objFSO.GetExtensionName(objFile.Name)) = "mp4") OR (LCase(objFSO.GetExtensionName(objFile.Name)) = "avi") OR (LCase(objFSO.GetExtensionName(objFile.Name)) = "wmv") OR (LCase(objFSO.GetExtensionName(objFile.Name)) = "m4v") OR (LCase(objFSO.GetExtensionName(objFile.Name)) = "m4p") OR (LCase(objFSO.GetExtensionName(objFile.Name)) = "mpg") OR (LCase(objFSO.GetExtensionName(objFile.Name)) = "mpeg") OR (LCase(objFSO.GetExtensionName(objFile.Name)) = "3gp")) Then curFile = objFile.Path curName = Replace(objFile.Name,"." & objFSO.GetExtensionName(objFile.Path),"") curExt = objFSO.GetExtensionName(objFile.Name) curFol = objFolder tempFn = "temp_" & curName & "." & curExt objFSO.GetFile(curFile).Name = tempFn param = "-i """ & curFol & "\" & tempFn & """ -o """ & curFol & "\" & curName & ".mp4"" -f av_mp4 -O -e x264 -E ac3 -6 5point1 -X 1920 -Y 1080" fullCom = """C:\Program Files\HandBrake\HandBrakeCLI.exe """ & param oShell.run fullCom, 1, true objFSO.DeleteFile(curFol & "\" & tempFn) End If Next For Each objSubFolder In objFolder.SubFolders Recurse objSubFolder Next End Sub objFSO.DeleteFile(WScript.ScriptFullName) Few things to note: 1. If your input file has a resolution lower than 1920px x 1080px the resolution of the output file will be the same as the input file. 2. This script was slightly changed. The last line causes the script to delete itself when it's done. I found that to be easier, but you need to make sure always to have a backup. Let's take a look at the line param = "-i """ & curFol & "\" & tempFn & """ -o """ & curFol & "\" & curName & ".mp4"" -f av_mp4 -O -e x264 -E ac3 -6 5point1 -X 1920 -Y 1080" This is the line that contains the parameters with which HandbrakeCLI knows what to do. As you can see, it currently encodes video with the 'x264' encoder (-e x264). Change that to (-e x265) to encode with the 'x265' encoder. (hope that answers your question in your pm.) Next we see it encodes audio with the 'ac3' encoder (-E ac3). Note the difference in uppercase/lowercase. Changing that to one of the encoders in the second line of this message changes the audio encoder accordingly ('ac3' should be 'av_aac' for aac). The next part (-6 5point1) tells handbrake that the audio should be encoded to 5.1 chanels. Removing this will keep the original chanels. Aac can't go higher than 2.0! '-X 1920 -Y 1080' speaks for itself. Hope to have helped someone with this. I am certainly not an expert, keep that in mind. Edited January 13, 2017 by sjigoow 1
sjigoow 4 Posted January 12, 2017 Author Posted January 12, 2017 Why would you want to use x265 and 5.1 sound btw? The idea behind this script was to convert my library to a format that almost any player can decode, so my server won't have to encode it all on-the-go.
x88dually 9 Posted January 16, 2017 Posted January 16, 2017 I guess i was thinking wrong,[convert my library,(13,000+ videos) automatically].
x88dually 9 Posted January 16, 2017 Posted January 16, 2017 (edited) Change 'C:\Program Files\HandBrake\HandBrakeCLI.exe' to the path of the 'HandBrakeCLI.exe' file. Note the space after the file path, this should not be removed! Wouldnt that be the same path ? Win7 and Win8.1 About how many days does the re-encoding take ? Edited January 16, 2017 by x88dually
Latchmor 584 Posted January 16, 2017 Posted January 16, 2017 For anyone unsure about doing this (and you should be careful), create a test folder and copy several files there and use the script. This will help you find out if it works on your system, how long it takes and if you like the results.
sjigoow 4 Posted January 16, 2017 Author Posted January 16, 2017 @@x88dually Depends on where you put the file. Converting a small library (about 5 series and 20 movies) costed me like a week. But that was on my super slow server. My laptop (3rd gen i5) usually converts @100fps, meaning that it takes about 1/4th the duration of a movie to convert that movie. Encoding simply costs a lot of processing power, and your cpu will be running @100% when you are converting, just keep that in mind. @@Latchmor True. You can also put a ' in front of this line: objFSO.DeleteFile(curFol & "\" & tempFn) This is the line that deletes the original file. Putting a ' in front of it: 'objFSO.DeleteFile(curFol & "\" & tempFn) keeps the script from deleting it. Your original file will have the text 'temp_' in front of its original file name. 1
x88dually 9 Posted January 17, 2017 Posted January 17, 2017 (edited) So if handbrake installs to default folder, then i shouldnt have to change the path in your file. ? Then your file goes into folder i wanna convert, and double click the db file to make it convert all files in that folder ? So, how do i make the convert media button work within emby ? Edited January 17, 2017 by x88dually
sjigoow 4 Posted January 17, 2017 Author Posted January 17, 2017 HandbrakeCLI isn't installed with Handbrake, it is a seperate package that you can get from https://handbrake.fr/downloads2.php. Put 'HandbrakeCLI.exe' in 'C:\Program Files\HandBrake\' and you're good to go. I don't know what you mean with 'db file'? It's supposed to be a vbs file. Guess you would need a plugin for that. I'm not an Emby expert though. Keep in mind that this script also converts files that are already in the correct format.
x88dually 9 Posted January 18, 2017 Posted January 18, 2017 (edited) Thank You And yes i meant the vbs file. the db was database file. What bitrate does it reencode at ? or is that taken from original file ? or can it be set ? Edited January 18, 2017 by x88dually
sjigoow 4 Posted January 18, 2017 Author Posted January 18, 2017 It reencodes at HandbrakeCLI's standard settings. Not sure what bitrate or quality this is, but I tested it once and it is good enough for me. To change it, you can add parameters to set bitrate or set quality. See https://handbrake.fr/docs/en/latest/cli/cli-guide.html for HandbrakeCLI's guide.
x88dually 9 Posted January 18, 2017 Posted January 18, 2017 (edited) i dont need anything perfect or blue-ray matching quality. i'm looking for good and up, and to shrink my library with 265 with good sound, i'm fine with 48 khz an 2 channel stereo (tv shows, more then 1/2 my library). Movies are a different thing. Thx for the link. Edited January 18, 2017 by x88dually
josephdouce 3 Posted December 20, 2017 Posted December 20, 2017 I modified this to use ffmpeg instead, also would be better to check the codec of the files and only convert non h264 files and just change the container of files that are h264
josephdouce 3 Posted December 21, 2017 Posted December 21, 2017 (edited) you don't need to transcode if its already h264 with aac or mp3 so I wrote a little powershell script the following flags are available -list lists all non mp4 files -transcode transcode all files to h264 + aac in mp4 container if they are not already -container changes container on files that are alreay h264 and aac you can supply the transcode and container flags together, it wont mindlessly transcode files that are already h264 param ( [switch]$list = $false, [switch]$container = $false, [switch]$transcode = $false ) #get all files in the directory recirsivley with included extensions $file_names = Get-Childitem -File -Include *.mkv, *avi -Recurse #create a powershell array $file_info = @() #iterate over the files and get the audio and video codecs for ($i=0; $i -lt $file_names.Count; $i++){ #get the video codec $video_codec = C:\tools\ffmpeg-3.4.1\bin\ffprobe.exe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 $file_names[$i].FullName #get the audio codec $audio_codec = C:\tools\ffmpeg-3.4.1\bin\ffprobe.exe -v error -select_streams a:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 $file_names[$i].FullName #add the properties to a powershell object $file = New-Object -TypeName PSObject $file | Add-Member -Type NoteProperty -Name "Full Name" -Value $file_names[$i].FullName $file | Add-Member -Type NoteProperty -Name "Name" -Value $file_names[$i].Basename $file | Add-Member -Type NoteProperty -Name "Extension" -Value $file_names[$i].Extension $file | Add-Member -Type NoteProperty -Name "Video Codec" -Value $video_codec $file | Add-Member -Type NoteProperty -Name "Audio Codec" -Value $audio_codec #add each ojject to the array $file_info += $file } if ($list) { Write-Host ($file_info | Format-Table -Property "Name", "Extension", "Video Codec", "Audio Codec" | Out-String) } #itterate through the array of files foreach ($file in $file_info){ $video_codec_out = "libx264" $audio_codec_out = "aac" #copy the video stream if it is already h264 if ($file."Video Codec" -eq "h264"){ $video_codec_out = "copy" } #copy the audio stream if it is already aac or mp3 if ($file."Audio Codec" -eq "aac" -or $file."Audio Codec" -eq "mp3"){ $audio_codec_out = "copy" } #dont transcode only change containers if ($container) { if (($video_codec_out -eq "copy") -and ($audio_codec_out -eq "copy")) { #create temp file name $new_file_name = [io.path]::ChangeExtension($file."Full Name", '.mp4') $argument_list = " -i """ + $file."Full Name" + """ -c:v " + $video_codec_out + " -c:a " + $audio_codec_out + " """ + $new_file_name + """ -hide_banner" #start ffmpeg Start-Process -FilePath C:\tools\ffmpeg-3.4.1\bin\ffmpeg.exe $argument_list -Wait -NoNewWindow #delete origional Remove-Item $file."Full Name" } } if ($transcode) { if (($video_codec_out -ne "copy") -or ($audio_codec_out -ne "copy")) { #create temp file name $new_file_name = [io.path]::ChangeExtension($file."Full Name", '.mp4') $argument_list = " -i """ + $file."Full Name" + """ -c:v " + $video_codec_out + " -c:a " + $audio_codec_out + " """ + $new_file_name + """ -hide_banner" #start ffmpeg Start-Process -FilePath C:\tools\ffmpeg-3.4.1\bin\ffmpeg.exe $argument_list -Wait -NoNewWindow #delete origional Remove-Item $file."Full Name" } } } Edited December 21, 2017 by josephdouce
shorage 0 Posted April 29, 2018 Posted April 29, 2018 How would someone use the Sync feature to do this? I want to decrease the size of my library. I would like to just click a series and decrease the size of those media files. Lets say, convert to x265 with a small size parameter. I got some tv series with 6GB size for a 1 hour show, its getting rediculous. I dont wont to create multiple files, i just want to re-encode my library to a more efficient codec (x265) and a low size paramter. Any ideas? Thanks Frank
Luke 42079 Posted April 29, 2018 Posted April 29, 2018 The next release will have a convert feature to help with this.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now