Jump to content

DTS to EAC3 Script for 2018+ TVs


siddhartha

Recommended Posts

siddhartha

Newer Samsung TVs won't support DTS passthrough on MKV files. The following Bash script will convert the file to EAC3 if it's either TrueHD, DTS, FLAC, or has PGS subtitles. This assumes you have ffmpeg installed. It can be modified to work with your favourite torrent client to be an automated process. If you are using it as an automated script, it's worth while to sleep 10 before checking for file locks.

 

Note that there is a small bug that will happen if the a TrueHD/DTS/FLAC audio stream of a file is at a higher index than a PGS subtitle stream. This happens because of the way ffmpeg maps input streams and references output streams. If you run into this bug, the solution is to simply run the script again on the output file.

 

Enjoy.

 

Windows version here.

 

#!/bin/bash

file=$1
tmp=temp.mkv

# Check if the file is open
lsof | grep "${file}" >/dev/null 2>&1 ||

(
    # Check if the file is encoded with DTS or TrueHD or PGS
    probe=$(ffprobe -i "${file}" 2>&1) &&
    (
        echo "${probe}" | grep -Eq "Audio: (truehd|dts)" ||
        echo "${probe}" | grep -Eq "Subtitle: pgs"
    ) &&

    # Create a subtitle stream that exludes all PGS streams
    substream=$(echo "${probe}" | grep -E "Subtitle: pgs" | sed -E 's/.*(0:[0-9]+).*/-map -0:\1/' | tr '\n' ' ') &&
    echo "substream=${substream}" &&

    # Only convert DTS, TrueHD, and FLAC streams to EAC3
    acstream=$(echo "${probe}" | grep -E "Audio: (truehd|dts|flac)" | sed -E 's/.*0:([0-9]+).*/-c:\1 eac3 -ac:\1 6 -b:\1 1536k/' | tr '\n' ' ') &&
    echo "acstream=${acstream}" &&

    # Convert!
    ffmpeg -i "${file}" -map 0 ${substream} -c:a copy ${acstream} -c:v copy -c:s copy -f matroska temp.mkv &&

    # Replace the original mkv with the newly converted file
    mv "${temp}" "${file}"
)
Edited by siddhartha
  • Like 2
Link to comment
Share on other sites

  • 5 months later...
siddhartha

This looks brilliant, thanks. Could you show how to use it with utorrent please ?

 

I don't use uTorrent, but I do use Deluge and  Flexget. I run the script automatically on every completed download.

 

For uTorrent, I believe there were flags passed to the batch file like %D %N which correspond to the directory and filename. I would check the documentation. If you're running Windows, the parameters for ffmpeg will likely be the same.

 

 

The full version of my script is here:

 

#!/bin/bash

# Sort torrents using flexget and process with ffmpeg to MKV files for Direct Play on 2018+ Samsung TVs
# Updated 2019.12.15

torrentid=$1
torrentname=$2
torrentpath=$3

moviespath=/srv/media/downloads/movies
tvseriespath=/srv/media/downloads/tv
incomingpath=/srv/media/downloads/incoming
logfile=/var/lib/deluged/scripts/torsort.log
tempsuffix=".EAC3REENC"

log () {
    echo $(date '+%Y-%m-%d %H:%M:%S') $1 >>${logfile}

}

if [[ ${torrentpath} != ${moviespath} && ${torrentpath} != ${tvseriespath} ]]; then
    exit 0
fi

# Sleep for a few seconds to free up any locks
sleep 10

files=()

while IFS= read -r -d $'\0'; do
    files+=("$REPLY")
done < <(find "${torrentpath}" -name "*.mkv" -print0)

