Last active
April 26, 2025 15:21
-
-
Save adithya2306/4c94f4a2ed064ce5cabe52f769358288 to your computer and use it in GitHub Desktop.
Convert dolby vision profile 8 mkv to dolby vision profile 5 mp4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Script to convert MKV files with dolby vision video (any profile), dolby audio (AC3 or EAC3) | |
# and subtitles, to MP4 with dolby vision profile 5 and SRT file. | |
# Default settings | |
video_id=0 | |
audio_id=0 | |
subtitle_id=0 | |
skip_extraction=false | |
audio_codec="eac3" | |
audio_ext="ec3" | |
# Usage message | |
usage() { | |
echo "Usage: $0 [-v video_id] [-a audio_id] [-s subtitle_id] [-k] [-c] [-h] input.mkv" | |
echo "Options:" | |
echo " -v <id> Video stream ID to extract (default 0)" | |
echo " -a <id> Audio stream ID to extract (default 0)" | |
echo " -s <id> Subtitle stream ID to extract (default 0)" | |
echo " -k Skip ffmpeg extraction, run only mp4muxer" | |
echo " -c Use AC3 audio instead of EAC3" | |
echo " -h Show this help message and exit" | |
exit 0 | |
} | |
# Parse options | |
while getopts ":v:a:s:kch" opt; do | |
case ${opt} in | |
v ) video_id=$OPTARG ;; | |
a ) audio_id=$OPTARG ;; | |
s ) subtitle_id=$OPTARG ;; | |
k ) skip_extraction=true ;; | |
c ) | |
audio_codec="ac3" | |
audio_ext="ac3" | |
;; | |
h ) usage ;; | |
\? ) | |
echo -e "\nInvalid option: -$OPTARG\n" >&2 | |
usage | |
;; | |
esac | |
done | |
# Shift processed options | |
shift $((OPTIND -1)) | |
# Check input file | |
input_file="$1" | |
if [[ -z "$input_file" ]]; then | |
echo "Error: No input file provided." | |
usage | |
fi | |
# Function to format seconds to mm:ss | |
format_time() { | |
local total_seconds=$1 | |
printf "%d min %02d sec" $((total_seconds / 60)) $((total_seconds % 60)) | |
} | |
# Record total start time | |
total_start_time=$(date +%s) | |
# Remove path and extension for naming | |
base_name="$(basename "$input_file" .mkv)" | |
# Create a new folder based on the base name | |
output_dir="./$base_name" | |
mkdir -p "$output_dir" | |
# Extract the video and audio into separate files | |
if ! $skip_extraction; then | |
start_time=$(date +%s) | |
set -x | |
if ! ffmpeg -i "$input_file" \ | |
-map 0:v:"$video_id" -c:v copy "$output_dir/${base_name}.hevc" \ | |
-map 0:a:"$audio_id" -c:a copy -f "$audio_codec" "$output_dir/${base_name}.${audio_ext}" \ | |
-map 0:s:"$subtitle_id" -c:s copy "$output_dir/${base_name}.srt"; then | |
set +x | |
echo -e "\nError: ffmpeg extraction failed." | |
exit 1 | |
fi | |
set +x | |
end_time=$(date +%s) | |
duration=$((end_time - start_time)) | |
echo -e "\nffmpeg extraction successful. Time taken: $(format_time $duration)" | |
fi | |
start_time=$(date +%s) | |
set -x | |
if ! mp4muxer -o "$output_dir/${base_name}.mp4" \ | |
-i "$output_dir/${base_name}.hevc" \ | |
-i "$output_dir/${base_name}.${audio_ext}" \ | |
--dv-profile 5; then | |
set +x | |
echo -e "\nError: mp4muxer failed." | |
exit 1 | |
fi | |
set +x | |
end_time=$(date +%s) | |
duration=$((end_time - start_time)) | |
echo -e "\nmp4muxer muxing successful. Time taken: $(format_time $duration)" | |
# Always cleanup intermediate files | |
echo -e "\nCleaning up intermediate files..." | |
rm -f "$output_dir/${base_name}.hevc" "$output_dir/${base_name}.${audio_ext}" | |
echo -e "\nCleanup done. Final output: $output_dir/${base_name}.mp4" | |
# Total time | |
total_end_time=$(date +%s) | |
total_duration=$((total_end_time - total_start_time)) | |
echo "Total time taken: $(format_time $total_duration)" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment