#!/bin/bash

# Edit settings below and run with:
#     bash prepare_video.sh | bash

FFMPEG=~/bin/ffmpeg

SCRIPT_DIR=$(dirname $0)
CONF_FILE=${0%\.*}.conf

[ -r $CONF_FILE ] && . $CONF_FILE                 # Read default settings

[ "$1" != "" ] && . $1       # Read specified config file, overruling any defaults above

mkdir -p "$TEMP_DIR/" "$TEMP2_DIR/" "$OUTPUT_DIR/"

echo -n "# Reading EXIF meta data... "
exiftool ${LAPTOP_FILES[*]}     > "$TEMP_DIR/laptop_exif.txt"
exiftool ${CAMERA_FILES[*]}     > "$TEMP2_DIR/camera_exif.txt"
echo "done"

ns_camera=$( exiftool -s -s -s -dateFormat "%s.000000000" -DateTimeOriginal ${CAMERA_FILES[0]} )
dt_camera=$( date -d @${ns_camera} '+%F %T.%N' )

dt_laptop=$( echo ${LAPTOP_FILES[0] } | sed -e 's/^.*\(20[0-9][0-9]-[0-9][0-9]-[0-9][0-9]\)[^0-9]*\([0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9]\).\([0-9]*\).*$/\1 \2:\3:\4.\5/' )
ns_laptop=$( date -d "$dt_laptop" +%s.%9N )

echo "# Timestamp camera recording: $dt_camera  (unix: $ns_camera s)"
echo "# Timestamp laptop recording: $dt_laptop  (unix: $ns_laptop s)"
echo "# Adjust for difference in clocks: $(( ${CLOCK_DELTA_NS:-0} / 1000000000 )).$(( ${CLOCK_DELTA_NS:-0} % 1000000000 )) s"

ns_delta=$(( ${ns_camera/./} - ${ns_laptop/./} - ${CLOCK_DELTA_NS:-0} -8037720770 ))
echo -n "# LAPTOP_SKIP ... $LAPTOP_SKIP"
if [ "$LAPTOP_SKIP" = "auto" ]; then
 LAPTOP_SKIP="$(( $ns_delta / 1000000000 )).$(( $ns_delta % 1000000000 ))"
 echo -n " => $LAPTOP_SKIP"
fi
echo " s"

cat > "$TEMP2_DIR/duration.sh" <<~~~
#!/bin/bash

# Get expected duration of full video (from source files)
$FFMPEG -hide_banner -loglevel info -stats \\
 -ss ${CAMERA_SKIP:-0} -i "concat:$( IFS=$'|' ; echo "${CAMERA_FILES[*]}" )" \\
 2>&1 | sed -ne 's/^ *Duration: \([0-9:.]*\).*$/\1/p'
~~~

if [ "$CAMERA_DURATION" = "" ]; then
 CAMERA_DURATION=$( bash "$TEMP2_DIR/duration.sh" )
fi
CAMERA_DURATION_S=$CAMERA_DURATION
if date -d "1970-01-01Z${CAMERA_DURATION}" 2>&1 >/dev/null ; then
 CAMERA_DURATION_S=$(  date -d "1970-01-01Z${CAMERA_DURATION}" "+%s" )
 CAMERA_DURATION_NS=$( date -d "1970-01-01Z${CAMERA_DURATION}" "+%N" )
fi
echo "# Camera recording duration: $CAMERA_DURATION = $CAMERA_DURATION_S.$CAMERA_DURATION_NS s"

if [ "$LAPTOP_AUTOCROP" = 1 ]; then
 echo -n "# Detecting autocrop value... "
 # TODO: Quickly skip through the whole file (instead of only a few seconds). Need duration of $CAMERA_FILES to
 # know when to stop though...
 LAPTOP_CROP=$(
  $FFMPEG -hide_banner -ss "${LAPTOP_SKIP:-0}" -i "concat:$( IFS=$'|' ; echo "${LAPTOP_FILES[*]}" )" -t 10 -vf cropdetect -f null - 2>&1 |
   awk '/crop/ { print $NF }' | tail -1
 )
 echo $LAPTOP_CROP
fi

