"""Download recordings from the S3 bucket and convert any .webm files to .wav. Skips files that have already been downloaded (and, for .webm sources, already converted to .wav), so re-running the script only fetches what's new. """ import os import shutil import subprocess import sys import boto3 from botocore.config import Config as BotoConfig from pathlib import Path from dotenv import load_dotenv load_dotenv(Path.home() / ".config" / "otree" / ".env") BUCKET = 'ethz-otree-whisper' REGION = 'eu-north-1' OUT_DIR = Path(__file__).parent.parent.parent / 'data' / 'recordings' if not shutil.which('ffmpeg'): print('Error: ffmpeg not found. Install it with: brew install ffmpeg') sys.exit(1) s3 = boto3.client( 's3', aws_access_key_id=os.environ['S3_ACCESS_KEY'], aws_secret_access_key=os.environ['S3_SECRET_KEY'], region_name=REGION, config=BotoConfig(signature_version='s3v4'), ) paginator = s3.get_paginator('list_objects_v2') keys = [obj['Key'] for page in paginator.paginate(Bucket=BUCKET) for obj in page.get('Contents', [])] if not keys: print('Bucket is empty.') sys.exit(0) OUT_DIR.mkdir(exist_ok=True) def local_target(key): """Path a key ends up at locally once fully processed (.webm -> .wav).""" dest = OUT_DIR / key return dest.with_suffix('.wav') if dest.suffix == '.webm' else dest to_download = [k for k in keys if not local_target(k).exists()] skipped = len(keys) - len(to_download) print(f'Found {len(keys)} file(s) in bucket: {skipped} already downloaded, ' f'{len(to_download)} to fetch. Saving to {OUT_DIR}/ ...') converted = 0 for key in to_download: dest = OUT_DIR / key dest.parent.mkdir(parents=True, exist_ok=True) s3.download_file(BUCKET, key, str(dest)) size_kb = dest.stat().st_size / 1024 if dest.suffix == '.webm': wav_dest = dest.with_suffix('.wav') print(f' {key} ({size_kb:.1f} KB) converting...', end=' ', flush=True) result = subprocess.run( ['ffmpeg', '-y', '-i', str(dest), '-ar', '44100', '-ac', '1', '-c:a', 'pcm_s16le', str(wav_dest)], capture_output=True, ) if result.returncode == 0: dest.unlink() wav_kb = wav_dest.stat().st_size / 1024 print(f'OK → {wav_dest.name} ({wav_kb:.1f} KB)') converted += 1 else: print(f'FAILED') print(f' ffmpeg stderr: {result.stderr.decode(errors="replace").strip()}') else: print(f' {key} ({size_kb:.1f} KB)') webm_total = sum(1 for k in to_download if k.endswith('.webm')) wav_total = sum(1 for k in to_download if k.endswith('.wav')) failed = webm_total - converted print(f'\n── Summary ───────────────────────────────') print(f' Files in bucket : {len(keys)}') print(f' Already downloaded : {skipped}') print(f' Newly downloaded : {len(to_download)}') print(f' Already .wav (new) : {wav_total}') print(f' .webm converted : {converted}') print(f' Conversion failed : {failed}') print(f' Saved to : {OUT_DIR}/') print(f'──────────────────────────────────────────')