#!/bin/bash # # dia_gen Character user interface for diascope # DIAscope file GENerator # # Syntax: dia_gen [-B] [-h|H] [show directory list] # #################################################################################### # "TO DO"s # -) Correct kenburns areas: sometime the area is greter than the picture # Done in version 0.5 # -) Introduce more parameter options (impossible to complete?) # Extra features, not related to video generator: # -) Generate the DVD structure (?) # -) Sometime the modern cameras can generate videos (generally avi, mpg): # it could be a good idea insert them in the final DVD # Partially done in ver 0.9: a whole video stream will be generated # in AVI format using "avidemux" #################################################################################### # H I S T O R Y # # < 08/2010 Marco Jack New DG_VERSION=0.1 # Core structure # DG_VERSION=0.2 # 24/08/2010 Marco Jack Bug corrections # Kenburns points: minimum distance # Parallel option editable # Author editable # Normalize & generate sound tracks per SHOW # Delete temporary files (Cancel) # Generate ALL video types (4 types) # Better help & instructions # Beautify & some optimizations # 25/08/2010 Marco Jack Parameter activation: # -B : disable colors - Black & White # -h|H: show syntax/parameters # Minor corrections DG_VERSION=0.3 # 25/08/2010 Marco Jack TwoPass in incompatible with flv format DG_VERSION=0.3b # 26/08/2010 Marco Jack The video file have extension != format. Corrected. DG_VERSION=0.4 # 28/08/2010 Marco Jack Automatic soundtrack generation before run diascope # 30/08/2010 Marco Jack Width percentage based on picture dimension DG_VERSION=0.5 # 01/09/2010 Marco Jack Paramenter variation check and warning. # Multiword title translation from directory name # Auto compose show list on manual error # Display picture comment # 06/09/2010 Marco Jack Save diascope logs DG_VERSION=0.6 # 07/09/2010 Marco Jack Picture name not enclose with " # 26/10/2010 Marco Jack Translate " " into "_" in file names (show + audio) # 09/11/2010 Marco Jack Managing videos: AVI camera video streams are unified # and a special soundtrack can be added to the result. # Put video soundtrack in audio4video directory DG_VERSION=0.8 # 22/11/2010 Marco Jack Extension to MOV files. # 23/11/2010 Marco Jack Auto rotate images (thanks you Martin for the suggest) # I finally wrote the code :-) # The result is not so beautiful DG_VERSION=0.9 # 23/11/2010 MArco Jack Bug: format is alwayw pal, even if you choose ntsc # Specify your format: HD included! # More diascope options activated #################################################################################### #renice 18 $$ # -- SHELL_AUTHOR="Marco Jack" SHELL_AUTHOR_MAIL="MarcoJack@inwind.it" DG_DIA_GEN=$(basename $0) PERM_FILE=$HOME/.$DG_DIA_GEN LUMA_DIR=~/share/diascope/luma DIA_GEN_LOG=${DG_DIA_GEN}.log # Minumum point distance in percentage between 2 KenBurns points # Must be low to avoid omega loops during runtime ! # The distance must be >= than *<% picture>*<% section> # so that point belogs always to the upper-left part of the picture DG_MIN_DISTANCE_PERC=30 # ------------------------- ### Importante quando l'ambiente non e' quello standard! #echo LC_NUMERIC=$LC_NUMERIC export LC_NUMERIC=en_US.UTF-8 #################################################################################### function dg_syntax { cat <<-EOF dia_gen Character user interface for diascope DIAscope file GENerator by $SHELL_AUTHOR Syntax: dia_gen [-B] [-h|H] [show directory list] Options: -B Black&White, do not use colors -h|-H See these lines If "show directory list" is empty, it will automatically loaded from disc. Run dia_gen and choose Help or Installation options to see more. EOF exit 0 } function separa { echo "--------------------------------------------------------------------------------" } function attendi { printf "To continue press <${W}${BLINK}RETURN${N}> " read ATTESA } function Help { HELP_PAGE=$1 HELP_DESC="$2" clear #printf " ${W}%-30s$N %50s\n" "${W}$DG_DIA_GEN$N by ${Y}Marco Jack$N" "${W} HELP page $HELP_PAGE${N}" printf " $W%s$N by $Y%s$N %18s $G%s$N\n" \ $DG_DIA_GEN "$SHELL_AUTHOR" "$HELP_DESC" $HELP_PAGE separa case $1 in 1) cat <<-EOF Create a directory with the name of your whole collection Eg: ${L}Holidays$N Inside the collection dir, put all the directories (the SHOWs) with your graphic (jpg) and/or video (avi/mov) files: Eg: ${L}Holidays$N |\-${C}Mountain$N \--${C}Sea$N You can create the audio and audio4video directories in each SHOW and put into them your preferred sound files: they will be used to generate the SHOW sountracks. Eg: ${L}Holidays$N |\-${C}Mountain$N \--${C}Sea$N \-${G}audio$N \------${G}audio$N \-----${G}audio4video$N Graphic and audio files will be involved using the naming order. The auto-rotate function is enabled with lossless feature (pay attention on it!) ${R}LIMITATIONs${N}: Directories and file names MUST NOT: -) contain spaces and -) begin with a number. Use ${C}S$N option to translate spaces into "_" EOF ;; 2) cat <<-EOF When ready, go in your collection directory (Ex: cd Holidays) and run ${W}$DG_DIA_GEN$N: the SHOW list will be autmatically populated. You can ever rebuild it with the "${C}l$N" option or explicitly write it on the command line (Ex: ${W}$DG_DIA_GEN$N Sea). You can modify (some) ${L}diascope${N} options using the letters: more help will be displayed when you will choose one of them. Options can be ${C}W${N}ritten PERMANENTLY (${C}W$N option) or ${C}R${N}ead from a previous saved state (${C}R$N option) or ${C}D${N}efaulted as never modified (${C}D$N option) Write your options when you have decided your video standards: these parameters will be read next time you run ${W}$DG_DIA_GEN$N. Audio files (mp3, wav, ...) can be ${R}normalized$N (${C}n$N option): a big SHOW.wav soundtrack file will automatically be generated and merged into video. You cannot share audio files for different shows. EOF ;; 3) cat <<-EOF Now you are ready to: ${C}1$N) generate the ${L}diascope${N} files (.dia). ${C}2$N) edit the *.dia files, if you want to adjust some random generated values. ${C}3$N) run ${L}diascope${N}: you'll get your videos! Usability AND operativity of all the software depends on the installed programs and their active options (a new "compilation" may be necessary, see Installation) WARNING: ${L}diascope${N} is very "space" aggressive. When you have your final results you can remove the "_TMP" directories and temporary files with the ${C}C$N option: cancel. Only the SHOW.dia file remains. Developped & Tested & Run on: ${B}Mandriva 2010.1$N with bash Many thanks to: ${G}Poison${N} First ispirator for these interfaces ${L}Martin Stoll${N} for his ${L}DIASCOPE$N (great!) If you think this shell is good ... fell free to let me know! :-) ${Y}MarcoJack@inwind.it${N} EOF ;; A) cat <<-EOF This program was designed to easily create video files. Starting from (camera) pictures and videos, you can post them in a structured directory tree and in few steps with some (random) choices you can have the final videos. The core program is ${L}diascope${N} (by Martin Stoll) ${W}http://diascope.sourceforge.net$N See ${L}diascope${N} web pages and proceed with a ${R}LOCAL$N installation, not a SYSTEM one. Some extra software is necessary to run ${W}$DG_DIA_GEN$N: jhead, avidemux, ... You should find these programs in your linux distribution or you may download them from the web. You also need: the pictures (obviously) in jpg format and some audio files. EOF ;; B) cat <<-EOF For every directory specified in the LIST, you will have one or more video files and maybe you will want to put them on a DVD-ROM to be seen on your TV. For the moment, ${W}$DG_DIA_GEN$N does ${BLINK}NOT$N create the DVD structure. To do that, you may need ${Y}dvd-menu$N | ${G}dvdauthor$N | ${G}dvd-styler$N | ... As noticed in ${L}diascope${N} site, some software is distributed with one or more de-activated flags so that some file types can't be handled natively: you may download the source code and re-compile them with the correct option(s). Some of these examples are sox, ffmpeg, ... ${Y}MarcoJack@inwind.it${N} EOF esac separa; attendi } function go_action { ACTION=$1 SHOW_INDEX=0 while : do SHOW="${LIST_SHOW[$SHOW_INDEX]}" if [[ "$SHOW" = "" ]] then break else separa echo " SHOW=${Y}$SHOW$N" $ACTION let SHOW_INDEX=SHOW_INDEX+1 fi done separa } function translate_space { cd $SHOW ls -1 * audio/* audio4video/* 2>/dev/null | \ while read DG_FILE do DG_NEWN=$(echo "$DG_FILE" | tr " " "_") printf "%30s -> %-30s : " "$DG_FILE" $DG_NEWN if [[ "$DG_FILE" = "$DG_NEWN" ]] then echo "skipped." else mv -f "$DG_FILE" $DG_NEWN if [[ $? -eq 0 ]] then echo "ok." else echo "Error!" fi fi done cd .. } function dg_normalize_audio { echo "Normalizing sounds files ..." echo " " echo " This should be done ONE TIME ONLY" echo " " if [[ $(ls "$SHOW"/audio/* | wc -l) -gt 0 ]] then normalize "$SHOW"/audio/* else echo " $BLINK${R}WARNING!$N No audio file found in $SHOW/audio" fi } function dg_create_soundtrk { printf "Create the wav audio soundtrack ...\n" if [[ $(ls "$SHOW"/audio/* 2>/dev/null | wc -l) -gt 0 ]] then sox $(ls "$SHOW"/audio/* 2>/dev/null| sort) "$SHOW".wav RC=$? if [[ $RC -eq 0 ]] then printf "ok.\n" else printf "\n $BLINK${R}WARNING!$N RC=$RC\n" fi else echo " $BLINK${R}WARNING!$N No audio files found: the video will be mute." rm -f "$SHOW".wav >/dev/null fi } function dg_delete_soundtrk { printf "delete the wav audio soundtrack ...\n" rm -f "$SHOW".wav RC=$? if [[ $RC -eq 0 ]] then echo "ok." else echo "Error RC=$RC during rm -f $SHOW.wav" fi } function dg_save_original_file { echo "Saving $SHOW.dia into $SHOW.dia_ori" mv -f "$SHOW".dia "$SHOW".dia_ori DG_FORMAT_NUM=$(cat "$SHOW".dia_ori | grep ^format | wc -w) DG_OUTPUT_ORI=$(dg_print_nth $DG_FORMAT_NUM $(cat "$SHOW".dia_ori | grep ^format )) } function dg_restore_original_file { echo "Restoring $SHOW.dia from $SHOW.dia_ori" mv -f "$SHOW".dia_ori "$SHOW".dia DG_OUTPUT=$DG_OUTPUT_ORI } function dg_print_nth { shift $1 echo $1 } function dg_change_output { echo "Changing output for "$SHOW" from $DG_OUTPUT_ORI to $DG_OUTPUT_NEW" cat "$SHOW".dia_ori | sed -e 's/'$DG_OUTPUT_ORI'$/'$DG_OUTPUT_NEW'/g' > "$SHOW".dia DG_OUTPUT=$DG_OUTPUT_NEW # Twopass & flv are INCOMPATIBLE if [[ "$DG_OUTPUT_NEW" = "flv" ]] then sed -i 's/twopass//' "$SHOW".dia fi } function see_movie { case $DG_OUTPUT in dv|flv) DG_OUTPUT_EXT=$DG_OUTPUT ;; mpeg2 ) DG_OUTPUT_EXT=mpeg ;; mpeg4 ) DG_OUTPUT_EXT=mp4 ;; esac echo "You're going to see ${Y}$SHOW.$DG_OUTPUT_EXT${N}" separa vlc "$SHOW".$DG_OUTPUT_EXT separa echo "You saw ${Y}$SHOW.$DG_OUTPUT_EXT${N}" } function dg_cancel_tmp { for DG_PIECE in _TMP _slideshow.sh .smil .wav .dia_ori _flv.log _dv.log _mpeg2.log _mpeg4.log do if [[ -f "${SHOW}"$DG_PIECE ]] then rm -rf "${SHOW}"$DG_PIECE RC=$? if [[ $RC -eq 0 ]] then printf "%32s deleted.\n" "${SHOW}"$DG_PIECE else echo "ERROR during ${SHOW}_TMP deletion: RC=$RC" fi fi done rm -f ffmpeg2pass*.log >/dev/null 2>&1 } function set_desc { SWITCH_VAR="$1" SWITCH_VAL="$2" if [[ "$SWITCH_VAL" = "" ]] then export ${SWITCH_VAR}_DESC=no else export ${SWITCH_VAR}_DESC=yes fi } function switch_var { SWITCH_VAR="$1" SWITCH_ELE="$2" SWITCH_VAL="$3" if [[ "$SWITCH_VAL" = "" ]] then export ${SWITCH_VAR}=$SWITCH_ELE export ${SWITCH_VAR}_DESC=yes else export ${SWITCH_VAR}="" export ${SWITCH_VAR}_DESC=no fi #R_W_OPT_DESC="!" } function Scegli { # $1 mask da visualizzare # $2 Variabile da valorizzare # $3 Testo display # $4 Attuale valore della variabile if [[ "$1" = "j" ]] then LIST_LS=$4 else LIST_LS=$(ls *$1 2>/dev/null) separa echo "${G}$LIST_LS$N" separa fi printf "%s [%s]: " "$3" $4 read ANS if [[ "$ANS" != "" ]] then export $2="$ANS" fi } function dg_read_dir { find . -mindepth 1 -maxdepth 1 -type d |\ grep -vwE "audio" |\ grep -vE "_TMP" |\ cut -d/ -f2 > $1 } function Componi_lista { local TEMP_FILE=$(mktemp) >$TEMP_FILE case $1 in M) echo "Divide the directories using \"$G|$N\":" Componi_lista A echo "$G$(mostra_lista)$N" echo "Specify the dir(s): " read LIST_SHOW if [[ "$LIST_SHOW" != "" ]] then SHOW_NUMBER=1 SHOW_PREV="" while : do SHOW=$(echo $LIST_SHOW | cut -d"|" -f $SHOW_NUMBER) if [[ "$SHOW" = "" || "$SHOW" = "$SHOW_PREV" ]] then break else if [[ ! -d "$SHOW" ]] then echo "Dir \"$SHOW\" NOT found! Ignored." attendi break else echo "$SHOW" >> $TEMP_FILE SHOW_PREV="$SHOW" fi fi let SHOW_NUMBER=SHOW_NUMBER+1 done else dg_read_dir $TEMP_FILE fi ;; *) dg_read_dir $TEMP_FILE ;; esac #Bug di bash: l'array non si compone correttamente attraverso il while #cat /tmp/dir2dvd.tmp | while read DIR unset LIST_SHOW SHOW_INDEX=0 SHOW_NUMBER=0 LIST_SHOW[$SHOW_INDEX]="" for DUMMY in $(cat $TEMP_FILE | awk '{print $1}') do LIST_SHOW[$SHOW_INDEX]="" let SHOW_NUMBER=SHOW_NUMBER+1 #echo SHOW_NUMBER=$SHOW_NUMBER DIR="$(cat $TEMP_FILE | head -$SHOW_NUMBER | tail -1)" case $DIR in audio*|$DIR_DVD|FILM|"") echo $DIR ;; *) LIST_SHOW[$SHOW_INDEX]="$DIR" let SHOW_INDEX=SHOW_INDEX+1 ;; esac done LIST_SHOW[$SHOW_INDEX]="" echo LIST_SHOW=${LIST_SHOW[*]} rm -f $TEMP_FILE } function mostra_lista { #echo "SHOW=${LIST_SHOW[*]}" SHOW_INDEX=0 while : do SHOW="${LIST_SHOW[$SHOW_INDEX]}" if [[ "$SHOW" = "" ]] then break else printf "%s|%s" $Y"$SHOW"$G $N fi let SHOW_INDEX=SHOW_INDEX+1 done } # ------------------------------------------------------------------------------ dg functions function quality_rescale { bc <<-EOF scale=1 $DG_QUALITY/10 EOF } function dg_format { echo format $DG_FORMAT \ quality=$(quality_rescale) \ $DG_INTERLACED \ $DG_TWOPASS \ aspect=$DG_ASPECT \ mpeg2sound=$DG_MPEG2SOUND \ $DG_OUTPUT$DG_OUTPUT_OPT #echo set dur= echo set dur=sec #echo set resize= echo set resize=resize #echo set debug= #set font=Fontname size=n fill=Colourname #set stroke=Colourname strokewidth=n #set label= #set title_area= title_hold=x% #set title_offset=x%,y% title_offset_x=x% title_offset_y=y% echo set title_offset=20%,80% title_area=15% echo $(dg_audio) } function dg_audio { if [[ $(ls $SHOW/audio/* 2>/dev/null | wc -w) -lt 1 ]] then echo " $BLINK${R}WARNING!$N" >&2 echo " $BLINK${R}WARNING!$N Audio files NOT found!" >&2 echo " $BLINK${R}WARNING!$N" >&2 echo " $BLINK${R}WARNING!$N Insert audio files in dir $SHOW/audio" >&2 echo " " >&2 else echo audio "$SHOW".wav fade=1,2 fi } function dg_fadein { echo set label=green echo create $DG_FADE_IN_OUT green-yellow title=0,1,2,1 dir=rl \"$1\" echo set label=off } function dg_fadeout { echo trns $DURATA_TRAN cross echo set label=black echo create $DG_FADE_IN_OUT black-white title=0,1,2,1 dir=rl \"$1\" echo set label=off echo trns 1 cross echo create 2 black } function dg_transaction { echo trns $DURATA_TRAN $DG_TRANSACTION $DG_TRANSACTION_OPT dg_title if [[ $DG_KENBURNS -lt 2 ]] then echo crop $DURATA_FOTO $1 $DG_TITLE $DG_COMMENT else dg_kbrn_movement echo kbrn $DURATA_FOTO $1 $DG_KBRN_OPT $DG_TITLE $DG_COMMENT fi } function dg_title { if [[ $DURATA_FOTO -lt 3 || $DG_PICT_COMMENT = no || "$DG_COMMENT" = "" ]] then DG_TITLE="" DG_COMMENT="" else DG_TITLE_FI=1 DG_TITLE_FO=1 if [[ $DURATA_FOTO -gt 6 ]] then DG_TITLE_DE=1 else DG_TITLE_DE=0 fi DG_TILE_DU=$(echo $DURATA_FOTO-$DG_TITLE_FI-$DG_TITLE_FO-$DG_TITLE_DE|bc) DG_TITLE="title=$DG_TITLE_DE,$DG_TITLE_FI,$DG_TILE_DU,$DG_TITLE_FO" DG_COMMENT=\"$DG_COMMENT\" fi echo DG_TILE_DU=$DG_TILE_DU >&2 echo DG_TITLE=$DG_TITLE >&2 } function dg_kbrn_movement { dg_min_distance 25 0 0 $DG_MIN_DISTANCE_PERC DG_KBRN_OPT="xyw=$DG_OFFSET_X,$DG_OFFSET_Y,$DG_OFFSET_W%" for (( DG_KBRN_IND=3; DG_KBRN_IND <= $DG_KENBURNS ; DG_KBRN_IND++ )) do dg_min_distance $(random_num 25) $DG_OFFSET_X $DG_OFFSET_Y $DG_MIN_DISTANCE_PERC DG_KBRN_OPT="$DG_KBRN_OPT xyw=$DG_OFFSET_X,$DG_OFFSET_Y,$DG_OFFSET_W%" done dg_min_distance $(random_num 5) $DG_OFFSET_X $DG_OFFSET_Y $DG_MIN_DISTANCE_PERC DG_KBRN_OPT="$DG_KBRN_OPT xyw=$DG_OFFSET_X,$DG_OFFSET_Y,$DG_OFFSET_W%" } function dg_min_distance { DG_MIN_DIST_MAX=$1 DG_MIN_DIST_PRE_X=$2 DG_MIN_DIST_PRE_Y=$3 DG_MIN_DIST_PERC=$4 DG_MIN_FOUND_X=0 DG_MIN_FOUND_Y=0 while [[ $DG_MIN_FOUND_X -eq 0 && $DG_MIN_FOUND_Y -eq 0 ]] do DG_OFFSET_X=$(random_num $(($DG_FILE_WI*$DG_MIN_DIST_MAX/100)) ) DG_OFFSET_Y=$(random_num $(($DG_FILE_HE*$DG_MIN_DIST_MAX/100)) ) if [[ $(( $DG_MIN_DIST_PRE_X-$DG_OFFSET_X )) -ge $(( $DG_FILE_WI*$DG_MIN_DIST_MAX*$DG_MIN_DIST_PERC/100/100)) || $(( $DG_OFFSET_X-$DG_MIN_DIST_PRE_X )) -ge $(( $DG_FILE_WI*$DG_MIN_DIST_MAX*$DG_MIN_DIST_PERC/100/100)) ]] then DG_MIN_FOUND_X=1 else DG_MIN_FOUND_X=0 fi if [[ $(( $DG_MIN_DIST_PRE_Y-$DG_OFFSET_Y )) -ge $(( $DG_FILE_HE*$DG_MIN_DIST_MAX*$DG_MIN_DIST_PERC/100/100)) || $(( $DG_OFFSET_Y-$DG_MIN_DIST_PRE_Y )) -ge $(( $DG_FILE_HE*$DG_MIN_DIST_MAX*$DG_MIN_DIST_PERC/100/100)) ]] then DG_MIN_FOUND_Y=1 else DG_MIN_FOUND_Y=0 fi done DG_OFFSET_W=$(echo 100-$DG_OFFSET_X*$DG_OFFSET_Y*100/$DG_FILE_WI/$DG_FILE_HE|bc) } function dg_prepara_show { dg_format dg_fadein "$(echo "$SHOW" | tr "_" " ")" ls "$SHOW"/*.jpg "$SHOW"/*.JPG 2>/dev/null | sort | while read DG_IMMAGINE do DG_COMMENT=$(jhead "$DG_IMMAGINE" | grep ^Comment | cut -d: -f2) DG_FILE_WI=$(jhead "$DG_IMMAGINE" | grep ^Resolution | cut -d: -f2 | awk '{print $1}') DG_FILE_HE=$(jhead "$DG_IMMAGINE" | grep ^Resolution | cut -d: -f2 | awk '{print $3}') DG_ORIENTA=$(jhead "$DG_IMMAGINE" | grep ^Orientation| cut -d: -f2 | awk '{print $2}') if [[ "$DG_ORIENTA" != "" ]] then jhead -autorot "$DG_IMMAGINE" >> "$SHOW"_rotated.log 2>&1 fi dg_random $DG_TRAN_VALUE dg_transaction "$DG_IMMAGINE" "$DG_COMMENT" done dg_fadeout "Created by $DG_AUTHOR - $(date +'%d/%m/%y')" } function random_num { #echo $(( (`od -An -N2 -i /dev/random` )%(1000-100+1)%$1)) #echo "Par #1:" $1 >&2 BASE=$1 if [[ $BASE -eq 0 ]] then echo 1 else echo $(( $RANDOM%$BASE )) fi } function dg_random { # cross, luma (built-in), luma (external file), push, put, take case $(random_num $1) in 0) DG_TRANSACTION=cross ;; 1) DG_TRANSACTION=push ;; 2) DG_TRANSACTION=put ;; 3) DG_TRANSACTION=take ;; 4) DG_TRANSACTION=luma DG_LUMA_TYPE=I ;; 5) DG_TRANSACTION=luma DG_LUMA_TYPE=E ;; esac case $DG_TRANSACTION in cross) DG_TRANSACTION_OPT="" ;; push|put|take) case $(random_num 2) in 0) DG_TRANSACTION_OPT="dir=td" ;; 1) DG_TRANSACTION_OPT="dir=rl" ;; esac ;; luma) case $DG_LUMA_TYPE in I) # -- INTERNAL -- case $(random_num 4) in 0) DG_TRANSACTION_OPT="dir=td" ;; 1) DG_TRANSACTION_OPT="dir=rl" ;; 2) DG_TRANSACTION_OPT="dir=ri" ;; 3) DG_TRANSACTION_OPT="dir=ro" ;; esac ;; E) # -- EXTERNAL -- case $(random_num 4) in 0) DG_TRANSACTION_OPT="file=$LUMA_DIR/luma_coscos8pi.png " ;; 1) DG_TRANSACTION_OPT="file=$LUMA_DIR/luma_coscos4pi.png " ;; 2) DG_TRANSACTION_OPT="file=$LUMA_DIR/luma_diagonal.png " ;; 3) DG_TRANSACTION_OPT="file=$LUMA_DIR/luma_iris.png " ;; esac ;; esac ;; esac } function Scegli_transazioni { cat <<-EOF Transaction priority: 1: cross 2: 1 + push 3: 2 + put 4: 3 + take 5: 4 + luma (internal) 6: 5 + luma (external) Random pan and zoom (Ken Burns effects) option "k", if activated, will be applied to ALL the pictures. EOF } function dg_prepara { echo dg_prepara_show dg_prepara_show | tee "$SHOW".dia } function dg_edit { echo vi "${SHOW}.dia" vi "${SHOW}".dia } function dg_run { DG_LOG="${SHOW}_$DG_OUTPUT.log" echo "$(date +'%d/%m/%y %T') About to start diascope..." > $DG_LOG echo diascope $FOR_WRI -n $DG_PARALLELISM "${SHOW}".dia diascope $FOR_WRI -n $DG_PARALLELISM "${SHOW}".dia 2>&1 | tee -a $DG_LOG echo "See $DG_LOG to verify the diascope last run log." echo "$(date +'%d/%m/%y %T') About to start diascope..." >> $DG_LOG dg_videos } function switch_sound { if [[ "$DG_MPEG2SOUND" = "ac3" ]] then DG_MPEG2SOUND=mp2 else DG_MPEG2SOUND=ac3 fi } function switch_comment { if [[ "$DG_PICT_COMMENT" = "no" ]] then DG_PICT_COMMENT=yes else DG_PICT_COMMENT=no fi } function switch_video { if [[ "$DG_VIDEOS" = "no" ]] then DG_VIDEOS=yes else DG_VIDEOS=no fi } # --------------------------------------------------------------------------- Videos function dg_videos { if [[ "$DG_VIDEOS" = "yes" && $(ls "$SHOW"/*.avi "$SHOW"/*.AVI "$SHOW"/*.MOV "$SHOW"/*.mov 2>/dev/null| wc -w) -gt 0 ]] then # definitions DG_VIDEO_DIR="$SHOW"/video_tmp DG_VIDEO_BIG=$DG_VIDEO_DIR/dg_video_big.avi DG_VIDEO_TMP=$DG_VIDEO_DIR/dg_video_tmp.avi DG_AUDIO_WAV=$DG_VIDEO_DIR/dg_audio_mp3.wav # Create temporary dir if [[ ! -d $DG_VIDEO_DIR ]] then mkdir $DG_VIDEO_DIR fi # ---------------------------------------------------------------------- # Create big video file whith NO AUDIO DG_VIDEO_LIST="" for DG_VIDEO_N in $(ls "$SHOW"/*.AVI "$SHOW"/*.avi "$SHOW"/*.MOV "$SHOW"/*.mov 2>/dev/null) do if [[ "$DG_VIDEO_LIST" = "" ]] then DG_VIDEO_LIST="--load $DG_VIDEO_N" else DG_VIDEO_LIST="$DG_VIDEO_LIST --append $DG_VIDEO_N" fi done avidemux --nogui $DG_VIDEO_LIST --no-audio \ --video-codec COPY --autoindex --output-format AVI \ --save $DG_VIDEO_BIG --quit # Indexing & duration DG_VIDEO_DUR=$(mencoder "$DG_VIDEO_BIG" -forceidx -oac copy -ovc copy -o "$DG_VIDEO_TMP" |\ grep "Video stream"| grep -v found | awk '{print $10}') rm -f $DG_VIDEO_TMP $DG_VIDEO_BIG # Create big audio file with fading at the end sox "$SHOW"/audio4video/* $DG_AUDIO_WAV fade 0 $DG_VIDEO_DUR 3 # Re-Generate the video with the corect audio duration avidemux --nogui $DG_VIDEO_LIST \ --audio-normalize --audio-bitrate 48000 --audio-codec MP2 --external-wav $DG_AUDIO_WAV \ --video-codec COPY --autoindex --output-format AVI \ --save $DG_VIDEO_BIG --quit mv $DG_VIDEO_BIG "$SHOW".avi rm -fr "$SHOW"/video_tmp # ---------------------------------------------------------------------- fi } # --------------------------------------------------------------------------- Perm values function setta_default { #MENU_AUTH="Jack - $(date +'%d/%m/%y')" DG_AUTHOR="Jack" DURATA_FOTO=5 DURATA_TRAN=1 # -- FOR_WRI= DG_CPU_NUM=16 set_desc FOR_WRI $FOR_WRI # ------------------------- DG_FORMAT=pal DG_FPS=25 DG_OUTPUT=mpeg2 DG_OUTPUT_QL=3 DG_OUTPUT_AB=192 DG_QUALITY=10 DG_INTERLACED= DG_ASPECT=4:3 DG_TWOPASS= DG_TRAN_VALUE=1 DG_KENBURNS=0 DG_MPEG2SOUND=mp2 DG_PARALLELISM=16 DG_PICT_COMMENT=no R_W_OPT_DESC="!" DG_VIDEOS=yes } function scrivi_default { R_W_OPT_DESC="=" cat <<-EOF >$PERM_FILE # $(basename $0) permanent values # # Syntax: Variable=Value # DG_AUTHOR=$DG_AUTHOR DURATA_FOTO=$DURATA_FOTO DURATA_TRAN=$DURATA_TRAN FOR_WRI=$FOR_WRI DG_CPU_NUM=$DG_CPU_NUM DG_FORMAT=$DG_FORMAT DG_FPS=$DG_FPS DG_OUTPUT_QL=$DG_OUTPUT_QL DG_OUTPUT_AB=$DG_OUTPUT_AB DG_OUTPUT=$DG_OUTPUT DG_QUALITY=$DG_QUALITY DG_INTERLACED=$DG_INTERLACED DG_ASPECT=$DG_ASPECT DG_TWOPASS=$DG_TWOPASS DG_TRAN_VALUE=$DG_TRAN_VALUE DG_KENBURNS=$DG_KENBURNS DG_MPEG2SOUND=$DG_MPEG2SOUND DG_PARALLELISM=$DG_PARALLELISM DG_PICT_COMMENT=$DG_PICT_COMMENT DG_VIDEOS=$DG_VIDEOS EOF RC=$? R_W_OPT_DESC="=" return $RC } function read_default_val { export $1=$(cat $PERM_FILE | grep -w ^$1 | cut -d= -f2) set_desc FOR_WRI $FOR_WRI } function leggi_default { for VAR in $(cat $PERM_FILE | grep -vE ^# | grep -v ^$ | cut -d= -f1) do read_default_val $VAR done R_W_OPT_DESC="=" } function chk_variations { for VAR in $(cat $PERM_FILE | grep -vE ^# | grep -v ^$ | cut -d= -f1) do DG_PERM_VAL=$(cat $PERM_FILE | grep -vE ^# | grep -v ^$ | grep ^$VAR | cut -d= -f2) DG_CURR_VAL=$(env | grep -w ^$VAR | cut -d= -f2) if [[ $DG_CURR_VAL != $DG_PERM_VAL ]] then R_W_OPT_DESC="!" break fi done } # --------------------------------------------------------------------------- Colors function dg_colors { if [[ "$COLORS" != "NO" ]] then R=$(echo -en "\033[1;31m") G=$(echo -en "\033[1;32m") Y=$(echo -en "\033[1;33m") B=$(echo -en "\033[1;34m") C=$(echo -en "\033[1;35m") L=$(echo -en "\033[1;36m") W=$(echo -en "\033[1;37m") N=$(echo -en "\033[0m") BLINK=$(tput blink) fi } # --------------------------------------------------------------------------- Menu function mp { MP_MAX=36 MP_2_LEN=$(echo "$2" | awk '{print(length($0))}') MP_3_LEN=$(echo "$3" | awk '{print(length($0))}') MP_4_LEN=$(( $MP_MAX - $MP_2_LEN - $MP_3_LEN )) #echo printf "$C%s$N) %-${MP_3_LEN}s$R%${MP_4_LEN}s$N" "<$2>" "<$3>" "<$4>" case $1 in _) printf "$Y%s$N%s" " $3 " "$4" ;; E) printf "$C%s$N) %s $R%s$N" "$2" "$($3)" "$4" ;; O) printf "$C%s$N) %-${MP_3_LEN}s$R%${MP_4_LEN}s$N" "$2" "$3" "$4" ;; M) printf "$C%s$N) %-11s$R%24s$N" "$2" "$3" "$4" ;; esac case $5 in N) printf "\n" ;; S) printf " |" ;; esac } function Menu_display { DATA=$(date +'%d/%m/%y %T') #mp _ S "$N==== $Y$(basename $0)$N ============ by ${G}Marco Jack$N ============= $DATA ==" "" N mp _ S "$N==== $Y$(basename $0)$N = $DG_VERSION ======== by ${G}Marco Jack$N ============= $DATA ===" "" N mp _ M "SHOWs" "------------------------------------------------------------------------" N mp E l "mostra_lista" "" N mp _ M " OPTs" "------------------------------------------------------------------------" N mp O p "Picture duration:" "$DURATA_FOTO" S mp O r "Random tran level:" "$DG_TRAN_VALUE" N mp O t "Transaction:" "$DURATA_TRAN" S mp O k "Pan & Zoom (KenBurns)" "$DG_KENBURNS_DESC" N mp O q "Quality (1 .. 10):" "$DG_QUALITY" S mp O P "Parallelism level" "$DG_PARALLELISM" N mp O o "Output:" "$DG_OUTPUT" S mp O O "Output parameters" "$DG_OUTPUT_OPT" N mp O f "Set video format" "$DG_FORMAT" S mp O T "TwoPass encoding" "$DG_TWOPASS" N mp O a "Aspect:" "$DG_ASPECT" S mp O A "Author:" "$DG_AUTHOR" N mp O s "Sound:" "$DG_MPEG2SOUND" S mp O m "Display picture comment" "$DG_PICT_COMMENT" N mp O v "Manage existing camera videos" "$DG_VIDEOS" N mp _ M "MISCs" "------------------------------------------------------------------------" N mp O n "Normalize sound files" "" S mp O S "Translate space in file names" "" N mp _ M "STEPs" "------------------------------------------------------------------------" N mp O 1 "Generate dia file(s)" "" S mp O d "Force delete previous run:" "$FOR_WRI_DESC" N mp O 2 "Edit them with 'vi'" "" S mp O C "Cancel temporary files" "" N mp O 3 "Run diascope" "" S mp O "R W D" "Parameter management" "" N mp O 4 "See video(s) in vlc " "" S mp O V "Generate ALL video types" "" N #mp _ M " MENU" "------------------------------------------------------------------------" N #mp M A "Author: " "$MENU_AUTH" N #mp M U "Menu name: " "$MENU_NAME" N #mp M F "Background:" "$MENU_FOTO" S #mp M M "Sountrack: " "$MENU_MUSI" N #mp E V "echo Guarda il DVD generato" "" N mp _ M "" "-----------------------------------------------------------------------------" N mp O H "Help & Usage" "" S mp O I "Scope & Installation" "" N mp _ S "= E exit ===============================================================$ERRORI=$R_W_OPT_DESC=" "" N } function Menu { clear while [[ $ESCI = "" ]] do formal_chk Menu_display printf "> " && read ANS case $ANS in l) Componi_lista M ;; # F) Scegli jpg MENU_FOTO 'Menu picture: ' $MENU_FOTO ;; # M) Scegli mp3 MENU_MUSI 'Soundtrack: ' $MENU_MUSI ;; # U) Scegli "j" MENU_NAME 'Name: ' $MENU_NAME ;; A) Scegli "j" DG_AUTHOR 'Author: ' $DG_AUTHOR ;; p) Scegli "j" DURATA_FOTO 'Picture time: ' $DURATA_FOTO ;; t) Scegli "j" DURATA_TRAN 'Transaction time: ' $DURATA_TRAN ;; d) switch_var FOR_WRI -clean $FOR_WRI ;; # i) switch_var DG_INTERLACED interlaced $DG_INTERLACED ;; k) Scegli "j" DG_KENBURNS '1=no 2..n' $DG_KENBURNS ;; T) switch_var DG_TWOPASS twopass $DG_TWOPASS ;; q) Scegli "j" DG_QUALITY '10=hi 5=med 1=low' $DG_QUALITY ;; o) Scegli "j" DG_OUTPUT 'Output: dv mpeg2 mpeg4 flv' $DG_OUTPUT ;; O) case $DG_OUTPUT in dv) echo "No parameters can be defined for $DG_OUTPUT" ;; * ) Menu_output_parms ;; esac ;; a) Scegli "j" DG_ASPECT 'Aspect: 1:1 4:3 16:9' $DG_ASPECT ;; s) switch_sound ;; f) Menu_format ;; m) switch_comment ;; v) switch_video ;; r) Scegli_transazioni Scegli "j" DG_TRAN_VALUE 'Level: ' $DG_TRAN_VALUE ;; P) Scegli "j" DG_PARALLELISM 'Parallelism level 1..48:' $DG_PARALLELISM ;; n) go_action dg_normalize_audio attendi;; S) echo "Translate space into "_" in file names" go_action translate_space attendi;; V) echo "Procedure to generate ALL video types: dv mpeg2 mpeg4 flv" separa echo "Re-generating audio" go_action dg_create_soundtrk separa printf "Activate FORCE DELETE option: " FOR_WRI="-clean" echo "ok." separa echo "Saving original diascope file" go_action dg_save_original_file for DG_OUTPUT_NEW in \ dv \ mpeg2=$DG_OUTPUT_QL,$DG_OUTPUT_AB \ mpeg4=$DG_OUTPUT_QL,$DG_OUTPUT_AB \ flv=$DG_OUTPUT_QL,$DG_OUTPUT_AB do separa; go_action dg_change_output separa; go_action dg_run done separa; go_action dg_restore_original_file attendi ;; C) echo "Deletion procedure: do you really want to ${R}delete$N TEMPORARY files?" printf "[yes|NO] > " ; read CANCEL if [[ "$CANCEL" = "yes" ]] then go_action dg_cancel_tmp attendi fi ;; D) setta_default if [[ $RC -eq 0 ]] then echo "Default values activated." else echo "ERROR in storing values into file $PERM_FILE: RC=$RC" fi attendi ;; R) leggi_default if [[ $RC -eq 0 ]] then echo "Previous stored values read." else echo "ERROR in reading values from file $PERM_FILE: RC=$RC" fi attendi ;; W) scrivi_default if [[ $RC -eq 0 ]] then echo "Defined values stored." else echo "ERROR in storing values into file $PERM_FILE: RC=$RC" fi attendi ;; 1) go_action dg_prepara attendi ;; 2) go_action dg_edit attendi ;; 3) go_action dg_create_soundtrk go_action dg_run go_action dg_delete_soundtrk attendi ;; 4) # go_action crea_videoshow_avi go_action see_movie attendi ;; # 6) crea_menu_dvd # attendi ;; "?"|h) Help 1 "HELP page:" Help 2 "HELP page:" Help 3 "HELP page:" ;; i|I) Help A "Installation:" Help B "Installation:" ;; e|E) ESCI=ESCI ;; esac formal_chk clear done printf "\n\n Thanks for using %s$DG_DIA_GEN%s by %sMarco Jack%s" $Y $N $G $N printf "\n\nBye\n\n" } function Menu_output_parms { mp _ M "Output format parameters" " " N mp _ M " " "------------------------------------------------------------------------" N mp O q "Quality [0=best, 31=worst]:" "$DG_OUTPUT_QL" N mp O a "Audio bitrate:" "$DG_OUTPUT_AB" N mp _ M " " "------------------------------------------------------------------------" N printf "> " && read DG_FORMAT_TMP case $DG_FORMAT_TMP in q) printf "Output quality: " && read DG_ANS if [[ $DG_ANS -ge 0 && $DG_ANS -lt 32 ]] then DG_OUTPUT_QL=$DG_ANS else echo "The range is 1..31" && read DG_ANS fi ;; a) printf "Audio bitrate: " && read DG_ANS if [[ $DG_ANS -ge 0 && $DG_ANS -lt 640 ]] then DG_OUTPUT_AB=$DG_ANS else echo "Wrong parameter." fi ;; esac } function Menu_format { mp _ M "Output format definition" " " N mp _ M " " "------------------------------ Standards -------------------------------" N mp O p "Pal :" "720x576@25" S mp O f "Frame per second [25|29.97|...]:" "$DG_FPS" N mp O n "Ntsc :" "720x576@29.97" N mp _ M " " "----------------------------- pre-defined ------------------------------" N mp O 1 "320x240@$DG_FPS" " " S mp O 2 "640x480@$DG_FPS" " " N mp O 3 "800x600@$DG_FPS" " " S mp O 4 "1024x768@$DG_FPS" " " N mp O 5 "1280x720@$DG_FPS" " " S mp O 6 "1440x1080@$DG_FPS" " " N mp O 7 "1920x1080@$DG_FPS" " " S mp O 8 "1920x1280@$DG_FPS" " " N mp _ M " " "----------------------------- User defined -----------------------------" N mp O 9 "Actual:" "$DG_FORMAT" N mp _ S "================================================================================" "" N printf "\nChoose your preferred format for the final video: " read DG_FORMAT_TMP case $DG_FORMAT_TMP in p) DG_FORMAT=pal DG_FPS=25 ;; n) DG_FORMAT=ntsc DG_FPS=29.97 ;; f) DG_FPS=$DG_FORMAT_TMP ;; 1) DG_FORMAT=320x240@$DG_FPS ;; 2) DG_FORMAT=640x480@$DG_FPS ;; 3) DG_FORMAT=800x600@$DG_FPS ;; 4) DG_FORMAT=1024x768@$DG_FPS ;; 5) DG_FORMAT=1280x720@$DG_FPS ;; 6) DG_FORMAT=1440x1080@$DG_FPS ;; 7) DG_FORMAT=1920x1080@$DG_FPS ;; 8) DG_FORMAT=1920x1280@$DG_FPS ;; 9) echo "Personalyze your settings: " read DG_FORMAT ;; *) echo "Unrecognized choice. :-) " ;; esac formal_chk } function dg_is_number { printf "%i" $1 >/dev/null 2>&1 return $? } function formal_chk { if [[ $(dg_is_number $DURATA_FOTO) || $(echo $DURATA_FOTO | bc) -eq 0 ]] then echo " Wrong picture duration: $DURATA_FOTO." read_default_val DURATA_FOTO echo " Must be > 0: now $DURATA_FOTO" read ANS fi if [[ $(dg_is_number $DURATA_TRAN) || $(echo $DURATA_TRAN | bc) -le 0 ]] then echo " Wrong transaction duration: $DURATA_TRAN." read_default_val DURATA_TRAN echo " Must be > 0: now $DURATA_TRAN" read ANS fi if [[ $(dg_is_number $DG_QUALITY ) || $(echo $DG_QUALITY | bc) -lt 1 || $(echo $DG_QUALITY | bc) -gt 10 ]] then echo " Wrong picture duration: $DG_QUALITY." read_default_val DG_QUALITY echo " Must be >= 1 and <= 10: now $DG_QUALITY " read ANS fi if [[ $(dg_is_number $DG_TRAN_VALUE ) || $(echo $DG_TRAN_VALUE | bc) -lt 1 || $(echo $DG_TRAN_VALUE | bc) -gt 7 ]] then echo " Random transaction value: $DG_TRAN_VALUE." read_default_val DG_QUALITY echo " Must be >= 1 and <= 10: now $DG_TRAN_VALUE " read ANS fi if [[ $DG_MPEG2SOUND != "ac3" && $DG_MPEG2SOUND != "mp2" ]] then echo "Invalid sound specification: $DG_MPEG2SOUND" read_default_val DG_MPEG2SOUND echo " Must be ac3 or mp2: now $DG_MPEG2SOUND" read ANS fi if [[ $(dg_is_number $DG_PARALLELISM ) || $(echo $DG_PARALLELISM | bc) -lt 1 || $(echo $DG_PARALLELISM | bc) -gt 48 ]] then echo " Wrong parallelism level: $DG_PARALLELISM." read_default_val DG_PARALLELISM echo " Must be >= 1 and <= 48: now $DG_PARALLELISM " read ANS fi if [[ "$DG_OUTPUT" = flv && "$DG_TWOPASS" != "" ]] then echo "$DG_OUTPUT and $DG_TWOPASS are INCOMPATIBLE." switch_var DG_TWOPASS twopass $DG_TWOPASS echo "TwoPass Switched off." read ANS fi case $DG_OUTPUT in dv|mpeg2|mpeg4|flv) ;; *) echo " Video output value: $DG_OUTPUT." read_default_val DG_OUTPUT echo " Must be dv|mpeg2|mpeg4|flv: now $DG_OUTPUT " read ANS ;; esac case $DG_ASPECT in 1:1|4:3|16:9) ;; *) echo " Video aspect value: $DG_ASPECT." read_default_val DG_ASPECT echo " Must be "1:1"|"4:3"|"16:9": now $DG_ASPECT. " echo " To do: set free aspect." read ANS ;; esac if [[ $DG_KENBURNS -lt 2 ]] then DG_KENBURNS_DESC="no" else DG_KENBURNS_DESC="yes: $DG_KENBURNS" fi case $DG_FORMAT in pal) DG_FPS=25;; ntsc) DG_FPS=29.97 ;; *) DG_FPS=$(echo $DG_FORMAT | cut -d "@" -f2) esac chk_variations # ------------------------ DG_OUTPUT_OPT if [[ "$DG_OUTPUT" = "dv" ]] then DG_OUTPUT_OPT="" else DG_OUTPUT_OPT="=$DG_OUTPUT_QL,$DG_OUTPUT_AB" fi } # ==================================================================== MAIN # ----------------------------------------- Inizializzazione variabili #MENU_FOTO=$(ls *.jpg *.JPG 2>/dev/null | head -n 1) #MENU_MUSI=$(ls *.mp3 *.MP3 2>/dev/null | head -n 1) #MENU_NAME=$(basename "$(pwd)") ERRORI="===" # ------------------------------ Command line parameters while getopts "BhH" OPT do case $OPT in B) COLORS=NO;; h*|H*) dg_syntax;; esac done shift $(echo $OPTIND-1|bc) # ------------------------------ Supplementary programs printf "Check supplementary programs:\n" for EXTRA in jhead avidemux do which $EXTRA > /dev/null if [[ $? -eq 0 ]] then printf "%20s ok\n" $EXTRA else printf "%20s missing!\n" $EXTRA read ANS fi done # ------------------------------ Permanent values inizialization setta_default if [[ -f $PERM_FILE ]] then leggi_default else scrivi_default fi # ------------------------------ DG_FADE_IN_OUT=5 for D in /usr/lib/kino /usr/lib64/kino do if [[ -d $D ]] then LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$D fi done # ------------------------------ dir list populating if [[ $# -eq 0 ]] then Componi_lista A else LIST_SHOW_IND=0 while [[ "$1" != "" ]] do if [[ -d "$1" && "$1" != "-nocolors" ]] then LIST_SHOW[$LIST_SHOW_IND]=$1 let LIST_SHOW_IND=LIST_SHOW_IND+1 else echo "Directory >$1<" echo "not found. Check the parameter list!" attendi fi shift done fi # ----------------------------------------- GO ! ESCI="" dg_colors Menu