122 lines
4.0 KiB
Bash
122 lines
4.0 KiB
Bash
#!/bin/bash
|
|
# class-watcher.sh — Watches /mnt/data/class-recordings for new .wav files
|
|
# and POSTs them to the n8n class/upload webhook.
|
|
# Saves the transcript + notes response as a .md file alongside the recording.
|
|
#
|
|
# Install:
|
|
# 1. Copy to PD: scp class-watcher.sh truenas_admin@10.5.1.6:/tmp/class-watcher.sh
|
|
# 2. sudo mv /tmp/class-watcher.sh /mnt/data/class-watcher.sh
|
|
# 3. sudo chmod +x /mnt/data/class-watcher.sh
|
|
# 4. sudo crontab -e
|
|
# * * * * * /mnt/data/class-watcher.sh >> /var/log/class-watcher.log 2>&1
|
|
#
|
|
# Folder structure after processing:
|
|
# /mnt/data/class-recordings/
|
|
# └── CS101-Java/
|
|
# ├── new-lecture.wav ← waiting to be processed
|
|
# └── done/
|
|
# ├── lecture-01-intro.wav ← already processed
|
|
# └── lecture-01-intro.md ← transcript + notes
|
|
|
|
WATCH_DIR="/mnt/data/class-recordings"
|
|
WEBHOOK_URL="http://10.5.1.6:5678/webhook/class/upload"
|
|
|
|
# Find all .wav files directly inside class subfolders (not in done/)
|
|
find "$WATCH_DIR" -mindepth 2 -maxdepth 2 -name '*.wav' -type f | while read -r filepath; do
|
|
# Skip files in 'done' directories
|
|
if echo "$filepath" | grep -q '/done/'; then
|
|
continue
|
|
fi
|
|
|
|
# Extract class name from parent folder
|
|
class_dir=$(dirname "$filepath")
|
|
class_name=$(basename "$class_dir")
|
|
file_name=$(basename "$filepath")
|
|
lecture_title="${file_name%.wav}"
|
|
|
|
echo "[$(date)] Processing: $filepath (class: $class_name)"
|
|
|
|
# Create done folder
|
|
mkdir -p "$class_dir/done"
|
|
|
|
# POST the file to n8n webhook and capture the response
|
|
response=$(curl -s -X POST "$WEBHOOK_URL" \
|
|
-H "X-Class-Name: $class_name" \
|
|
-H "X-Lecture-Title: $lecture_title" \
|
|
-F "data=@$filepath" \
|
|
-F "class_name=$class_name" \
|
|
-F "lecture_title=$lecture_title" \
|
|
-F "filename=$file_name" \
|
|
-w "\n%{http_code}" 2>/dev/null)
|
|
|
|
http_code=$(echo "$response" | tail -1)
|
|
body=$(echo "$response" | sed '$d')
|
|
|
|
echo "[$(date)] HTTP $http_code"
|
|
|
|
# Save the transcript + notes as markdown
|
|
md_file="$class_dir/done/${lecture_title}.md"
|
|
|
|
# Try to parse JSON response and format as markdown
|
|
if command -v python3 &>/dev/null; then
|
|
echo "$body" | python3 -c "
|
|
import json, sys
|
|
try:
|
|
data = json.load(sys.stdin)
|
|
# Handle array response from n8n
|
|
if isinstance(data, list):
|
|
data = data[0] if data else {}
|
|
cn = data.get('className', '$class_name')
|
|
lt = data.get('lectureTitle', '$lecture_title')
|
|
dm = data.get('durationMinutes', '?')
|
|
notes = data.get('notes', {})
|
|
summary = notes.get('summary', 'No summary available')
|
|
concepts = notes.get('key_concepts', [])
|
|
defs = notes.get('definitions', [])
|
|
assignments = notes.get('assignments', [])
|
|
transcript = data.get('timestampedText', data.get('fullText', 'No transcript'))
|
|
|
|
print(f'# {cn} — {lt}')
|
|
print(f'**Duration:** {dm} minutes')
|
|
print()
|
|
print('## Summary')
|
|
print(summary)
|
|
print()
|
|
if concepts:
|
|
print('## Key Concepts')
|
|
for c in concepts:
|
|
print(f'- {c}')
|
|
print()
|
|
if defs:
|
|
print('## Definitions')
|
|
for d in defs:
|
|
if isinstance(d, dict):
|
|
print(f'- **{d.get(\"term\", \"\")}**: {d.get(\"definition\", \"\")}')
|
|
else:
|
|
print(f'- {d}')
|
|
print()
|
|
if assignments:
|
|
print('## Assignments')
|
|
for a in assignments:
|
|
print(f'- {a}')
|
|
print()
|
|
print('## Full Transcript')
|
|
print(transcript)
|
|
except Exception as e:
|
|
print(f'# {\"$class_name\"} — {\"$lecture_title\"}')
|
|
print()
|
|
print('## Raw Response')
|
|
print(sys.stdin.read() if not data else json.dumps(data, indent=2))
|
|
" > "$md_file" 2>/dev/null
|
|
else
|
|
# Fallback: save raw JSON
|
|
echo "$body" > "$md_file"
|
|
fi
|
|
|
|
echo "[$(date)] Saved notes to: $md_file"
|
|
|
|
# Move wav to done folder
|
|
mv "$filepath" "$class_dir/done/$file_name"
|
|
echo "[$(date)] Moved to: $class_dir/done/$file_name"
|
|
done
|