Skip to main content
The Drive Proxy API enables streaming of course content directly from Google Drive, with support for range requests, video transcoding, and browser compatibility modes.

Stream File from Drive

curl http://localhost:8080/drive/files/1aB2cD3eF4gH5iJ6kL7mN8oP9qR0

Endpoint

GET /drive/files/{fileId}
Streams a file from Google Drive using the service account API.

Path Parameters

fileId
string
required
Google Drive file ID (10+ alphanumeric characters)Must match pattern: [A-Za-z0-9_-]{10,}

Request Headers

Range
string
Request a byte range from the fileFormat: bytes=start-endExamples:
  • bytes=0-1023 - First 1KB
  • bytes=1024- - From byte 1024 to end
  • bytes=-1024 - Last 1KB
Multi-range requests (e.g., bytes=0-100,200-300) are not supported and will return 416 Range Not Satisfiable.

Response Headers

Content-Type
string
MIME type from Google Drive (e.g., video/mp4, application/pdf, image/png)
Content-Length
string
Size of the response in bytes (full file or range)
Content-Range
string
Byte range being returned (only for range requests)Format: bytes start-end/totalExample: bytes 0-1023/5242880
Accept-Ranges
string
Always returns bytes to indicate range request support
Cache-Control
string
For video files: public, max-age=3600For other files: No cache control header
Access-Control-Allow-Origin
string
Set for localhost origins only

Response Status Codes

CodeMeaning
200Full file content returned
206Partial content (range request)
400Invalid file ID format
416Range not satisfiable
502Drive API error
503Drive service not available

Example: Full File Request

Request
GET /drive/files/1aB2cD3eF4gH5iJ6kL7mN8oP9qR0 HTTP/1.1
Host: localhost:8080
Response
HTTP/1.1 200 OK
Content-Type: video/mp4
Content-Length: 52428800
Accept-Ranges: bytes
Cache-Control: public, max-age=3600

[binary video data]

Example: Range Request

Request
GET /drive/files/1aB2cD3eF4gH5iJ6kL7mN8oP9qR0 HTTP/1.1
Host: localhost:8080
Range: bytes=0-1048575
Response
HTTP/1.1 206 Partial Content
Content-Type: video/mp4
Content-Range: bytes 0-1048575/52428800
Content-Length: 1048576
Accept-Ranges: bytes
Cache-Control: public, max-age=3600

[first 1MB of video data]

Performance Metrics

The server logs streaming metrics for requests taking >0.5 seconds:
[STREAM] 1aB2cD3eF4gH5iJ6kL7mN8oP9qR0 | Range: bytes=0-1048575 | 50.00 MB in 2.45s (20.41 MB/s)
Chunk size is optimized at 1MB to reduce overhead and improve A/V sync during video playback.

Stream Compatible Video

curl http://localhost:8080/api/video-compatible/1aB2cD3eF4gH5iJ6kL7mN8oP9qR0

Endpoint

GET /api/video-compatible/{fileId}
Streams a video file with ffmpeg transcoding to ensure browser compatibility. This endpoint:
  1. Downloads the file from Drive
  2. Processes it through ffmpeg
  3. Outputs browser-compatible MP4 with fragmented structure
This endpoint requires ffmpeg to be installed and available.

Path Parameters

fileId
string
required
Google Drive file ID for a video file

ffmpeg Processing

The server applies these ffmpeg settings: Default Mode (Copy)
  • Video codec: Copy original stream (no re-encoding)
  • Audio codec: AAC, 48kHz, resampled
  • Container: Fragmented MP4 for progressive streaming
Force Re-encode Mode Set PLATZI_COMPAT_FORCE_REENCODE=1 to force video re-encoding:
  • Video codec: H.264 (libx264), veryfast preset, yuv420p
  • Audio codec: AAC, 48kHz, resampled
  • Container: Fragmented MP4
export PLATZI_COMPAT_FORCE_REENCODE=1

Response Headers

Content-Type
string
Always video/mp4
Accept-Ranges
string
Always none (range requests not supported on transcoded stream)
Cache-Control
string
no-store, max-age=0 (transcoded content not cached)

Response Status Codes

CodeMeaning
200Streaming in progress
400Invalid file ID
502ffmpeg processing failed
503ffmpeg or Drive service not available

Example Response

Request
GET /api/video-compatible/1aB2cD3eF4gH5iJ6kL7mN8oP9qR0 HTTP/1.1
Host: localhost:8080
Response
HTTP/1.1 200 OK
Content-Type: video/mp4
Cache-Control: no-store, max-age=0
Accept-Ranges: none

[fragmented MP4 stream]

ffmpeg Command

The server constructs this ffmpeg command:
ffmpeg -hide_banner -loglevel error \
  -fflags +genpts+discardcorrupt \
  -avoid_negative_ts make_zero \
  -max_interleave_delta 0 \
  -i http://127.0.0.1:8080/drive/files/{fileId} \
  -map 0:v:0 -map 0:a? \
  -c:v copy \
  -c:a aac -ar 48000 \
  -af aresample=async=1:first_pts=0 \
  -movflags +frag_keyframe+empty_moov+default_base_moof \
  -muxdelay 0 -muxpreload 0 \
  -f mp4 -

Performance Metrics

The server logs compatibility stream statistics:
[COMPAT] 1aB2cD3eF4gH5iJ6kL7mN8oP9qR0 | 150.00 MB in 12.34s (12.16 MB/s)

Compatibility Stream Stats