#  -ss ${INTRO_SKIP:-0} -i "concat:$( IFS=$'|' ; echo "${INTRO_FILES[*]}" )" \\
#  [4:v] scale=1920*0.8:-1                                                     [intro];

# TODO: -itsoffset 5  (maybe, problem: FIXED_AUDIO goes out of sync, but not by 5 seconds...)

AUDIO_EXT=wav          # wav uncompressed, fast but large
#AUDIO_EXT=ogg          # ogg is nice and small, but lossy. suitable for editing? (slow !)
#AUDIO_EXT=flac         # quite large, but fast
INPUT_AUDIO="[0:a]"
#INPUT_AUDIO="[1:a]"  # TODO: Would like to use laptop audio by default, but ffmpeg can't seek accurately to correct starting position (within mkv)
AUDIO_PAN="pan=3.0|c0=FL|c1=FR|c2=FC"
if [ -f "$AUDIO_FIXED" ]; then
 INPUT_AUDIO_FIXED="-ss \"${AUDIO_SKIP:-0}\" ${CAMERA_DURATION:+-t \"$CAMERA_DURATION\"} -i \"$AUDIO_FIXED\""
 INPUT_AUDIO="[4:a]"
 AUDIO_PAN="pan=stereo|c0=FL|c1=FR"
# AUDIO_PAN=""
fi

cat > "$TEMP2_DIR/extract_camera_audio.sh" <<~~~
#!/bin/bash

# Extract camera audio for editing in e.g. Audacity:
#$FFMPEG -hide_banner -loglevel warning -stats \\
# -i "concat:$( IFS=$'|' ; echo "${CAMERA_FILES[*]}" )" \\
# -vn -codec:a copy "$TEMP2_DIR/camera_audio_original.tmp.ac3" &&
# mv "$TEMP2_DIR/camera_audio_original.tmp.ac3" "$TEMP2_DIR/camera_audio_original.ac3"

$FFMPEG -hide_banner -loglevel warning -stats \\
 -i "concat:$( IFS=$'|' ; echo "${CAMERA_FILES[*]}" )" \\
 -vn -codec:a pcm_f32le "$TEMP2_DIR/camera_audio_original.tmp.$AUDIO_EXT" &&
 mv "$TEMP2_DIR/camera_audio_original.tmp.$AUDIO_EXT" "$TEMP2_DIR/camera_audio_original.$AUDIO_EXT"
~~~

cat > "$TEMP2_DIR/extract_laptop_audio.sh" <<~~~
#!/bin/bash

# Extract laptop audio for editing in e.g. Audacity:
$FFMPEG -hide_banner -loglevel warning -stats \\
 -ss ${LAPTOP_SKIP:-0} -t $CAMERA_DURATION_S.$CAMERA_DURATION_NS \\
 -i "concat:$( IFS=$'|' ; echo "${LAPTOP_FILES[*]}" )" \\
 -vn -codec:a copy "$TEMP2_DIR/laptop_audio_original.tmp.$AUDIO_EXT" &&
 mv "$TEMP2_DIR/laptop_audio_original.tmp.$AUDIO_EXT" "$TEMP2_DIR/laptop_audio_original.$AUDIO_EXT"
~~~

cat > "$TEMP_DIR/extract_all_laptop_audio.sh" <<~~~
#!/bin/bash

# Extract laptop audio for editing in e.g. Audacity:
$FFMPEG -hide_banner -loglevel warning -stats \\
 -i "concat:$( IFS=$'|' ; echo "${LAPTOP_FILES[*]}" )" \\
 -vn -codec:a copy "$TEMP_DIR/laptop_audio_original.tmp.$AUDIO_EXT" &&
 mv "$TEMP_DIR/laptop_audio_original.tmp.$AUDIO_EXT" "$TEMP_DIR/laptop_audio_original.$AUDIO_EXT"
~~~

cat > "$TEMP2_DIR/corrolate_audio_offset.praat" <<~~~
form Cross Correlate two Sounds
	sentence Input_sound_1
	sentence Input_sound_2
	real start_time 0
	real end_time 30
endform

Open long sound file... 'Input_sound_1$'
Extract part: 0, 60, "no"
Extract one channel... 1
sound1 = selected("Sound")
Open long sound file... 'Input_sound_2$'
Extract part: 0, 60, "no"
Extract one channel... 1
sound2 = selected("Sound")