for file in "${files[@]}"; do
    # Check if the file is open
    lsof | grep "${file}" >/dev/null 2>&1 ||
    (
         # Check if the file is encoded with DTS, TrueHD, FLAC, or PGS
         probe=$(ffprobe -i "${file}" 2>&1) &&
         (
             echo "${probe}" | grep -Eq "Audio: (truehd|dts|flac)" ||
             echo "${probe}" | grep -Eq "Subtitle: pgs"
         ) &&
         (
             # Move the file to a temporary directory
             mv "${file}" "${incomingpath}" &&
             log "mv '${file}' to '${incomingpath}'"

             # Create a subtitle stream that exludes all PGS streams
             substream=$(echo "${probe}" | grep -E "Subtitle: pgs" | sed -E 's/.*(0:[0-9]+).*/-map -0:\1/' | tr '\n' ' ') &&
             log "substream='${substream}'"

             # Only convert TrueHD, DTS, and FLAC streams to EAC3
             acstream=$(echo "${probe}" | grep -E "Audio: (truehd|dts|flac)" | sed -E 's/.*0:([0-9]+).*/-c:\1 eac3 -ac:\1 6 -b:\1 1536k/' | tr '\n' ' ') &&
             log "acstream='${acstream}'"

             # Encode the audio as EAC3 to the original path
             # Use a temporary suffix so the open file isn't touched by flexget
             log "ffmpeg '${file}${tempsuffix}'"
             ffmpeg -i "${incomingpath}/$(basename "${file}")" -map 0 ${substream} -c:a copy ${acstream} -c:v copy -c:s copy -f matroska "${file}${tempsuffix}" &&

             log "Cleaning up"
             # Remove the temporary file
             rm -f "${incomingpath}/$(basename "${file}")" &&

             # Remove the temporary suffix
             mv "${file}${tempsuffix}" "${file}"
         )
    )
done

case "$torrentpath" in
    "$moviespath")
        /usr/local/bin/flexget -c /etc/flexget/config.yml execute --tasks sort_movies
        ;;
    "$tvseriespath")
        /usr/local/bin/flexget -c /etc/flexget/config.yml execute --tasks sort_tv_series
        ;;
    *)
        exit 0
        ;;
esac
The relevant part of my flexget config.yml is:

 

tasks: 
  sort_tv_series:
    no_entries_ok: yes
    parsing:
      series: guessit
    metainfo_series: yes
    disable:
      - seen
      - seen_info_hash
    template: tv_series
    series:
      settings:
        webrip+ 720p+:
          parse_only: yes
    filesystem:
      path: '{? filesystem.complete_tv ?}'
      regexp: '.*\.(avi|mkv|mp4)$'
      recursive: yes
    regexp:
      reject:
        - '^sample'
        - '.*-sample.*'
        - '.*\.sample$'
    require_field: series_name
    accept_all: yes
    move:
      to: '{? filesystem.series_path ?}'
      clean_source: 350
      along:
        extensions:
          - sub
          - srt
          - idx
        subdirs:
          - subs
          - subtitles

  sort_movies:
    no_entries_ok: yes
    disable:
      - seen
      - seen_info_hash
    filesystem:
      path: '{? filesystem.complete_movies ?}'
      regexp: '.*\.(avi|mkv|mp4)$'
      recursive: yes
    regexp:
      reject: 
        - '^sample'
        - '.*-sample.*'
        - '.*\.sample$'
    accept_all: yes
    move:
      to: '{? filesystem.movies_path ?}'
      clean_source: 350
      along:
        extensions:
          - sub
          - srt
          - idx
        subdirs:
          - subs
          - subtitles

Edited by siddhartha
Link to comment
Share on other sites

holdestmade

 

 

Thanks for the reply, the new emby update plays DTS on the fly now so don't need to do any post processing

 

Cheers

Edited by holdestmade
Link to comment
Share on other sites

  • 4 months later...
siddhartha

I still much prefer to have Emby direct play MKV files since transcoding puts unnecessary load on the CPU. I've updated the script to copy over any non-PGS subtitle tracks (as PGS subtitles seem to be an issue for Samsung TVs) and the script now copies over any playable audio tracks, only converting DTS and TrueHD audio. It's been perfect for the year I've been using it.

  • Like 1
Link to comment
Share on other sites

FrostByte

I still much prefer to have Emby direct play MKV files since transcoding puts unnecessary load on the CPU. I've updated the script to copy over any non-PGS subtitle tracks (as PGS subtitles seem to be an issue for Samsung TVs) and the script now copies over any playable audio tracks, only converting DTS and TrueHD audio. It's been perfect for the year I've been using it.

 

 

