mirror of
https://github.com/Aider-AI/aider.git
synced 2025-05-20 12:24:59 +00:00
feat: Add metadata tracking and TTS fallback improvements
This commit is contained in:
parent
aee52c01a3
commit
8404165db3
2 changed files with 99 additions and 12 deletions
|
@ -180,6 +180,20 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
}, 3000);
|
}, 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to use browser's TTS as fallback
|
||||||
|
function useBrowserTTS(text) {
|
||||||
|
if ('speechSynthesis' in window) {
|
||||||
|
console.log('Using browser TTS fallback');
|
||||||
|
const utterance = new SpeechSynthesisUtterance(text);
|
||||||
|
utterance.rate = 1.0;
|
||||||
|
utterance.pitch = 1.0;
|
||||||
|
utterance.volume = 1.0;
|
||||||
|
window.speechSynthesis.speak(utterance);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Function to play pre-generated TTS audio files
|
// Function to play pre-generated TTS audio files
|
||||||
function speakText(text, timeInSeconds) {
|
function speakText(text, timeInSeconds) {
|
||||||
// Format time for filename (MM-SS)
|
// Format time for filename (MM-SS)
|
||||||
|
@ -200,19 +214,14 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
// Error handling with fallback to browser TTS
|
// Error handling with fallback to browser TTS
|
||||||
audio.onerror = () => {
|
audio.onerror = () => {
|
||||||
console.warn(`Failed to load audio: ${audioPath}`);
|
console.warn(`Failed to load audio: ${audioPath}`);
|
||||||
// Fallback to browser TTS
|
useBrowserTTS(text);
|
||||||
if ('speechSynthesis' in window) {
|
|
||||||
const utterance = new SpeechSynthesisUtterance(text);
|
|
||||||
utterance.rate = 1.0;
|
|
||||||
utterance.pitch = 1.0;
|
|
||||||
utterance.volume = 1.0;
|
|
||||||
window.speechSynthesis.speak(utterance);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Play the audio
|
// Play the audio
|
||||||
audio.play().catch(e => {
|
audio.play().catch(e => {
|
||||||
console.warn(`Error playing audio: ${e.message}`);
|
console.warn(`Error playing audio: ${e.message}`);
|
||||||
|
// Also fall back to browser TTS if play() fails
|
||||||
|
useBrowserTTS(text);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ Usage: python scripts/recording_audio.py path/to/recording.md
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
@ -80,6 +81,32 @@ def generate_audio_openai(text, output_file, voice=VOICE):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def load_metadata(output_dir):
|
||||||
|
"""Load the audio metadata JSON file if it exists."""
|
||||||
|
metadata_file = os.path.join(output_dir, "metadata.json")
|
||||||
|
|
||||||
|
if os.path.exists(metadata_file):
|
||||||
|
try:
|
||||||
|
with open(metadata_file, "r") as f:
|
||||||
|
return json.load(f)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
print(f"Warning: Could not parse metadata file {metadata_file}, will recreate it")
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def save_metadata(output_dir, metadata):
|
||||||
|
"""Save the audio metadata to JSON file."""
|
||||||
|
metadata_file = os.path.join(output_dir, "metadata.json")
|
||||||
|
|
||||||
|
with open(metadata_file, "w") as f:
|
||||||
|
json.dump(metadata, f, indent=2)
|
||||||
|
|
||||||
|
def get_timestamp_key(time_sec):
|
||||||
|
"""Generate a consistent timestamp key format for metadata."""
|
||||||
|
minutes = time_sec // 60
|
||||||
|
seconds = time_sec % 60
|
||||||
|
return f"{minutes:02d}-{seconds:02d}"
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="Generate TTS audio for recording commentary.")
|
parser = argparse.ArgumentParser(description="Generate TTS audio for recording commentary.")
|
||||||
parser.add_argument("markdown_file", help="Path to the recording markdown file")
|
parser.add_argument("markdown_file", help="Path to the recording markdown file")
|
||||||
|
@ -90,6 +117,9 @@ def main():
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--dry-run", action="store_true", help="Print what would be done without generating audio"
|
"--dry-run", action="store_true", help="Print what would be done without generating audio"
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--force", action="store_true", help="Force regeneration of all audio files"
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
@ -113,15 +143,52 @@ def main():
|
||||||
|
|
||||||
print(f"Found {len(markers)} commentary markers")
|
print(f"Found {len(markers)} commentary markers")
|
||||||
|
|
||||||
|
# Load existing metadata
|
||||||
|
metadata = load_metadata(output_dir)
|
||||||
|
|
||||||
|
# Create a dictionary of current markers for easier comparison
|
||||||
|
current_markers = {}
|
||||||
|
for time_sec, message in markers:
|
||||||
|
timestamp_key = get_timestamp_key(time_sec)
|
||||||
|
current_markers[timestamp_key] = message
|
||||||
|
|
||||||
|
# Track files that need to be deleted (no longer in the markdown)
|
||||||
|
files_to_delete = []
|
||||||
|
for timestamp_key in metadata:
|
||||||
|
if timestamp_key not in current_markers:
|
||||||
|
files_to_delete.append(f"{timestamp_key}.mp3")
|
||||||
|
|
||||||
|
# Delete files that are no longer needed
|
||||||
|
if files_to_delete and not args.dry_run:
|
||||||
|
for filename in files_to_delete:
|
||||||
|
file_path = os.path.join(output_dir, filename)
|
||||||
|
if os.path.exists(file_path):
|
||||||
|
print(f"Removing obsolete file: {filename}")
|
||||||
|
os.remove(file_path)
|
||||||
|
elif files_to_delete:
|
||||||
|
print(f"Would remove {len(files_to_delete)} obsolete files: {', '.join(files_to_delete)}")
|
||||||
|
|
||||||
# Generate audio for each marker
|
# Generate audio for each marker
|
||||||
for time_sec, message in markers:
|
for time_sec, message in markers:
|
||||||
|
timestamp_key = get_timestamp_key(time_sec)
|
||||||
|
filename = f"{timestamp_key}.mp3"
|
||||||
|
output_file = os.path.join(output_dir, filename)
|
||||||
|
|
||||||
|
# Check if we need to generate this file
|
||||||
|
needs_update = args.force or (
|
||||||
|
timestamp_key not in metadata or
|
||||||
|
metadata[timestamp_key] != message
|
||||||
|
)
|
||||||
|
|
||||||
minutes = time_sec // 60
|
minutes = time_sec // 60
|
||||||
seconds = time_sec % 60
|
seconds = time_sec % 60
|
||||||
timestamp = f"{minutes:02d}-{seconds:02d}"
|
|
||||||
filename = f"{timestamp}.mp3"
|
|
||||||
output_file = os.path.join(output_dir, filename)
|
|
||||||
|
|
||||||
print(f"Marker at {minutes}:{seconds:02d} - {message}")
|
print(f"Marker at {minutes}:{seconds:02d} - {message}")
|
||||||
|
|
||||||
|
if not needs_update:
|
||||||
|
print(f" ✓ Audio file already exists with correct content")
|
||||||
|
continue
|
||||||
|
|
||||||
if args.dry_run:
|
if args.dry_run:
|
||||||
print(f" Would generate: {output_file}")
|
print(f" Would generate: {output_file}")
|
||||||
else:
|
else:
|
||||||
|
@ -129,8 +196,19 @@ def main():
|
||||||
success = generate_audio_openai(message, output_file, voice=selected_voice)
|
success = generate_audio_openai(message, output_file, voice=selected_voice)
|
||||||
if success:
|
if success:
|
||||||
print(f" ✓ Generated audio file")
|
print(f" ✓ Generated audio file")
|
||||||
|
# Update metadata with the new message
|
||||||
|
metadata[timestamp_key] = message
|
||||||
else:
|
else:
|
||||||
print(f" ✗ Failed to generate audio")
|
print(f" ✗ Failed to generate audio")
|
||||||
|
|
||||||
|
# Save updated metadata
|
||||||
|
if not args.dry_run:
|
||||||
|
# Remove entries for deleted files
|
||||||
|
for timestamp_key in list(metadata.keys()):
|
||||||
|
if timestamp_key not in current_markers:
|
||||||
|
del metadata[timestamp_key]
|
||||||
|
|
||||||
|
save_metadata(output_dir, metadata)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue