Skip to content

Instantly share code, notes, and snippets.

@lededje
Forked from djotto/mp4.sh
Last active May 9, 2020 00:59
Show Gist options
  • Save lededje/7b5d81b0d9825cc9d7abca03d5264238 to your computer and use it in GitHub Desktop.
Save lededje/7b5d81b0d9825cc9d7abca03d5264238 to your computer and use it in GitHub Desktop.

Revisions

  1. lededje revised this gist May 9, 2020. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions mp4.sh
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@
    # ffmpeg | ffmpeg/ffprobe | 3.1.4 3.2
    # gpac | MP4Box | 0.6.1
    # mp4v2 | mp4chaps | 2.0.0
    # coreutils | grealpath/gdate | 8.25
    # coreutils | realpath/date | 8.25
    #
    # Usage
    # ./mp4.sh merge_as_chapter input*.mp4 output.mp4
    @@ -18,7 +18,7 @@ check_dependency(){
    echo "ffmpeg $(echo_if $(program_is_installed ffmpeg))"
    echo "gpac $(echo_if $(program_is_installed MP4Box))"
    echo "mp4v2 $(echo_if $(program_is_installed mp4chaps))"
    echo "coreutils $(echo_if $(program_is_installed grealpath))"
    echo "coreutils $(echo_if $(program_is_installed realpath))"
    }

    # Merge multiple mp4 files as chapters
  2. lededje revised this gist May 9, 2020. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions mp4.sh
    Original file line number Diff line number Diff line change
    @@ -6,7 +6,7 @@
    # library name | commands used | verified version
    # ------------------------------------------------
    # ffmpeg | ffmpeg/ffprobe | 3.1.4 3.2
    # gpac | mp4box | 0.6.1
    # gpac | MP4Box | 0.6.1
    # mp4v2 | mp4chaps | 2.0.0
    # coreutils | grealpath/gdate | 8.25
    #
    @@ -16,7 +16,7 @@
    ####################################################
    check_dependency(){
    echo "ffmpeg $(echo_if $(program_is_installed ffmpeg))"
    echo "gpac $(echo_if $(program_is_installed mp4box))"
    echo "gpac $(echo_if $(program_is_installed MP4Box))"
    echo "mp4v2 $(echo_if $(program_is_installed mp4chaps))"
    echo "coreutils $(echo_if $(program_is_installed grealpath))"
    }
    @@ -76,7 +76,7 @@ add_chaptermark(){
    local input="$2"
    echo "chapterfile:" "$chapterfile"

    mp4box -chap "$chapterfile" "$input" &&
    MP4Box -chap "$chapterfile" "$input" &&
    mp4chaps --convert --chapter-qt "$input"
    }

    @@ -96,7 +96,7 @@ create_chapterfile(){
    local chapter_number=$(printf "CHAPTER%s" "$i")
    local duration=$(duration "$file")

    printf "%s=%s\n" "$chapter_number" $(gdate -d@"$chapter_start" -u +%T.%3N) | tee -a /tmp/create_chapterfile.log
    printf "%s=%s\n" "$chapter_number" $(date -d@"$chapter_start" -u +%T.%3N) | tee -a /tmp/create_chapterfile.log
    printf "%sNAME=%s\n" "$chapter_number" "$chapter_name" | tee -a /tmp/create_chapterfile.log

    chapter_end=$(bc <<< "scale=6;$chapter_end+ $duration")
    @@ -106,7 +106,7 @@ create_chapterfile(){

    create_filelist(){
    for file in "$@"; do
    printf "file %q\n" "$(grealpath "$file")" | tee -a /tmp/create_filelist.log
    printf "file %q\n" "$(realpath "$file")" | tee -a /tmp/create_filelist.log
    done
    }

    @@ -146,4 +146,4 @@ function echo_if {


    # call arguments verbatim:
    "$@"
    "$@"
  3. @invalid-email-address Anonymous created this gist Nov 28, 2016.
    149 changes: 149 additions & 0 deletions mp4.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,149 @@
    #! /usr/bin/env bash

    ####################################################
    # Required Libraries
    #
    # library name | commands used | verified version
    # ------------------------------------------------
    # ffmpeg | ffmpeg/ffprobe | 3.1.4 3.2
    # gpac | mp4box | 0.6.1
    # mp4v2 | mp4chaps | 2.0.0
    # coreutils | grealpath/gdate | 8.25
    #
    # Usage
    # ./mp4.sh merge_as_chapter input*.mp4 output.mp4
    #
    ####################################################
    check_dependency(){
    echo "ffmpeg $(echo_if $(program_is_installed ffmpeg))"
    echo "gpac $(echo_if $(program_is_installed mp4box))"
    echo "mp4v2 $(echo_if $(program_is_installed mp4chaps))"
    echo "coreutils $(echo_if $(program_is_installed grealpath))"
    }

    # Merge multiple mp4 files as chapters
    # - Each input file name will be the chapter title
    # - Chapter markers in the input files will NOT be preserved
    # - Each input file must be extractly same format
    merge_as_chapter(){
    echo "### Merge As Chapter ###"

    if [ "$#" -lt 2 ]; then
    echo "Error: Wrong number of parameters:"
    echo "Usage: merge_as_chapter input.mp4 [input.mp4...] output.mp4"
    return
    fi

    local output=${!#}
    set -- "${@:1:$# -1}"

    local chapterfile=$(printf "%s-%s" "/tmp/chapterfile" "$(basename ${output} .${output##*.})")

    merge_file "$@" "$output" &&
    create_chapterfile "$@" > "$chapterfile" &&
    add_chaptermark "$chapterfile" "$output"
    }

    # Merge multiple mp4 files
    # - Chapter markers in the input files will NOT be preserved
    # - Each input file must be extractly same format
    merge_file(){
    echo "### Merge File ###"

    if [ "$#" -lt 2 ]; then
    echo "Usage: merge_file input.mp4 [input.mp4...] output.mp4"
    return
    fi

    local output=${!#}
    set -- "${@:1:$# -1}"

    echo "input :" "$@"
    echo "output:" "$output"

    ffmpeg -n -f concat -safe 0 -i <(create_filelist "$@") -c copy "$output"
    }

    add_chaptermark(){
    echo "### Add Chaptermark ###"

    if [ "$#" -ne 2 ]; then
    echo "Usage: add_chaptermark chapterfile file.mp4"
    return
    fi

    local chapterfile="$1"
    local input="$2"
    echo "chapterfile:" "$chapterfile"

    mp4box -chap "$chapterfile" "$input" &&
    mp4chaps --convert --chapter-qt "$input"
    }

    create_chapterfile(){
    echo "### Create Chapterfile ###"

    if [ "$#" -lt 1 ]; then
    echo "Usage: create_chapterfile input.mp4 [input.mp4...]"
    return
    fi

    local chapter_start=0
    local chapter_end=0
    for ((i=1; i<=$#; i++)); do
    file="${!i}"
    local chapter_name=$(basename "$file" .mp4)
    local chapter_number=$(printf "CHAPTER%s" "$i")
    local duration=$(duration "$file")

    printf "%s=%s\n" "$chapter_number" $(gdate -d@"$chapter_start" -u +%T.%3N) | tee -a /tmp/create_chapterfile.log
    printf "%sNAME=%s\n" "$chapter_number" "$chapter_name" | tee -a /tmp/create_chapterfile.log

    chapter_end=$(bc <<< "scale=6;$chapter_end+ $duration")
    chapter_start=$(bc <<< "scale=6;$chapter_end+ 0.001")
    done
    }

    create_filelist(){
    for file in "$@"; do
    printf "file %q\n" "$(grealpath "$file")" | tee -a /tmp/create_filelist.log
    done
    }

    duration(){
    ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$1"
    }


    # ==============================================
    # https://gist.github.com/JamieMason/4761049
    # ==============================================
    function program_is_installed {
    local return_=1
    type $1 >/dev/null 2>&1 || { local return_=0; }
    echo "$return_"
    }

    function echo_fail {
    printf "\e[31m✘ ${1}"
    echo -e "\033[0m"
    }

    function echo_pass {
    printf "\e[32m✔ ${1}"
    echo -e "\033[0m"
    }

    function echo_if {
    if [ $1 == 1 ]; then
    echo_pass $2
    else
    echo_fail $2
    fi
    }

    # ==============================================


    # call arguments verbatim:
    "$@"