| Scenario | Why a downloader is needed | |----------|----------------------------| | | Capture footage for forensic review, machine‑learning pipelines, or compliance audits. | | Edge‑to‑cloud backup | Pull archived video from a stream that was only temporarily stored in the cloud. | | Custom playback | Bypass the standard KVS Player SDK (WebRTC or HLS) to embed video in non‑browser environments (e.g., desktop apps, embedded devices). | | Integration with third‑party tools | Feed raw fragments into FFmpeg, GStreamer, or video‑analytics frameworks. |
// 3️⃣ Pipe the payload directly to a file (or to FFmpeg for re‑muxing) const outFile = createWriteStream("downloaded-stream.mp4"); await pipeline(resp.Payload, outFile);
// 2️⃣ Execute GetMedia – the response body is a readable stream of fMP4 fragments const resp = await mediaClient.send(getMediaCmd); if (!resp.Payload) throw new Error("No payload returned");
// 1️⃣ Get data endpoint for GET_MEDIA kvClient := kv.NewFromConfig(cfg) epOut, err := kvClient.GetDataEndpoint(ctx, &kv.GetDataEndpointInput APIName: kv.APINameGetMedia, StreamARN: aws.String(streamARN), ) if err != nil panic(err) mediaCfg := cfg.Copy() mediaCfg.EndpointResolver = aws.EndpointResolverFromURL(*epOut.DataEndpoint)
def sign_request(url, method="GET"): # boto3's botocore can sign arbitrary requests from botocore.auth import SigV4Auth from botocore.awsrequest import AWSRequest from botocore.credentials import ReadOnlyCredentials
async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers) as resp: resp.raise_for_status() with open(OUTPUT, "wb") as f: async for chunk in resp.content.iter_chunked(1024 * 256): f.write(chunk) # optional: print progress print(f"\rf.tell() // 1024 KiB received", end="") print("\n✅ Done →", OUTPUT)
async def download(): endpoint = await get_data_endpoint() url = f"endpoint/getMedia?StreamARN=STREAM_ARN&StartSelector.Type=NOW" headers = sign_request(url)