Uploading With a Pre-Signed URL
When This Option Is Ideal
You’ve got a video locally. Maybe it’s on your server, maybe it’s on your user’s phone.
You want to make this video playable for everyone else.
Follow this guide. We’ll show you how to get that video ready to be played back for anyone.
The Two-Step Process
This workflow has two steps:
- Video Config. Tell Hesedvid things like the video quality and resolutions you want available. You’ll get a pre-signed URL back.
- Video Upload. You’ll get a pre-signed URL from step one. Upload this video to the pre-signed URL.
Step 1: Submit Video Config
POST https://api.hesedvid.com/v1/{orgID}/environments/{envID}/videos/upload-url
Required Parameters
| Field | Type | Description |
|---|---|---|
fileName | string | The name of the file including the file extension |
videoQuality | string | Quality preset: standard, high, ultra |
allowPublicAccess | boolean | Whether video can be accessed without authentication |
To decide on which video quality you might want to use, click here.
Caution
TODO: We need a comparison page
Optional Parameters
| Field | Type | Default | Description |
|---|---|---|---|
videoName | string | - | Display name for the video. Useful for finding the video in the dashboard or via API. |
maxEdgeLength | integer | (auto-detected) | Maximum resolution: 480, 720, 1080, 1440, 2160 |
maxFrameRate | integer | (auto-detected) | Maximum frame rate (fps) |
EncodingMode | string | fast | Either fast or slow. Use slow for better quality and slightly faster loading speed. |
audioCodec | string | aac | Audio codec: aac, mp3, ac3, eac3 |
To see the quality difference of the fast or slow encoding mode, click here.
Caution
TODO: We need a comparison page for encoding mode too.
Response body
{ "body": { "videoID": "pubvid_XXX", "signedURL": "https://storage.googleapis.com/hesedvid-uploads/org_123/env_prod/videos/uuid-123.mp4?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=...", "expiresAt": 1640995200 }}| Field | Type | Description |
|---|---|---|
signedURL | string | Pre-signed URL for direct upload (valid for 1 hour) |
expiresAt | integer | Unix timestamp when the upload URL expires |
Step 2: Upload To Pre-Signed URL
Open your video file and make a “PUT” request to the signedURL you got from step 1.
file, _ := os.Open(filePath)defer file.Close()putReq, _ := http.NewRequest("PUT", `<signedURL>`, file)client.Do(putReq)Code Examples
const ORGID = "org_XXX";const ENVID = "ENV_XXX";const APIKEY = "key_XXX";
async function uploadVideo( filePath: string, fileName: string): Promise<string> { // Step 1: Submit the video config to get upload URL const uploadResponse = await fetch( `https://api.hesedvid.com/v1/api/${ORGID}/environments/${ENVID}/videos/upload-url`, { method: "POST", headers: { "X-Api-Key": APIKEY, "Content-Type": "application/json" }, body: JSON.stringify({ fileName: fileName, videoQuality: "high", allowPublicAccess: true }) } );
const { body: uploadData } = await uploadResponse.json();
// Step 2: Upload the video to the pre-signed URL const fileBlob = await fetch(filePath).then(r => r.blob()); await fetch(uploadData.uploadUrl, { method: "PUT", body: fileBlob });
return uploadData.videoID;}import requests
ORGID = "org_XXX"ENVID = "ENV_XXX"APIKEY = "key_XXX"
def upload_video(file_path: str, file_name: str) -> str: # Step 1: Submit the video config to get upload URL upload_response = requests.post( f'https://api.hesedvid.com/v1/api/{ORGID}/environments/{ENVID}/videos/upload-url', headers={ 'X-Api-Key': APIKEY, 'Content-Type': 'application/json' }, json={ 'fileName': file_name, 'videoQuality': 'high', 'allowPublicAccess': True } )
upload_data = upload_response.json()['body']
# Step 2: Upload the video to the pre-signed URL with open(file_path, 'rb') as f: requests.put(upload_data['uploadUrl'], data=f)
return upload_data['videoID']package main
import ( "bytes" "encoding/json" "fmt" "net/http" "os")
const ( ORGID = "org_XXX" ENVID = "ENV_XXX" APIKEY = "key_XXX")
type UploadURLRequest struct { FileName string `json:"fileName"` VideoQuality string `json:"videoQuality"` AllowPublicAccess bool `json:"allowPublicAccess"`}
type UploadURLResponse struct { Body struct { UploadURL string `json:"uploadUrl"` VideoID string `json:"videoID"` } `json:"body"`}
func uploadVideo(filePath, fileName string) (string, error) { // Step 1: Submit the video config to get upload URL reqBody, _ := json.Marshal(UploadURLRequest{ FileName: fileName, VideoQuality: "high", AllowPublicAccess: true, })
req, _ := http.NewRequest("POST", fmt.Sprintf("https://api.hesedvid.com/v1/api/%s/environments/%s/videos/upload-url", ORGID, ENVID), bytes.NewBuffer(reqBody)) req.Header.Set("X-Api-Key", APIKEY) req.Header.Set("Content-Type", "application/json")
client := &http.Client{} resp, err := client.Do(req) if err != nil { return "", err } defer resp.Body.Close()
var uploadResp UploadURLResponse json.NewDecoder(resp.Body).Decode(&uploadResp)
// Step 2: Upload the video to the pre-signed URL file, _ := os.Open(filePath) defer file.Close()
putReq, _ := http.NewRequest("PUT", uploadResp.Body.UploadURL, file) client.Do(putReq)
return uploadResp.Body.VideoID, nil}const ORGID = "org_XXX";const ENVID = "ENV_XXX";const APIKEY = "key_XXX";
interface UploadVideoOptions { // Required fileName: string; videoQuality: "standard" | "high" | "ultra"; allowPublicAccess: boolean;
// Optional videoName?: string; maxEdgeLength?: 480 | 720 | 1080 | 1440 | 2160; maxFrameRate?: number; encodingMode?: "fast" | "slow"; audioCodec?: "aac" | "mp3" | "ac3" | "eac3";}
async function uploadVideo( filePath: string, options: UploadVideoOptions): Promise<string> { // Step 1: Submit the video config to get upload URL const uploadResponse = await fetch( `https://api.hesedvid.com/v1/api/${ORGID}/environments/${ENVID}/videos/upload-url`, { method: "POST", headers: { "X-Api-Key": APIKEY, "Content-Type": "application/json" }, body: JSON.stringify(options) } );
const { body: uploadData } = await uploadResponse.json();
// Step 2: Upload the video to the pre-signed URL const fileBlob = await fetch(filePath).then(r => r.blob()); await fetch(uploadData.uploadUrl, { method: "PUT", body: fileBlob });
return uploadData.videoID;}
// Example usage with all optionsconst videoID = await uploadVideo("/path/to/video.mp4", { fileName: "video.mp4", videoQuality: "ultra", allowPublicAccess: false, videoName: "Product Demo 2024", maxEdgeLength: 1080, maxFrameRate: 60, encodingMode: "slow", audioCodec: "aac"});import requestsfrom typing import Optional, Literal
ORGID = "org_XXX"ENVID = "ENV_XXX"APIKEY = "key_XXX"
def upload_video( file_path: str, file_name: str, video_quality: Literal["standard", "high", "ultra"], allow_public_access: bool, # Optional parameters video_name: Optional[str] = None, max_edge_length: Optional[int] = None, max_frame_rate: Optional[int] = None, encoding_mode: Optional[Literal["fast", "slow"]] = None, audio_codec: Optional[Literal["aac", "mp3", "ac3", "eac3"]] = None) -> str: # Step 1: Build request body with all options request_body = { 'fileName': file_name, 'videoQuality': video_quality, 'allowPublicAccess': allow_public_access }
# Add optional parameters if provided if video_name: request_body['videoName'] = video_name if max_edge_length: request_body['maxEdgeLength'] = max_edge_length if max_frame_rate: request_body['maxFrameRate'] = max_frame_rate if encoding_mode: request_body['encodingMode'] = encoding_mode if audio_codec: request_body['audioCodec'] = audio_codec
# Step 2: Submit the video config to get upload URL upload_response = requests.post( f'https://api.hesedvid.com/v1/api/{ORGID}/environments/{ENVID}/videos/upload-url', headers={ 'X-Api-Key': APIKEY, 'Content-Type': 'application/json' }, json=request_body )
upload_data = upload_response.json()['body']
# Step 3: Upload the video to the pre-signed URL with open(file_path, 'rb') as f: requests.put(upload_data['uploadUrl'], data=f)
return upload_data['videoID']
# Example usage with all optionsvideo_id = upload_video( file_path="/path/to/video.mp4", file_name="video.mp4", video_quality="ultra", allow_public_access=False, video_name="Product Demo 2024", max_edge_length=1080, max_frame_rate=60, encoding_mode="slow", audio_codec="aac")package main
import ( "bytes" "encoding/json" "fmt" "net/http" "os")
const ( ORGID = "org_XXX" ENVID = "ENV_XXX" APIKEY = "key_XXX")
type UploadURLRequest struct { // Required FileName string `json:"fileName"` VideoQuality string `json:"videoQuality"` AllowPublicAccess bool `json:"allowPublicAccess"`
// Optional VideoName *string `json:"videoName,omitempty"` MaxEdgeLength *int `json:"maxEdgeLength,omitempty"` MaxFrameRate *int `json:"maxFrameRate,omitempty"` EncodingMode *string `json:"encodingMode,omitempty"` AudioCodec *string `json:"audioCodec,omitempty"`}
type UploadURLResponse struct { Body struct { UploadURL string `json:"uploadUrl"` VideoID string `json:"videoID"` } `json:"body"`}
func uploadVideo(filePath string, req UploadURLRequest) (string, error) { // Step 1: Submit the video config to get upload URL reqBody, _ := json.Marshal(req)
httpReq, _ := http.NewRequest("POST", fmt.Sprintf("https://api.hesedvid.com/v1/api/%s/environments/%s/videos/upload-url", ORGID, ENVID), bytes.NewBuffer(reqBody)) httpReq.Header.Set("X-Api-Key", APIKEY) httpReq.Header.Set("Content-Type", "application/json")
client := &http.Client{} resp, err := client.Do(httpReq) if err != nil { return "", err } defer resp.Body.Close()
var uploadResp UploadURLResponse json.NewDecoder(resp.Body).Decode(&uploadResp)
// Step 2: Upload the video to the pre-signed URL file, _ := os.Open(filePath) defer file.Close()
putReq, _ := http.NewRequest("PUT", uploadResp.Body.UploadURL, file) client.Do(putReq)
return uploadResp.Body.VideoID, nil}
// Example usage with all optionsfunc main() { videoName := "Product Demo 2024" maxEdge := 1080 frameRate := 60 encoding := "slow" codec := "aac"
videoID, _ := uploadVideo("/path/to/video.mp4", UploadURLRequest{ FileName: "video.mp4", VideoQuality: "ultra", AllowPublicAccess: false, VideoName: &videoName, MaxEdgeLength: &maxEdge, MaxFrameRate: &frameRate, EncodingMode: &encoding, AudioCodec: &codec, })
fmt.Println("Video ID:", videoID)}How To Play The Video You Just Uploaded
After you upload your video, it will begin processing. When it’s done processing, you can take the public Video ID you got from step 1 and start to play the video:
<!-- Replace the {vidID} with the public video ID from step 1 --><iframe src="https://player.hesedvid.com/v1/public/{orgID}/{envID}/{vidID}/master.m3u8?autoplay=true&muted=true" frameborder="0" allowfullscreen></iframe>Check out our “Video Player” docs for more information.
Bonus: Upload Progress Tracking
For large files, you may want to track upload progress:
const uploadWithProgress = async (file, signedURL) => { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', (event) => { if (event.lengthComputable) { const percentComplete = (event.loaded / event.total) * 100; console.log(`Upload progress: ${percentComplete.toFixed(2)}%`); } });
xhr.addEventListener('load', () => { if (xhr.status === 200) { resolve('Upload complete'); } else { reject(new Error('Upload failed')); } });
xhr.open('PUT', signedURL); xhr.setRequestHeader('Content-Type', file.type); xhr.send(file); });};