select sound1
plus sound2
Cross-correlate: "peak 0.99", "zero"
offset = Get time of maximum: 0, 0, "Sinc70"

writeInfoLine: 'offset'
~~~

cat > "$TEMP2_DIR/corrolate_audio_offset.sh" <<~~~
#!/bin/bash

cd "$TEMP2_DIR"
praat corrolate_audio_offset.praat camera_audio_original.$AUDIO_EXT laptop_audio_original.$AUDIO_EXT
cd -
~~~

# Automatically find scene changes (iframes in video captured by record_desktop.sh) :
# ffprobe -hide_banner -loglevel warning -sexagesimal -of compact -select_streams v -show_frames 
# -show_entries frame=pkt_pts_time,pict_type capture_2015-03-03_192617.028248517.mkv |
# sed -une '/pict_type=I$/ s/^.*pkt_pts_time=\([0-9:.]*\)|.*/\1/p' | tee iframes.txt | ( while read line ; do echo -ne "\r$line" ; done ; echo )
# https://sites.google.com/site/linuxencoding/x264-ffmpeg-mapping
cat > "$TEMP2_DIR/extract_laptop_scene_times.sh" <<~~~
#!/bin/bash

# Automatically find scene changes (iframes in video captured by record_desktop.sh) :
$FFMPEG -hide_banner -loglevel warning -stats \\
 -i "${LAPTOP_FILES[*]}" -vf scale=$((1024 / 4)):-1 -an -g 32000 -sc_threshold 255  -preset ultrafast \\
 -y "$TEMP_DIR/laptop_thumbnail.mkv" &&
ffprobe -hide_banner -loglevel warning -sexagesimal -of compact -select_streams v -show_frames \\
 -show_entries frame=pkt_pts_time,pict_type "$TEMP_DIR/laptop_thumbnail.mkv" |
  sed -une '/pict_type=I\$/ s/^.*pkt_pts_time=\([0-9:.]*\)|.*/\1/p' |
  tee "$TEMP_DIR/laptop_scene_times.txt.tmp" | ( 
    while read line ; do
      echo -ne "\r\$line"
    done
    echo 
  ) &&
  mv "$TEMP_DIR/laptop_scene_times.txt.tmp" "$TEMP_DIR/laptop_scene_times.txt"
~~~

( cat | sed -e 's/\t\t*/\t/g' | expand --tabs=2,80 ) > "$TEMP2_DIR/encode_video.sh" <<~~~
#!/bin/bash

time $FFMPEG -hide_banner -loglevel warning -stats -threads 0 \\
 -ss "${CAMERA_SKIP:-0}" -i "concat:$( IFS=$'|' ; echo "${CAMERA_FILES[*]}" )" \\
 -ss "${LAPTOP_SKIP:-0}" -i "concat:$( IFS=$'|' ; echo "${LAPTOP_FILES[*]}" )" \\
 -i "concat:$( IFS=$'|' ; echo "${BACKGROUND_FILES[*]}" )" \\
 -i "concat:$( IFS=$'|' ; echo "${LOGO_FILES[*]}" )" \\
 $INPUT_AUDIO_FIXED \\
 -metadata title="$META_TITLE" \\
 -metadata author="$META_SPEAKER" \\
 -metadata event="$META_EVENT" \\
 -filter_complex "
  color=${BACKGROUND_COLOR}:size=1920x1080																[canvas];
  [0:v] crop=796:604:196:470${CAMERA_BRIGHTNESS:+,lutyuv=y=val*$CAMERA_BRIGHTNESS}
       ,scale=1920/2.4:-1
       ,pad=iw+$BORDER_PX*2:ih+$BORDER_PX*2:$BORDER_PX:$BORDER_PX:color=$BORDER_COLOR					[speaker];
  [1:v] ${LAPTOP_CROP:+$LAPTOP_CROP,}scale=2*1920/3-$PADDING_PX*2:-1,scale=-1:clip(ih\,400\,850)
       ,pad=width=iw+$BORDER_PX*2:height=ih+$BORDER_PX*2:x=$BORDER_PX:y=$BORDER_PX:color=$BORDER_COLOR	[laptop];
  [2:v] scale=1920:1080:force_original_aspect_ratio=increase,crop=1920:1080								[back];
  [3:v] scale=1920/6-3*$PADDING_PX:-1																	[logo];
  $INPUT_AUDIO ${AUDIO_PAN:+$AUDIO_PAN,}volume=1dB														[audio];
  [canvas][back] overlay=																				[back];
  color=#00000000:size=1920x1080																		[trans];
  [back]drawtext='x=(main_w-text_w)/2+$PADDING_PX
                 :y=$PADDING_PX*2
                 :fontcolor=$FONT_COLOR
                 :borderw=$FONT_BORDER_PX
                 :bordercolor=$FONT_BORDER_COLOR
                 :shadowcolor=$FONT_SHADOW_COLOR
                 :shadowx=-$FONT_SHADOW_PX
                 :shadowy=$FONT_SHADOW_PX
                 :fontsize=80
                 :fontfile=/usr/share/fonts/dejavu/DejaVuSerif.ttf
                 :expansion=none
                 :textfile=$TEMP2_DIR/header.txt
                 '                                                            