Agree, plus the higher bitrate DD+ sounds a lot better (as long as your soundbar supports it) than DD I think

Link to comment
Share on other sites

  • 4 weeks later...
siddhartha

@@siddhartha Thank You for the effort of creating this script. Would it be possible for you to make similar one but for Windows ffmpeg?

I'm actually not that versed in PowerShell, but I'll take a look.

Link to comment
Share on other sites

iceman81

Thanks for your effort.

I have encountered this error:

 

.\ffprobe.exe : The term '.\ffprobe.exe' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\eac3conv\eac3conv.ps1:3 char:9
+ $probe=(.\ffprobe.exe "$file" 2>&1)
+         ~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (.\ffprobe.exe:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

The same with grep.exe and next with ffmpeg.exe

  • Like 1
Link to comment
Share on other sites

siddhartha

Thanks for your effort.

I have encountered this error:

 

 

.\ffprobe.exe : The term '.\ffprobe.exe' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\eac3conv\eac3conv.ps1:3 char:9
+ $probe=(.\ffprobe.exe "$file" 2>&1)
+         ~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (.\ffprobe.exe:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
The same with grep.exe and next with ffmpeg.exe

 

I've modified the attachment in the post to fix the issue. Thanks for the tip! (This happened if the source MKV was outside the eac3conv directory)

Edited by siddhartha
  • Like 3
Link to comment
Share on other sites

  • 2 weeks later...
fredosp87

hello, I find your script great it works super well, I would like to know how to make a waiting list of mkv file so that they convert to the following

 

thanks

 

I’m French and my English is limited sorry for the vocabulary

Link to comment
Share on other sites

iceman81

hi @@siddhartha recently i've noticed that when movie filename have spaces in it the script gives an error.

Thats not a big deal though  to change the name temporary for conversion.

Link to comment
Share on other sites

  • 2 months later...
xzilvinas

Okay, I think I have a working Windows version. You need to download ffmpeg.exe and ffprobe.exe and place them in the eac3conv folder.

 

To use the script, just drag and drop an MKV file onto eac3conv.bat.

 

attachicon.gifeac3conv11.7z

This is awesome tool since i got useless samsung 4k tv that wont read dts, thanks very much.

 

But there is one bug, there a problem when you drop a file that has spaces in the title or folder has spaces where the file is.

 

 

S:\Downloads\Good: No such file or directory

mv : Cannot find path 'S:\eac3conv\temp.mkv' because it does not exist.

At S:\eac3conv\eac3conv.ps1:13 char:1

+ mv temp.mkv ($path + '\' + $basename + '.eac3.mkv')

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : ObjectNotFound: (S:\eac3conv\temp.mkv:String) [Move-Item], ItemNotFoundException

    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.MoveItemCommand

 

PS S:\eac3conv>

 

For example if the file name is Good Boys 2019 1080p Hybrid WEBRip DTS x264-RightSiZE.mkv and i drag and drop it on eac3conv.bat there is this error, but if i change all the spaces to dots(.), then all is fine, same apply to directory if folder where the file is also has spaces in name, it will give same error.

Edited by xzilvinas
Link to comment
Share on other sites

  • 1 month later...
Synthetic

Hey sorry to drag up an old thread, works great thanks, however i'm wondering if it's possible to amend the windows script so rather than replace the DTS stream, it adds a second EAC3 stream?

 

Thanks! 

Link to comment
Share on other sites

  • 3 months later...
On 1/2/2020 at 9:24 AM, iceman81 said:

i've noticed that when movie filename have spaces in it the script gives an error.

 

On 3/27/2020 at 12:21 AM, xzilvinas said:

there a problem when you drop a file that has spaces in the title or folder has spaces where the file is.

@iceman81 @xzilvinas and to all others. To fix this bug with script not working properly with filenames with spaces just change in eac3conv.ps1

iex ".\ffmpeg.exe -i $file -map 0$substream -c:a copy $acstream -c:v copy -c:s copy -f matroska temp.mkv"

to

iex ".\ffmpeg.exe -i '$file' -map 0$substream -c:a copy $acstream -c:v copy -c:s copy -f matroska temp.mkv"

The problem is solely because of the absence of single quotes.

Best regards!

Edited by WINTEX
  • Like 1
Link to comment
Share on other sites

  • 1 month later...
rbjtech

Nice script - an alternative to creating a new file, is to simply insert the eac3 track into the existing MKV.

You need to remap a few tracks but essentially this is the syntax -

"ffmpeg.exe"  -i "input.mkv" -map 0:v -map 0:a:0 -map 0:a  -c:v copy -c:a copy -c:a:0 eac3 -disposition:a:0 default -disposition:a:1 0 "output.mkv"

It will mark the eac3 as the new default audio track, moving the previous audio track to 2nd in the drop down list.

 

 

  • Like 1
Link to comment
Share on other sites

  • 3 months later...
xzilvinas
On 8/25/2020 at 12:55 AM, WINTEX said:

 

@iceman81 @xzilvinas and to all others. To fix this bug with script not working properly with filenames with spaces just change in eac3conv.ps1

iex ".\ffmpeg.exe -i $file -map 0$substream -c:a copy $acstream -c:v copy -c:s copy -f matroska temp.mkv"

to

iex ".\ffmpeg.exe -i '$file' -map 0$substream -c:a copy $acstream -c:v copy -c:s copy -f matroska temp.mkv"

The problem is solely because of the absence of single quotes.

Best regards!

thanks for help,

But maybe you also know how to make batch? I like to convert like 10+ videos, how can i make this script convert whole folder? Or maybe someone else have suggestion?

Link to comment
Share on other sites

On 8/24/2020 at 4:55 PM, WINTEX said:

 

@iceman81 @xzilvinas and to all others. To fix this bug with script not working properly with filenames with spaces just change in eac3conv.ps1

iex ".\ffmpeg.exe -i $file -map 0$substream -c:a copy $acstream -c:v copy -c:s copy -f matroska temp.mkv"

to

iex ".\ffmpeg.exe -i '$file' -map 0$substream -c:a copy $acstream -c:v copy -c:s copy -f matroska temp.mkv"

The problem is solely because of the absence of single quotes.

Best regards!

Wow. First of all, I don't really speak english, but this was a great solution for me. I just want to convert DTS / TrueHD to eAC3 and the only option I had was Handbrake (which does not allow direct copy function in video). With this script, ¡problem solved! Thanks a lot :)

Link to comment
Share on other sites

  • 5 months later...
mrprivate
On 1/13/2021 at 7:55 PM, xzilvinas said:

thanks for help,

But maybe you also know how to make batch? I like to convert like 10+ videos, how can i make this script convert whole folder? Or maybe someone else have suggestion?

it could be nice to be able to batch convert

Link to comment
Share on other sites

rbjtech

A simple batch script below in red - just paste into a new notepad file called convert.bat.  copy into the folder you wish to run it from - and all subfolders will be processed.  if you wish to delete the original file - then just remove the 'rem' from the delete line, otherwise the original will be kept.  Remember to change the path to ffmpeg.

edit - note the script just uses the first audio track it finds to make the new eac3 audio track (and make it the default) - it does not apply any sort of logic or intelligence. ;)

edit 2 - eac3 bitrate is 256k - according to dolby themselves (see below) this is sufficient. (DTS (5.1) > EAC3)

https://developer.dolby.com/technology/dolby-audio/dolby-digital-plus/

 

@echo off

FOR /F "delims=" %%x in ('dir /a-s /b /s *.mkv') DO (

    "<YOUR_EMBY_PATH_FFMPEG_LOCATION>ffmpeg.exe" -i "%%x" -map 0:v -map 0:a:0 -map 0:a  -c:s copy -c:v copy -c:a copy -c:a:0 -b:a 256k eac3 -disposition:a:0 default -disposition:a:1 0 -f matroska "%%~dx%%~px%%~nx-EAC3.mkv"

rem    del /q "%%~dx%%~px%%~nx.mkv"

    )

 

 

Edited by rbjtech
  • Like 1
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...