as

Settings
Sign out
Notifications
Alexa
Amazon Appstore
Ring
AWS
Documentation
Support
Contact Us
My Cases
Ring

Media Clips (MP4 Download)

Ring provides an endpoint to download historical video content as MP4 files. This complements live video streaming by enabling access to recorded footage for analysis, storage, or playback.

Overview

  • MP4 format: Standard video format for broad compatibility
  • Configurable quality: Adjustable resolution, frame rate, and codec
  • Audio support: Optional audio inclusion
  • Flexible duration: Up to 15 minutes per request
  • Partial content support: Handles cases where full requested duration isn't available

API Endpoint

Unlike other Ring APIs, the media download endpoint does not follow JSON:API specification and uses standard HTTP constructs with MIME types.

POST https://api.amazonvision.com/v1/devices/{device_id}/media/video/download
Authorization: Bearer <access_token>
Content-Type: application/json

Request Parameters

Required Parameters

Parameter Type Description Constraints
timestamp integer Start time in epoch milliseconds ≤ now()
duration integer Video length in milliseconds ≤ 900,000 (15 minutes)

Optional Parameters

Video Options

| Parameter | Type | Description | Default | |———–|——|————-|———| | video_options.codec | string | Video codec ("avc" or "hevc") | Device default | | video_options.frame_rate | integer | Frames per second | Device default (≤ 25) | | video_options.resolution.width | integer | Video width in pixels | Device default (≤ 1920) | | video_options.resolution.height | integer | Video height in pixels | Device default (≤ 1080) |

Audio Options

| Parameter | Type | Description | Default | |———–|——|————-|———| | audio_options.audio_enabled | boolean | Include audio in video file | false |

Request Example

{
  "timestamp": 1699457230000,
  "duration": 5000,
  "video_options": {
    "codec": "avc",
    "frame_rate": 5,
    "resolution": {
      "width": 1080,
      "height": 720
    }
  },
  "audio_options": {
    "audio_enabled": true
  }
}

Response Handling

Response Headers

  • Content-Type: MIME type for the media content
  • X-Media-Timestamp: Actual start timestamp of the provided video
  • X-Media-Length: Actual duration in milliseconds (for partial responses)

HTTP Status Codes

200 OK - Full Content

HTTP/1.1 200 OK
Content-Type: video/mp4
X-Media-Timestamp: 1699457230000
Content-Length: 2048576

[Binary MP4 data]

206 Partial Content

HTTP/1.1 206 Partial Content
Content-Type: video/mp4
X-Media-Timestamp: 1699457235000
X-Media-Length: 3000

[Binary MP4 data]

Partial content occurs when:

  • Requesting video beyond current time
  • Requesting video from before recording started
  • Device was offline during part of the requested timeframe

301 Redirect

Redirects may occur when video processing is handled by different servers. Clients must follow redirects.

Implementation Example

import requests
from datetime import datetime

def download_video_clip(device_id, access_token, start_time, duration_ms):
    url = f"https://api.amazonvision.com/v1/devices/{device_id}/media/video/download"

    payload = {
        "timestamp": int(start_time.timestamp() * 1000),
        "duration": duration_ms
    }

    headers = {
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json"
    }

    response = requests.post(url, json=payload, headers=headers, allow_redirects=True)

    if response.status_code == 200:
        return {"status": "complete", "data": response.content}
    elif response.status_code == 206:
        return {
            "status": "partial",
            "data": response.content,
            "actual_duration": response.headers.get("X-Media-Length")
        }
    else:
        response.raise_for_status()

Since the download endpoint only retrieves existing footage, you must ensure the camera is recording before requesting a clip:

  1. Start a live video session (which triggers recording on supported devices)
  2. Wait for the desired recording duration
  3. Stop the session
  4. Download the clip using the time window from the session
import time
from datetime import datetime

def record_and_download(device_id, access_token, duration_seconds=10):
    # Step 1: Start a live video session (triggers recording)
    session = start_live_session(device_id, access_token)
    record_start = datetime.utcnow()

    # Step 2: Wait for the desired recording duration
    time.sleep(duration_seconds)

    # Step 3: Stop the live video session
    stop_live_session(device_id, session["session_id"], access_token)

    # Step 4: Small delay to allow media processing
    time.sleep(2)

    # Step 5: Download the recorded clip
    clip = download_video_clip(
        device_id=device_id,
        access_token=access_token,
        start_time=record_start,
        duration_ms=duration_seconds * 1000
    )
    return clip

Common Mistakes

1. Assuming Download Triggers Recording

The most common mistake. This endpoint is read-only — it retrieves footage that was already recorded.

Wrong:

clip = download_video_clip(device_id, token, some_timestamp, 5000)

Correct:

session = start_live_session(device_id, token)
time.sleep(10)
stop_live_session(device_id, session["session_id"], token)
time.sleep(2)
clip = download_video_clip(device_id, token, session_start_time, 10000)

2. Requesting Clips from Periods with No Recording

If you request a clip for a time range when the device was idle, there is no stored footage. Use webhook notifications to track motion_detected events to confirm when the camera was recording.

Best Practices

  1. Reasonable durations: Request appropriate clip lengths
  2. Quality selection: Choose resolution and frame rate based on use case
  3. Audio consideration: Only include audio when needed to reduce file size
  4. Handle partial content: Process 206 responses appropriately
  5. Follow redirects: Always allow redirect following
  6. Retry logic: Implement exponential backoff for transient failures

Next: Error Handling →