Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename Audio #362

Open
DJ-BrianC opened this issue Oct 25, 2023 · 4 comments
Open

Rename Audio #362

DJ-BrianC opened this issue Oct 25, 2023 · 4 comments

Comments

@DJ-BrianC
Copy link

DJ-BrianC commented Oct 25, 2023

What is your new plugin request?

I have many video files with unknown audio. It would be nice to be able to map unknown audios to English. Just a cosmetic issue but it's anoying to see that when the audio is correct. I've been able to do it file by file with makemkv edit header but 1x1 is VERY tedious and slow.

Additional Context

No response

@yajrendrag
Copy link
Contributor

You want to relabel any audio stream marked as "und" as "eng" instead? what if it's not really "eng"? Or is it that you know they are "eng" but they just just need to be correctly marked?

@DJ-BrianC
Copy link
Author

That is correct. Like I said I already know that the audio was correct because I've watched most of the movies that I have. I just like to fix this cosmetic issue as a batch rather than a 1x1 which is very tedious.

@yajrendrag
Copy link
Contributor

yajrendrag commented Dec 14, 2023

so, i started a plugin to do this, but i have no mkv files that have "und" tagged language streams, and oddly when i went to edit one (using ffmpeg or mkvpropedit), i can execute the command, but it simply wipes out the language tag. So net/net, i have no way to test it.

so here are 2 options - i can make the plugin available for you to try, OR, here is a bash shell script that you can run in your library that will make the changes. In EITHER case i would suggest making a test directory/library with a couple of files that you can try this on.

You can run these command interactively or put it in a shell script.

shopt -s globstar
for file in **/*.mkv; do as=$(ffprobe -v quiet -select_streams a -show_entries stream=index:stream_tags=language -of csv=p=0:nk=1 "$file"); if [[ "$as" =~ .*"und".* ]]; then for j in $as; do stream=$(echo "$j" | awk -F"," '{ print $1 + 1 }'); stream_lang=$(echo "$j" | awk -F"," '{ print $2 }'); if [[ "$stream_lang" == "und" ]]; then mkvpropedit "$file" --edit track:$stream --set language=eng; fi; done; fi; done
shopt -u globstar

For testing, i would put this/run this in a directory that only has a few test files in it. (cd to the directory you wish to run in - it will grab mkv files at that level and below). If you navigate to the root of your library and run it, it will select ALL mkv files in your library. This is the globstar functioning like this - without this it gets a little more complex to find all the mkv files and put them in an array and process them all. It equates to the same thing, but this is simpler to code.

@phobiac
Copy link

phobiac commented Jul 10, 2024

#!/bin/bash
# Input directory
dir=$1
set_lang=${2:-eng}
search_lang=${3:-und}

find "$dir" -type f -iname "*.mkv" \
        -execdir sh -c ' \
                set_lang=$1;
                search_lang=$2;
                mkvmerge -J "{}" | jq ".tracks[] | select(.type == \"audio\") | select(.properties.language == \"$search_lang\") | .properties.language" \
                | grep -q "$search_lang";
        ' {} "$set_lang" "$search_lang" \; \
        -execdir sh -c ' \
                set_lang=$1;
                search_lang=$2;
                audio_track_count=$(mkvmerge -J "{}" | jq ".tracks[] | select(.type == \"audio\") | select(.properties.language == \"$search_lang\") | .type" | wc -l);
                if [ "audio_track_count" -eq "1" ]
                then
                        track_id=1
                else
                        track_id=$(mkvmerge -J "{}" | jq ".tracks[] | select(.type == \"audio\") | select(.properties.language == \"$search_lang\") | .id" | head -n 1);
                fi;
                echo "Track [$track_id] to [$set_lang] on "$(basename "{}");
                mkvpropedit -v "{}" --edit track:a"$track_id" --set language="$set_lang";
        ' {} "$set_lang" "$search_lang" \; \
#-printf '%p\n'

# Manual commands
# FILE=""
# mkvmerge -J "$FILE" | jq ".tracks[] | select(.type == \"audio\")"
# find "$FILE" -type f -iname "*.mkv" -execdir sh -c 'mkvmerge -J "{}" | jq ".tracks[] | select(.type == \"audio\") | .properties.language"' {} \; -printf "%P\n"
# mkvpropedit -v "$FILE" --edit track:a1 --set language="eng"

# ffprobe way
# replaces first execdir #              ffprobe -v quiet -select_streams a -show_entries stream_tags=language -of csv=p=1:nk=0 "{}" | grep -q -w "stream,"
# replaces track #                      ffprobe -v quiet -select_streams a -show_entries stream=index -of csv=p=0:nk=1 "{}"

I've been playing with a solution for this same issue with my own files and wanted to share the above script I ended up going with.
I originally wanted it to be contained within the unmanic docker container using the mkvpropedit plugin available in the repos. This should be able to be done using the above commands and the ffprobe plugin for file identification, though I'm probably just going to use the script and target specific files or folders.

I ended up finding a way to accomplish the file searching using ffprobe but also an alternative using mkvmerge that makes this script dependent entirely on the mkvinfo tools. The script by default is using the mkverge method. The main source of confusion I found was that ffprobe does NOT return und but instead returns a null so I'm taking advantage of the csv output to get a result that is more easily searchable. mkvmerge does return und when a tag is undefined.

It should be noted this search is a bit fragile. It's expecting your files to have only 1 audio track that's got an undefined language. It's pretty basic to run. I've named mine audiofixer.sh and you can run it as audiofixer.sh $FileOrFolder $SetLang $SearchLang where $FilerOrFolder is a path, and $SetLang/$SearchLang are any language code like eng, jpn, spa. The script will default to eng as the language to set and und as the language to search for if they are not provided. I also highly suggest commenting out the mkvpropedit line first and running a dry run against any files you want to modify just to be sure the output makes sense, or use the list of manual commands to get an idea of the changes the script would make before running it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants