290 lines
8.5 KiB
Bash
Executable File
290 lines
8.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
IFS=$'\n\t'
|
|
|
|
# === Gestion des arguments ===
|
|
PROCESS_ALL=false
|
|
PRINT_ERR=false
|
|
|
|
# Fonction pour afficher l'aide
|
|
usage() {
|
|
echo "Usage: $0 [--all|-a]"
|
|
echo "Options:"
|
|
echo " --all, -a Traiter tous les fichiers (ignore la liste de fichiers)"
|
|
echo " --force, -f Traiter les fichiers ignorés"
|
|
echo " --help, -h Afficher cette aide"
|
|
echo " --print-err, -e Afficher les erreurs en stderr et non dans le fichier de logs"
|
|
exit 1
|
|
}
|
|
|
|
# Traitement des arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--all|-a)
|
|
PROCESS_ALL=true
|
|
shift
|
|
;;
|
|
--force|-f)
|
|
PROCESS_IGNORED_FILES=true
|
|
shift
|
|
;;
|
|
--help|-h)
|
|
usage
|
|
;;
|
|
--print-err|-e)
|
|
PRINT_ERR=true
|
|
shift
|
|
;;
|
|
*)
|
|
echo "Option inconnue : $1" >&2
|
|
usage
|
|
;;
|
|
esac
|
|
done
|
|
|
|
SCRIPTS_DIR=$(dirname `realpath ${BASH_SOURCE[0]}`)
|
|
|
|
# === CONFIGURATION ===
|
|
export DOSSIER_SOURCE="${HOME}/Downloads"
|
|
export DOSSIER_DESTINATION_RAW="${HOME}/Documents/.DanceVideos/raw"
|
|
export TEMP_FILE="/tmp/dancevideos_moved_files_$RANDOM.txt"
|
|
|
|
# Initialiser le fichier temporaire
|
|
> "$TEMP_FILE"
|
|
|
|
sanitize_name() {
|
|
local name="$1"
|
|
basename "$name" \
|
|
| tr '[:upper:]' '[:lower:]' \
|
|
| tr ' ' '_' \
|
|
| tr -cd '[:alnum:]._-\n'
|
|
}
|
|
export -f sanitize_name
|
|
|
|
source $SCRIPTS_DIR/append_with_lock.sh
|
|
|
|
# Fonction pour vérifier et déplacer un fichier
|
|
check_and_move() {
|
|
local fichier="$1"
|
|
local taille1 taille2
|
|
taille1=$(stat -f "%z" "$fichier")
|
|
sleep 5
|
|
taille2=$(stat -f "%z" "$fichier")
|
|
|
|
if [ "$taille1" -eq "$taille2" ] && [ "$taille2" -gt 0 ]; then
|
|
echo "Déplacement de $(basename "$fichier")"
|
|
rsync -av --remove-source-files "$fichier" "$DOSSIER_DESTINATION_RAW/$(sanitize_name "$(basename "$fichier")")"
|
|
if ! append_with_lock "$DOSSIER_DESTINATION_RAW/$(sanitize_name "$(basename "$fichier")")" "$TEMP_FILE"; then
|
|
echo "Échec de l'écriture dans $TEMP_FILE (timeout)" >&2
|
|
fi
|
|
else
|
|
echo "Fichier $(basename "$fichier") encore en cours de réception."
|
|
fi
|
|
}
|
|
export -f check_and_move
|
|
|
|
import_downloaded_file() {
|
|
find "$DOSSIER_SOURCE" -maxdepth 1 -type f \( -iname "*.mp4" -o -iname "*.mov" \) -print0 \
|
|
| parallel -0 -j 4 check_and_move
|
|
}
|
|
import_downloaded_file
|
|
|
|
##
|
|
|
|
export DOSSIER_DESTINATION_MP4="$(dirname $DOSSIER_DESTINATION_RAW)/videos"
|
|
|
|
## DB utilities
|
|
export DANCE_VIDEOS_DB="$(dirname $DOSSIER_DESTINATION_RAW)/db.sqlite"
|
|
export MODEL_DIR=$(realpath $SCRIPTS_DIR/../model)
|
|
|
|
cat $MODEL_DIR/videos.sql | sqlite3 $DANCE_VIDEOS_DB
|
|
|
|
source $MODEL_DIR/register_video.sh
|
|
# register_video \
|
|
# file_name raw_file duration mp4_file \
|
|
# rotated_file thumbnail_file record_datetime day_of_week \
|
|
# lat long address
|
|
|
|
source $SCRIPTS_DIR/metadata.sh
|
|
source $SCRIPTS_DIR/rotation.sh
|
|
|
|
mp4_dir() {
|
|
local raw="$1" weekday="$2" address="${3:-wherever}"
|
|
address=$(sed 's/[^a-zA-Z0-9]/_/g' <<< $(sanitize_name "$address") | tr -s '_' '_')
|
|
local dir=$DOSSIER_DESTINATION_MP4
|
|
dir=$dir/$(date -jf "%Y-%m-%dT%H:%M:%S" "$(get_creation_time $raw)" +%Y%m%d_%H%M%S)
|
|
dir=${dir}_${weekday}_${address}
|
|
echo $dir
|
|
}
|
|
export -f mp4_dir
|
|
|
|
write_thumbnail() {
|
|
local raw="$1"
|
|
local thumbnail="$2"
|
|
ffmpeg -ss 00:00:03 -i $raw -vframes 1 $thumbnail 2>/dev/null
|
|
}
|
|
export -f write_thumbnail
|
|
|
|
write_mp4() {
|
|
local src="$1"
|
|
local dst="$2"
|
|
[ -e "$dst" ] || reencode_with_rotation $src $dst
|
|
}
|
|
export -f write_mp4
|
|
|
|
generate_funny_suffix() {
|
|
local file="$1"
|
|
|
|
# Grande liste de suffixes uniques et lisibles
|
|
local funny_names=(
|
|
"pamplemousse" "canard" "yolo" "flan" "tortue" "biscotte" "poney" "baguette"
|
|
"chaussette" "banane" "hippopotame" "tuba" "bretzel" "chocolatine" "carambar"
|
|
"frometon" "krokmou" "gnocchi" "clafoutis" "capybara" "choubidou" "pingouin"
|
|
"maracas" "raclette" "saucisson" "pistache" "chamallow" "boomerang" "pirouette"
|
|
"moustache" "abricot" "falafel" "pouet" "zouzou" "cornichon" "gnouf" "mouette"
|
|
"paprika" "crouton" "galipette" "gratin" "pouliche" "brocoli" "nugget"
|
|
)
|
|
|
|
# Calcul du hash MD5 compatible macOS
|
|
local hash_val
|
|
hash_val=$(md5 -q "$file" 2>/dev/null)
|
|
|
|
# Fallback si le hash échoue (ex: fichier non lisible)
|
|
if [[ -z "$hash_val" ]]; then
|
|
echo "default"
|
|
return
|
|
fi
|
|
|
|
# Extraire les 8 derniers caractères hexadécimaux pour faire un modulo fiable
|
|
local short_hex="${hash_val: -8}"
|
|
|
|
# Convertir en entier et choisir un mot dans la liste
|
|
local index=$(( 0x$short_hex % ${#funny_names[@]} ))
|
|
|
|
echo "${funny_names[$index]}"
|
|
}
|
|
export -f generate_funny_suffix
|
|
|
|
process_raw_file() {
|
|
local raw="$1"
|
|
local dir_suffixe="${2:-}"
|
|
|
|
local ct weekday duration lat lon address
|
|
IFS="|" read -r ct weekday duration lat lon address <<<"$(process_video "$raw")"
|
|
|
|
# récupérer les infos eventuelles dans la BDD
|
|
# si fichier videos existent toujours ingorer, sinon écraser
|
|
# TODO
|
|
|
|
local dir=$(mp4_dir $raw $weekday "$address")
|
|
[ -n "$dir_suffixe" ] && dir=${dir}_${dir_suffixe} || :
|
|
mkdir -p $dir
|
|
|
|
local thumbnail=${dir}/thumbnail.jpg
|
|
$(write_thumbnail $raw $thumbnail)
|
|
|
|
local mp4=${dir}/video.mp4
|
|
$(write_mp4 $raw $mp4)
|
|
|
|
register_video $(basename $raw) "$raw" "$duration" "$mp4" \
|
|
"$mp4" "$thumbnail" "'$ct'" "$weekday" \
|
|
"$lat" "$lon" "$address"
|
|
}
|
|
export -f process_raw_file
|
|
|
|
iphone_video() {
|
|
local raw="$1"
|
|
echo iphone $raw
|
|
process_raw_file $raw
|
|
}
|
|
export -f iphone_video
|
|
screen_video() {
|
|
local raw="$1"
|
|
echo screen $raw
|
|
process_raw_file $raw
|
|
}
|
|
export -f screen_video
|
|
whatsapp_video() {
|
|
local raw="$1"
|
|
echo whatsapp $raw
|
|
local suffixe=$(generate_funny_suffix $raw)
|
|
process_raw_file $raw $suffixe
|
|
}
|
|
export -f whatsapp_video
|
|
ignored_video() {
|
|
local raw="$1"
|
|
echo ignored "$raw"
|
|
local suffixe=$(generate_funny_suffix $raw)
|
|
process_raw_file $raw $suffixe
|
|
}
|
|
export -f ignored_video
|
|
|
|
convert_raws() {
|
|
|
|
if $PROCESS_ALL; then
|
|
|
|
find "$DOSSIER_DESTINATION_RAW" -type f \
|
|
-name "*.mov" \
|
|
-print0 | parallel -0 -j 4 iphone_video
|
|
|
|
find "$DOSSIER_DESTINATION_RAW" -type f \
|
|
-name "screenrecording*.mp4" \
|
|
-print0 | parallel -0 -j 4 screen_video
|
|
|
|
find "$DOSSIER_DESTINATION_RAW" -type f \
|
|
-name '*[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]*.mp4' \
|
|
-print0 | parallel -0 -j 4 whatsapp_video
|
|
|
|
else
|
|
if [ -f "$TEMP_FILE" ]; then
|
|
while IFS= read -r file || [ -n "$file" ]; do
|
|
file=$(echo "$file" | tr -d '\r' | xargs)
|
|
# Ignorer les lignes vides
|
|
if [ -z "$file" ]; then
|
|
continue
|
|
fi
|
|
echo "Dealing with $file"
|
|
local filename=$(basename "$file")
|
|
if [[ "$filename" == *.mov ]]; then
|
|
iphone_video "$file"
|
|
elif [[ "$filename" == screenrecording*.mp4 ]]; then
|
|
screen_video "$file"
|
|
elif [[ "$filename" =~ ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.mp4$ ]]; then
|
|
whatsapp_video "$file"
|
|
else
|
|
echo "$file didn't match any pattern"
|
|
fi
|
|
done < "$TEMP_FILE"
|
|
fi
|
|
fi
|
|
|
|
if [[ -n "$PROCESS_IGNORED_FILES" ]]; then
|
|
set -x
|
|
for f in $(find "$DOSSIER_DESTINATION_RAW" -maxdepth 1 -type f \( -iname "*.mp4" -o -iname "*.mov" \) -print); do
|
|
if [[ -z $(sqlite3 "$DANCE_VIDEOS_DB" "SELECT 1 FROM VIDEOS WHERE RAW_FILE='$f';") ]]; then
|
|
ignored_video "$f"
|
|
fi
|
|
done
|
|
set +x
|
|
fi
|
|
}
|
|
|
|
$PRINT_ERR || exec 2> /tmp/DanceVideos.stderr
|
|
|
|
convert_raws
|
|
|
|
set -x
|
|
if [ 0 -lt $(wc -l $TEMP_FILE | awk '{print $1}') ]; then
|
|
|
|
set +o pipefail
|
|
STREAMLIT_PID="$(ps aux | grep streamlit | grep -v 'grep' | awk '{print $2}')"
|
|
set -o pipefail
|
|
if [ ! -z "$STREAMLIT_PID" ]; then
|
|
kill $STREAMLIT_PID
|
|
fi
|
|
# (cd $SCRIPTS_DIR/..; source .venv/bin/activate; streamlit run app/app.py -- --unlabeled &)
|
|
ROOT=$(realpath $SCRIPTS_DIR/..)
|
|
source $ROOT/.venv/bin/activate
|
|
streamlit run $ROOT/app/app.py -- --unlabeled &
|
|
|
|
fi |