$(cat "$TEMP2_DIR/titlescreen.txt" | while read LINE; do 
  LINENR=$(($LINENR+1))
  sed -ne "$LINENR p" "$TEMP2_DIR/titlescreen.txt" | sed -ze 's/\n//g' >"$TEMP2_DIR/titlescreen_${LINENR}.txt"

cat <<~~~2
       ,drawtext='x=(main_w-text_w)/2
                 :y=200+$LINENR*100
                 :enable=between(t, 0, 10)
                 :fontcolor=$FONT_COLOR
                 :borderw=$FONT_BORDER_PX
                 :bordercolor=$FONT_BORDER_COLOR
                 :shadowcolor=$FONT_SHADOW_COLOR
                 :shadowx=-$FONT_SHADOW_PX
                 :shadowy=$FONT_SHADOW_PX
                 :fontsize=60
                 :fontfile=/usr/share/fonts/dejavu/DejaVuSerif.ttf
                 :expansion=none
                 :textfile=$TEMP2_DIR/titlescreen_${LINENR}.txt
                 '
~~~2
  done
)
       ,drawtext='x=main_w-mod(main_w+max(0\,50*t-1100)\,main_w+text_w)
                 :y=main_h-text_h-$PADDING_PX-$BORDER_PX-$FONT_SHADOW_PX
                 :enable=gt(t,10)
                 :fontcolor=$FONT_COLOR
                 :borderw=$FONT_BORDER_PX
                 :bordercolor=$FONT_BORDER_COLOR
                 :shadowcolor=$FONT_SHADOW_COLOR
                 :shadowx=-$FONT_SHADOW_PX
                 :shadowy=$FONT_SHADOW_PX
                 :fontsize=60
                 :fontfile=/usr/share/fonts/dejavu/DejaVuSerif.ttf
                 :expansion=none
                 :textfile=$TEMP2_DIR/banner.txt
                 '																						[text];
  [trans][logo]  overlay=main_w-w-$PADDING_PX:100+$PADDING_PX											[tmp];
  [tmp][laptop]  overlay=$PADDING_PX:100+$PADDING_PX:shortest=1											[tmp];
  [tmp][speaker] overlay=main_w-w-$PADDING_PX:main_h-h-$PADDING_PX:shortest=1							[tmp];
  [tmp]          ${FADE_IN:+$FADE_IN}																	[tmp];
  [text][tmp]    overlay=shortest=1																		[video]
 " \\
 -shortest -map '[video]' -shortest -map '[audio]' \\
 -codec:v libx264 -codec:a ac3 -y -shortest "$OUTPUT_DIR/$OUTPUT_FILE"
~~~

# 10% smaller at 1.5x encoding time:   -preset veryslow -tune film

cat > "$TEMP2_DIR/readme.txt" <<~~~
Edit camera_audio_original.$AUDIO_EXT or laptop_audio_original.$AUDIO_EXT in for example Audacity and
save your edited version as fixed/camera_audio_fixed.$AUDIO_EXT or fixed/laptop_audio_fixed.$AUDIO_EXT so
it will automatically be picked up when you run prepare_video.sh again.
~~~

