VideoHelp Forum




+ Reply to Thread
Results 1 to 4 of 4
  1. Member
    Join Date
    Dec 2011
    Location
    Portugal
    Search Comp PM
    Hi, everybody
    I've been using this forum for a long time but only now decided to join in... So this is my first post.

    I'm a linux user and while searching for a xml chapter file maker for matroska video format, discovered that most available and viable options are Windows related so I've been playing with bash and develop my first bash script, not counting the 'Hello World' one.

    For those how don't know the ropes already copy paste the code bellow in a new file on you favorite text editor and save it, mark the file as executable and you're ready to go. The script has a built-in help, so use it if needed.

    Here goes,

    Code:
    #!/bin/bash
    
    ##
    ## XML chapter file creator for matroska video format
    ##
    ## Version History
    ##    0.5   * basic file structure creation
    ##
    ##    1.0   * added more command line options and help
    ##          * usage of random numbers for UIDs
    ##          * usage of mediainfo for video length
    ##
    ##    1.1   * added floating number calculation for chapter size accuracy
    ##            unfortunately this delays the program
    ##          * add support for filenames with spaces
    ##
    
    version="XML chapter file creator for matroska video format
    mkchapters version 1.1 created by perdigueiro
    "
    usage="
    Usage: $0 [OPTIONS] SRCFILE [DSTFILE]
    
    Examples
       1st: $0 SRCFILE
       2nd: $0 SRCFILE DSTFILE
       3rd: $0 [-c | --chapters=NUMBER] [-t | --length=TIME] DSTFILE
    
    In the 1st form, create xml file with same name as source file with 15 chapters.
    In the 2nd, same as in the first form but use the specified destination file
    In the 3rd, create destination file with the specified time length
    
    Options:
        SRCFILE         source file
        DSTFILE         destination file, if not used assume source file with XML
                        extension
        
        -h, --help              display this help and exit.
        -v, --version           display version info and exit.
        -c, --chapters=NUMBER   number of chapters to create default is 18
        -t, --length=TIME       Video length in format HH:MM:SS or number of seconds,
                                is ignored, if given a source file
        --prefix=WORD           Chapter name prefix, default is 'Chapter'
        --lang=WORD             Chapter language, default is 'eng'
    "
    ch=18
    prx="Chapter "
    lang="eng"
    
    while test $# -ne 0; do
        case $1 in
            --help|-h)
                echo "$version$usage";
                exit 0;;
            --version|-v)
                echo "$version";
                exit 0;;
            --chapters=*)
                ch=${1#*=};
                shift;;
            --length=*)
                ch=${1#*=};
                shift;;
            --prefix=*)
                prx=${1#*=};
                shift;;
            --lang=*)
                lang=${1#*=};
                shift;;
            -c)
                ch=$2;
                shift 2;;
            -t)
                length=$2;
                shift 2;;
            -*)
                echo "$0: invalid option: $1" >&2;
                exit 2;;
            *)
                break;;
        esac
    done
    
    if [[ $# -ne 0 && -z $in ]]; then 
        in=$1
        shift
        while [[ $# -ne 0 && `expr match ${in:${#in}-1} '\'` -ne 0 ]]; do
            in="$in $1"
            shift
        done
    fi
    
    if test $# -ne 0; then
        out=$1
        shift
        while [[ $# -ne 0 && `expr match ${out:${#out}-1} '\'` -ne 0 ]]; do
            out="$out $1"
            shift
        done
    elif [[ -n $length ]]; then
        out=$in
        unset -v in
    else
        out="${in%.*}.xml"
    fi
    
    if test $# -ne 0; then
        echo -e "$0: Too much arguments.\n" >&2
        exit 2
    fi
    
    if [[ -n $in ]]; then
        echo -e "\nUsing $in as input file"
        info=$(mediainfo $in | grep -m 1 "Duration")
        time=$((`expr match "$info" '.*\([0-9]\+\)h'`*60*60 + `expr match "$info" '.*\([0-9][0-9]\)mn'`*60))
    elif [[ `expr match "$length" '[0-1][0-9]:[0-5][0-9]:[0-5][0-9]$'` -eq 0 && `expr match "$length" '[1-9][0-9]\+$'` -eq 0 ]]; then
        echo -e "$0: Invalid time format, must use HH:MM:SS or number of seconds.\n" >&2
        exit 1
    else
        if [[ `expr match "$length" '[1-9][0-9]\+$'` -ne 0 ]]; then
            time=$((length*1))
        else
            time=$((${length:0:2}*3600 + ${length:3:2}*60 + ${length:6:2}))
        fi
    fi
    
    if [[ -n $out ]]; then echo -e "\nUsing $out as destination file"; fi
    echo -e "Total movie length is $time seconds\n"
    echo -e "\nCreating $ch chapters with $(($time/$ch)) seconds each."
    
    if [[ -f $out ]]; then
        read -p "File exists, do you want to overwrite? [Y/n] " -n1 -s answer
        if [[ $answer -ne "n" || $answer -ne "N" ]]; then
            echo "N"
            echo -e "$0: Aborted by user.\n" >&2
            exit 0
        else
            echo -n "Y"
        fi
    fi
    echo
    
    # Create list of Unique ID's
    UIDs=($(od -N$(($ch*4+4)) -An -t u4 /dev/random))
    
    #Create Chapter Atoms
    function getAtom(){
        local st=$(printf "%02d:%02d:%06.3f" ${starttime[0]} ${starttime[3]} ${starttime[4]})
        local en=$(printf "%02d:%02d:%06.3f" ${endtime[0]} ${endtime[1]} ${endtime[2]})
        printf "%03d> %s  %s\n" $1 $st $en
        atom="\n\t\t<ChapterAtom>"
        atom="$atom\n\t\t\t<ChapterDisplay>"
        atom="$atom\n\t\t\t\t`printf "<ChapterString>%s %02d</ChapterString>" $prx $1`"
        atom="$atom\n\t\t\t\t<ChapterLanguage>$lang</ChapterLanguage>"
        atom="$atom\n\t\t\t</ChapterDisplay>"
        atom="$atom\n\t\t\t<ChapterUID>${UIDs[$1]}</ChapterUID>"
        atom="$atom\n\t\t\t<ChapterTimeStart>$st</ChapterTimeStart>"
        atom="$atom\n\t\t\t<ChapterTimeEnd>$en</ChapterTimeEnd>"
        atom="$atom\n\t\t\t<ChapterFlagHidden>0</ChapterFlagHidden>"
        atom="$atom\n\t\t\t<ChapterFlagEnabled>1</ChapterFlagEnabled>"
        atom="$atom\n\t\t</ChapterAtom>"    
        return 0
    }
    
    #Create XML structure
    function getXML(){
        
        local xmlh="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n"
        xmlh="$xmlh<!-- <!DOCTYPE Tags SYSTEM \"matroskatags.dtd\"> -->\n\n"
        xmlh="$xmlh<Chapters>\n\t<EditionEntry>\n\t\t<EditionFlagHidden>0</EditionFlagHidden>\n"
        xmlh="$xmlh\t\t<EditionFlagDefault>0</EditionFlagDefault>\n"
        xmlh="$xmlh\t\t<EditionUID>${UIDs[0]}</EditionUID>"
        
        local xmlb="\n\t</EditionEntry>\n</Chapters>\n"
        starttime=(0 0 0 0 0)                   #Start time
        for (( i=1; i<=$ch; i++ )); do
            endtime=($(bc -q << CALC
                if($ch==$i) {
                    tm=$time
                } else {
                    scale=3
                    st=$time/$ch
                    tm=st*$i
                }
    
                scale=0
                h=tm/3600
                m=tm%3600/60
                s=tm%60
                m1=(tm+0.1)%3600/60
                s1=(tm+0.1)%60    
                print h," ",m," ",s," ",m1," ",s1;
                quit
    CALC
    ))                                           # Calculate endtime
            getAtom $i
            starttime=(${endtime[@]})            #Set start time
            atoms=$atoms$atom                    #Add Chapter Atom
        done
        xml="$xmlh $atoms $xmlb"
        return
    }
    
    getXML
    echo -e $xml > "$out"
    
    echo -e "\nDone"
    exit 0
    Hope you'll use it and tell me what you thing of it.
    Quote Quote  
  2. Member
    Join Date
    Jan 2012
    Location
    Massachusetts USA
    Search Comp PM
    Hi perdigueiro,

    I followed your directions above and when I tried to run your script I got the following error messages:



    ./MKVXMLchapterCreator: 91: [[: not found
    ./MKVXMLchapterCreator: 105: [[: not found
    ./MKVXMLchapterCreator: 125: [[: not found
    ./MKVXMLchapterCreator: 125: [[: not found
    ./MKVXMLchapterCreator: 125: [[: not found
    ./MKVXMLchapterCreator: 125: Bad substitution


    I was wondering if you could help me troubleshoot this error (only if you have some free time) since I am not much of a programmer but am willing to learn. I am planning to start learning Linux shell scripting this week.

    BR,

    drajc07
    Quote Quote  
  3. Member
    Join Date
    Dec 2011
    Location
    Portugal
    Search Comp PM
    Hello drajc07,


    I'm afraid your system is using sh by default and my script is bash as declared in the shebang.

    Probably the location of your bash interpreter is other than /bin/bash, find it and change the shebang accordingly.
    Quote Quote  
  4. just for the record: Hybrid can create mkv/mp4/m2ts chapters for quite some time,... (and it works on Windows/Mac/Linux) it allows you to create chapters every X min, import chapters from a source, edit existing chapters and export the chapters as mkv chapter file in the case that you don't want to use Hybrid for encoding,..
    Quote Quote  



Similar Threads

Visit our sponsor! Try DVDFab and backup Blu-rays!