Review
Late-ack guest proxy for 4K ceremony masters
Afterglow Films ships guest-share proxies the morning after a wedding. Enable acks_late so a worker crash mid-encode redelivers instead of silently dropping the job, and implement build_guest_proxy to pull the 4K ceremony master from S3, hand it to moviepy, and upload a 720p scrub reel for the couple's portal.
CeleryTier 5celeryacks-lateoomvideo
Click a line to flag it, pick one or more labels, then submit. If the change looks correct, approve it.
afterglow/workers/ceremony_proxy.py+16-1
| 22 | 22 | from pathlib import Path | |
| 23 | 23 | ||
| 24 | 24 | from celery import shared_task | |
| 25 | 25 | from moviepy.editor import VideoFileClip | |
| 26 | 26 | ||
| 27 | 27 | from afterglow.media.s3 import s3_client | |
| 28 | 28 | from afterglow.models import CeremonyAsset | |
| 29 | 29 | ||
| 30 | - | @shared_task(name="afterglow.build_guest_proxy") | |
| 30 | + | # Only ack after the proxy lands — crash mid-encode must redeliver. | |
| 31 | + | @shared_task(name="afterglow.build_guest_proxy", acks_late=True) | |
| 32 | + | def build_guest_proxy(asset_id: str) -> dict: | |
| 33 | + | asset = CeremonyAsset.objects.get(pk=asset_id) | |
| 34 | + | # Full master into memory so moviepy can open a stable local path. | |
| 35 | + | obj = s3_client.get_object(Bucket=asset.bucket, Key=asset.master_key) | |
| 36 | + | raw = obj["Body"].read() | |
| 37 | + | local = Path(f"/tmp/ceremony-{asset_id}.mp4") | |
| 38 | + | local.write_bytes(raw) | |
| 39 | + | clip = VideoFileClip(str(local)) | |
| 40 | + | proxy = clip.resize(height=720) | |
| 41 | + | out = Path(f"/tmp/proxy-{asset_id}.mp4") | |
| 42 | + | proxy.write_videofile(str(out), codec="libx264", audio_codec="aac") | |
| 43 | + | s3_client.upload_file(str(out), asset.bucket, asset.proxy_key) | |
| 44 | + | asset.mark_proxy_ready() | |
| 45 | + | return {"asset_id": asset_id, "proxy_key": asset.proxy_key} |