if [ -f "$TEMP2_DIR/camera_audio_original.$AUDIO_EXT" -o -f "$TEMP2_DIR/laptop_audio_original.$AUDIO_EXT" -o -f "$AUDIO_FIXED" ]; then
 echo "# Audio already extracted. Edit and save as source/{camera,laptop}_audio_fixed.$AUDIO_EXT if necessary. Then"
 echo "# make sure to specify AUDIO_FIXED and AUDIO_SKIP in the config file."
else
 echo "# Extracting audio. Edit and save as source/{camera,laptop}_audio_fixed.$AUDIO_EXT if necessary. Then"
 echo "# make sure to specify AUDIO_FIXED and AUDIO_SKIP in the config file."
 echo "# $TEMP2_DIR/camera_audio_original.$AUDIO_EXT ... "
 bash "$TEMP2_DIR/extract_camera_audio.sh" || exit 1
 echo
 echo "# $TEMP2_DIR/laptop_audio_original.$AUDIO_EXT ... "
 bash "$TEMP2_DIR/extract_laptop_audio.sh" || exit 1
 echo
fi

#if [ ! -f "$TEMP_DIR/laptop_scene_times.txt" ]; then
# echo "# Finding scene changes in laptop recording ... "
# bash "$TEMP2_DIR/extract_laptop_scene_times.sh" || exit 1
# echo -e "\r$TEMP_DIR/laptop_scene_times.txt"
#fi

if [ "$2" == "final" ]; then
 echo "# Encoding final video... "
 bash "$TEMP2_DIR/encode_video.sh" || exit 1
fi

echo

exit 0

TODO: 

# -strict -2  ?

* Banner on top?
* 
* Automatic synchronisation !!!!
* Introduction screen, few seconds with music
* fade audio
* fade in videos
* use st() and ld() functions

* Rewrite whole thing to use makefile?

* add wallclock in record script
* Automatically crop speaker video following the face
  script that plays whole vid and records bounding box of motion every frame. generate
  ffmpeg filter that continuously adjusts the cropping towards the bounding box (with 
  delay and accelleration)
  Filter motion: ~/bin/ffmpeg -ss 30 -i "source/AVCHD/BDMV/STREAM/00000.MTS" -filter_complex "[0] select='eq(pict_type\,I)',format=rgba,tblend=all_mode=difference,format=yuva422p10le" -an difference.mkv
  Camera has all frames as I-frames, so select filter doesnt help...
~/bin/ffmpeg -i difference.mkv -ss 5 -t 20 -vf cropdetect=30:16:1 -f null - 2>&1 | awk '/crop/ { print $NF }' | sort -bn | uniq -c | sort -bn
  Take outer edges of crops with linecount > 10% of total lines.

* Automatic noise reduction: 
   1) always record a few seconds of "silence" with the camera
   2) use the audio from that MTS file to create a noise profile and automatically reduce it using:
      http://www.zoharbabin.com/how-to-do-noise-reduction-using-ffmpeg-and-sox/
      and/or
      http://superuser.com/questions/733061/reduce-background-noise-and-optimize-the-speech-from-an-audio-clip-using-ffmpeg

* Upload to youtube:
  https://developers.google.com/youtube/v3/guides/uploading_a_video
  http://www.cnx-software.com/2014/02/09/how-to-upload-youtube-videos-with-the-command-line-in-linux/

ffmpeg filters:
- earwax (audio)
- normalize (audio)
- pan (audio, gain channels)

* Audio filters from Veritas:  List of proccesses used:
  - Equalizer
  - Gate
  - DeEsser
  - Stereo Imager
  - Compression


Sources / examples:
https://ffmpeg.org/ffmpeg-filters.html
https://www.ffmpeg.org/ffmpeg-utils.html#Color
http://superuser.com/questions/323119/how-can-i-normalize-audio-using-ffmpeg
http://stackoverflow.com/questions/18152745/multiple-overlay-movies-in-ffmpeg
http://stackoverflow.com/questions/13390714/superimposing-two-videos-onto-a-static-image
http://superuser.com/questions/688256/how-to-add-a-video-on-a-template-with-ffmpeg
https://trac.ffmpeg.org/wiki/AudioChannelManipulation

