Site Tools


linux:scripts:audiostreamconvert

Convert .mkv Audio

Currently this script will convert any audiostream of a .mkv file to EAC3 768k with the same channels (via ffmpeg), then remux these audiostreams to a new .mkv (via mkvmerge)

Prerequisites

mkvtoolnix - Matroska tools
ffmpeg - Audio conversion tool

While these apps are available via the default repos on Ubuntu, you can get a newer version of mkvtoolnix via their mkvtoolnix - Repo

Usage

Set the following variables inside the script:

# Directory containing the video files
input_dir=“</your/source/folder>“

# Output directory for converted files
output_dir=”</your/target/folder>“

# Temporary directory for AAC audio files
temp_dir=”/tmp/audio_conversion”

# Set new codec
new_codec=“eac3”

# Set new bitrate
new_bitrate=“768k”

If you run the script, it will convert all files inside the “input_dir”, the output file will have all audio streams converted to the set “new_codec” and “new_bitrate” but with the same channels as before. If the original audio stream had 7.1 channels it will be set to 5.1 because ffmpeg EAC3 only supports up to 5.1.

Code

#!/bin/bash
 
# Comment in to see debug messages
#set -x
 
# Directory containing the video files
input_dir="</your/source/folder>"
 
# Output directory for converted files
output_dir="</your/target/folder>"
 
# Temporary directory for EAC3 audio files
temp_dir="/tmp/audio_conversion"
 
# Set new codec
new_codec="eac3"
 
# Set new bitrate
new_bitrate="768k"
 
# Create temporary directory if it doesn't exist
mkdir -p "$temp_dir"
 
# Iterate over video files (MKV) in the input directory
for file in "$input_dir"/*.mkv; do
  # Check if the file is a regular file
  if [ -f "$file" ]; then
    # Get the base filename
    filename=$(basename "$file")
 
    # Print the current file being processed
    echo "Processing file: $filename"
 
    # Extract audio information using ffprobe
    audio_info=$(ffprobe -v error -show_entries stream=index,codec_name,channels:stream_tags=language -select_streams a -of csv=p=0 "$file")
 
    # Split the audio information into an array of streams
    IFS=$'\n' read -rd '' -a streams <<< "$audio_info"
 
    # Create an array to store the temporary EAC3 audio files
    temp_files=()
 
    # Create an array to store the languages for mkvpropedit
    languages=()
 
    # Iterate over the audio streams
    for stream in "${streams[@]}"; do
      IFS=',' read -ra stream_info <<< "$stream"
      index=${stream_info[0]}
      codec=${stream_info[1]}
      channels=${stream_info[2]}
      language=${stream_info[3]}
 
      # Print the current audio stream information
      echo "Audio Stream $index:"
      echo "Codec: $codec"
      echo "Channels: $channels"
      echo "Bitrate: 768 kbps"
      echo "Language: $language"
 
      # If channels equal 8, change it to 6 (7.1 EAC3 is currently not supported by ffmpeg)
      if [ "$channels" -eq 8 ]; then
            channels="6"
      fi
 
      # If language is not set, dont set any metadata, if it is set then set the correct option
      if [ -z "$language" ]; then
        lang1=""
        lang2=""
      else
        lang1="-metadata:s:a:0 language=$language"
        lang2="--edit track:a$index --set language=$language "
      fi
 
      # Create a temporary EAC3 audio file with a fixed bitrate of 768 kbps
      temp_eac3_file="$temp_dir/${filename%.*}_stream_$index.eac3"
      ffmpeg -i "$file" -map 0:$index $lang1 -c:a $new_codec -b:a $new_bitrate -ac $channels "$temp_eac3_file"
 
      # Construct the temporary EAC3 audio files for mkvmerge
      temp_files+=("$temp_eac3_file")
 
      # Construct the audio stream language for mkvmerge
      languages+=("$lang2")
    done
 
    # Construct the output filename
    output_filename="$output_dir/${filename%.*}_converted.${filename##*.}"
 
    # Wait for a few seconds before remuxing to ensure the input file is closed
    sleep 5
 
    # Remux the video and audio streams using mkvmerge
    mkvmerge -o "$output_filename" -A "$file" "${temp_files[@]}"
 
    # Set language metadata for the new audio streams using mkvpropedit
    mkvpropedit "$output_filename" ${languages[@]}
 
    echo "Conversion complete for file: $filename"
    echo "----------------------------------"
 
    # Clean up temporary directory files
    rm $temp_dir/*
 
  fi
done
 
# Clean up temporary directory
rm -rf "$temp_dir"

linux/scripts/audiostreamconvert.txt · Last modified: 2023/06/05 22:49 by lunetikk