Get real-time statistics via /api/health:
{
  "status": "ok",
  "compatStream": {
    "totalRequests": 45,
    "successfulStreams": 42,
    "failedStreams": 3,
    "totalBytes": 6442450944,
    "lastFileId": "1aB2cD3eF4gH5iJ6kL7mN8oP9qR0",
    "lastError": null,
    "lastDurationSec": 12.34,
    "lastSpeedMBps": 12.16,
    "lastMode": "copy",
    "lastAt": "2026-03-07T10:30:00Z"
  }
}
Use /drive/files/{fileId} for direct streaming when possible. Only use /api/video-compatible/{fileId} if you encounter playback issues.

MIME Type Detection

MIME types are determined by Google Drive’s file metadata:

Video Files

  • video/mp4 - MP4 video
  • video/quicktime - MOV video
  • video/x-matroska - MKV video
  • video/webm - WebM video

Document Files

  • application/pdf - PDF documents
  • application/vnd.google-apps.presentation - Google Slides
  • application/vnd.google-apps.document - Google Docs

Image Files

  • image/png - PNG images
  • image/jpeg - JPEG images
  • image/webp - WebP images

Default

  • application/octet-stream - Unknown file types

Range Request Support

Video Seeking

Range requests enable efficient video seeking in HTML5 video players:
const video = document.querySelector('video');
const fileId = '1aB2cD3eF4gH5iJ6kL7mN8oP9qR0';

video.src = `http://localhost:8080/drive/files/${fileId}`;

// Browser automatically uses range requests for seeking
video.currentTime = 120; // Jump to 2 minutes

Progressive Download

Range requests allow downloading large files in chunks:
async function downloadFileInChunks(fileId, chunkSize = 1024 * 1024) {
  let offset = 0;
  const chunks = [];
  
  while (true) {
    const response = await fetch(
      `http://localhost:8080/drive/files/${fileId}`,
      {
        headers: {
          'Range': `bytes=${offset}-${offset + chunkSize - 1}`
        }
      }
    );
    
    if (response.status === 416) break; // No more data
    
    const chunk = await response.arrayBuffer();
    chunks.push(chunk);
    
    if (response.status === 200) break; // Got full file
    
    offset += chunkSize;
  }
  
  return new Blob(chunks);
}

Validation

Range header validation: Valid formats:
  • bytes=0-1023
  • bytes=1024-
  • bytes=-1024
Invalid formats:
  • bytes=0-100,200-300 (multi-range)
  • items=0-100 (wrong unit)
  • bytes=abc-def (non-numeric)

Error Handling

Invalid File ID

Request
curl http://localhost:8080/drive/files/invalid
Response
HTTP/1.1 400 Bad Request

Invalid file ID

Drive Service Unavailable

Request
curl http://localhost:8080/drive/files/1aB2cD3eF4gH5iJ6kL7mN8oP9qR0
Response
HTTP/1.1 503 Service Unavailable

Drive service not available. Check service_account.json, GOOGLE_SERVICE_ACCOUNT_FILE or GOOGLE_SERVICE_ACCOUNT_JSON.

Local File Reference (Deprecated)

Request
curl http://localhost:8080/drive/files/local:video.mp4
Response
HTTP/1.1 400 Bad Request

Local file refs are disabled in Drive mode. Rebuild cache with rebuild_cache_drive.py

Range Not Satisfiable

Request
curl -H "Range: bytes=0-100,200-300" \
  http://localhost:8080/drive/files/1aB2cD3eF4gH5iJ6kL7mN8oP9qR0
Response
HTTP/1.1 416 Range Not Satisfiable

Invalid range header

ffmpeg Not Available

Request
curl http://localhost:8080/api/video-compatible/1aB2cD3eF4gH5iJ6kL7mN8oP9qR0
Response
HTTP/1.1 503 Service Unavailable

ffmpeg_not_available

Configuration

Environment Variables

GOOGLE_SERVICE_ACCOUNT_FILE
string
Path to service account JSON file
GOOGLE_SERVICE_ACCOUNT_JSON
string
Service account JSON as string (alternative to file)
FFMPEG_PATH
string
Path to ffmpeg executable (auto-detected if not set)
PLATZI_COMPAT_FORCE_REENCODE
string
Set to 1 to force video re-encoding (default: 0)

ffmpeg Detection

The server searches for ffmpeg in this order:
  1. FFMPEG_PATH environment variable
  2. ffmpeg in system PATH
  3. Windows: C:\Program Files\ffmpeg\bin\ffmpeg.exe
  4. Windows: C:\ffmpeg\bin\ffmpeg.exe
Check ffmpeg availability:
curl http://localhost:8080/api/health | jq .ffmpeg
{
  "available": true,
  "path": "/usr/bin/ffmpeg"
}

Best Practices

For optimal video playback:
  1. Use /drive/files/{fileId} for direct streaming
  2. Only use /api/video-compatible/{fileId} for problematic files
  3. Enable browser caching for better performance
  4. Use range requests for large files
  5. Monitor stream metrics via /api/health

Caching Strategy

The server sets cache headers for video files:
Cache-Control: public, max-age=3600
Browsers cache video segments for 1 hour, reducing Drive API calls.

Bandwidth Optimization

  • Use range requests to download only needed portions
  • Videos are streamed in 1MB chunks for optimal A/V sync
  • Monitor streaming speed in server logs

Next Steps

Course APIs

Get file IDs from course catalog

Progress API

Save video playback positions

Configuration

Configure Drive service account

Build docs developers (and LLMs) love