Login

Upload videos directly

FastPix Direct Uploads provide a streamlined solution for uploading media (video and audio) directly to your platform from client applications. This guide will simplify the process and highlight how users can effectively utilize authenticated upload URLs for seamless content delivery.


Why to use FastPix direct uploads


  • Authenticated access: Grant authenticated access for direct uploads from mobile and web applications, ensuring secure and controlled content management.
  • Flexible upload options: Upload media directly from your server or use command-line tools, providing ultimate flexibility in how you manage your media.
  • Storage efficiency: Eliminate the need to store original files on your local system, reducing storage costs and simplifying file management.
  • Better user experience: Deliver exceptional experiences to your audience with efficient content delivery, reducing loading times and improving accessibility.

Use case scenarios

FastPix Direct Uploads can be utilized in multiple scenarios:

  • Mobile app uploads: Users can upload videos directly from their mobile devices, enhancing user-generated content (UGC) capabilities.
  • Web app uploads: Web applications can facilitate direct uploads, allowing users to share content easily.
  • Server-side content uploads: Large platforms can upload media files in batches from their servers, streamlining content management.
  • Command-line tool uploads: Developers can leverage command-line tools for quick and efficient uploads, perfect for automated workflows.

Uploading media to FastPix in 3 steps

Follow these steps to easily upload content directly to FastPix:


Step 1: Generate a unique upload URL

  • Generate an access token: Create a new Access Token in FastPix dashboard. This token consists of a Token ID (username) and Token Secret (password) pair, which are necessary for authenticating with the FastPix Video API. See the guide.
  • Make the API request: You can visit FastPix API reference and navigate to the Upload media from device endpoint. This lets you create a new direct upload with your desired media settings.
  • Receive your upload URL: The API in its response will generate an authenticated URL specifically for your upload. This URL is unique and can be used directly in your client applications.
  • Keep track of your upload ID: Along with the URL, you will receive a unique ID for this direct upload. Make sure to save this ID for tracking the upload progress later through the API.

Command line tool:

curl --request POST \
     --url https://v1.fastpix.io/on-demand/uploads \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "corsOrigin": "*",
  "pushMediaSettings": {
    "accessPolicy": "public",
    "metadata": {
      "key1": "value1"
    },
    "maxResolution": "1080p",
    "mp4Support": "capped_4k"
  }
}
'

Javascript:

<script>
// This endpoint provides you with the signed URL necessary for uploading your video. 

const url = 'https://v1.fastpix.io/on-demand/uploads';

// The FastPix Video API employs a token key pair consisting of a Token ID (username) and Token Secret (password) for authentication.  
// Generate a new Access Token in the Access Token settings located within your FastPix Organization dashboard. 
const username = '';
const password = '';

// Initialize the data object 
const data = {
    corsOrigin: '*',
    newAssetSettings: {
        accessPolicy: 'public',
        metadata: {
            key1: 'value1',
        },
        generateSubtitles: false,
        normalizeAudio: true,
        maxResolution: '1080p',
    },
};

const options = {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        Authorization: 'Basic ' + btoa(username + ':' + password),
    },
    body: JSON.stringify(data),
}

fetch(url, options)
    .then(response => {
        if (response.success) {

            // You can fetch the signedUrl in the response 
        }
    }) 
</script>

Step 2: Initiate the upload

With the upload URL in hand, you’re ready to upload your media content. In your client application (whether it’s a mobile or web app), use the provided URL to initiate a PUT request. Include the file you want to upload in the request body. The API accepts the media file from the device and uploads it to the FastPix platform.


Step 3: Track your upload

Once uploaded, the media undergoes processing and is assigned a unique ID for tracking. Retain this  uploadId  for any future operations related to this upload.

Check your FastPix dashboard to confirm successful uploads. You'll see new assets listed with the settings you specified during setup, along with the uploaded video. Alternatively, you can also use the  Get Media by ID  endpoint to check the status of the uploaded media asset and see if it has transitioned to a ready status for playback.


📘

USING WEBHOOKS

To notify your application about the status of this API request check for the webhooks for Upload related events.


Resumable uploading of large files

When it comes to uploading files, especially large ones like videos, using the right method is crucial for a smooth and efficient experience. This guide explains how to implement resumable uploads effectively.


How resumable uploads work through chunking

Resumable uploads can be effectively handled through a technique called chunking. This method involves breaking down large files into smaller, more manageable pieces, or "chunks." Here's how chunking works:

  1. Divide the file: Large files are split into smaller, manageable chunks (e.g., 16 MB by default).
  2. Upload individually: Each chunk is uploaded separately. If a chunk fails, only that specific chunk needs to be re-uploaded.
  3. Resume capability: If the upload is interrupted, you can resume from the last successfully uploaded chunk instead of starting over.

This approach is important because:

  • It reduces the risk: Uploading smaller chunks minimizes the risk of failure. If a chunk fails to upload due to network issues, only that specific chunk needs to be re-uploaded, not the entire file.
  • Improves performance: Smaller chunks can be uploaded more quickly and efficiently, especially on slower connections, as they require less time to transfer.
  • Easier management: Chunking allows for better tracking of upload progress, making it easier to implement features like pause and resume.

The FastPix Uploader SDK helps you efficiently upload large files from the browser by splitting them into chunks and also gives you the ability to pause and resume your uploads.


Installation

To install the SDK, you can use npm or any of your favourite node package manager 😉:

npm i @fastpix/uploader

Basic usage

To get started with the SDK, you will need a signed URL.

To make API requests, you'll need a valid Access Token and Secret Key. See the Basic Authentication Guide for details on retrieving these credentials.

Once you have your credentials, use the Upload media from device API to generate a signed URL for uploading media.

import { Uploader } from "@fastpix/uploader"; 

const fileUploader = Uploader.init({
    endpoint: 'https://example.com/signed-url', // Replace with the signed URL. 
    file: mediaFile, // Provide the media file you want to upload. 
    chunkSize: 5120, // Specify the chunk size in kilobytes (KB). Minimum allowed chunk size is 5120KB (5MB). 

    // Additional optional parameters can be specified here as needed 
})

Monitor the upload progress through lifecycle events

// fileUploader is the instance of the Uploader 
// Track upload progress 
fileUploader.on('progress', event => {
    console.log("Upload Progress:", event.detail);
});

// Handle errors during the upload process 
fileUploader.on('error', event => {
    console.error("Upload Error:", event.detail.message);
});

// Trigger actions when the upload completes successfully 
fileUploader.on('success', event => {
    console.log("Upload Completed");
});

// Track the initiation of each chunk upload 
fileUploader.on('attempt', event => {
    console.log("Chunk Upload Attempt:", event.detail);
});

// Track failures of each chunk upload attempt 
fileUploader.on('chunkAttemptFailure', event => {
    console.log("Chunk Attempt Failure:", event.detail);
});

// Perform an action when a chunk is successfully uploaded 
fileUploader.on('chunkSuccess', event => {
    console.log("Chunk Successfully Uploaded:", event.detail);
});

// Triggers when the connection is back online 
fileUploader.on('online', event => {
    console.log("Connection Online");
});

// Triggers when the connection goes offline 
fileUploader.on('offline', event => {
    console.log("Connection Offline");
});

Managing video uploads

You can control the upload lifecycle with the following methods:

Pause an upload:

// fileUploader is the instance of the Uploader 
fileUpload.pause() 

Resume an upload:

// fileUploader is the instance of the Uploader 
fileUpload.resume() 

Abort an upload:

// fileUploader is the instance of the Uploader 
fileUpload.abort() 

Parameters to use

This SDK supports the following parameters:

  • endpoint (mandatory): The URL endpoint where the file will be uploaded.
  • file (mandatory): The file object that you want to upload (e.g., a video file).
  • chunkSize (optional): chunkSize should be provided in kilobytes (KB). By default, the SDK splits files into chunks of 16 MB. You can customize this by specifying a chunkSize in kilobytes (minimum of 5 MB).
  • maxFileSize (optional): This parameter restricts the maximum file size that users can upload. Setting this can help prevent users from attempting to upload excessively large files that may not be manageable.
  • retryChunkAttempt (optional): Specifies the number of times to retry uploading a chunk in case of failure. The default value is 5.
  • delayRetry (optional): The delay time (in milliseconds) before retrying a chunk upload after a failure. The default value is 1000ms.

import React, { useState, useRef } from "react";
import { Uploader } from "@fastpix/uploader";

function Uploads() {
    const [progress, setProgress] = useState(0);
    const [statusMessage, setStatusMessage] = useState({
        status: "",
        message: "",
    });

    const fileInputRef = useRef(null);
    const fileUploadRef = useRef(null);

    const handleUpload = (video, signedUrl) => {
        try {
           
            // Initialize the uploader with the signed URL and video file 
            const fileUpload = Uploader.init({
                endpoint: signedUrl, // The signed URL to upload the file to 
                file: video, // The video file to upload 
                chunkSize: 5120, // The size of each chunk in KB 
            });
            fileUploadRef.current = fileUpload;

            // Listen to the 'progress' event to update progress percentage 
            fileUpload.on("progress", (event) => {
                console.log(event);
                setProgress(event.detail);
            });

            // Listen to the 'success' event to display a success message 
            fileUpload.on("success", () => {
                setStatusMessage({
                    message: "Upload completed successfully!",
                    status: "success",
                });
            });

            // Listen to the 'error' event to handle errors 
            fileUpload.on("error", (event) => {
                setStatusMessage({ message: event.detail.message, status: "error" });
            });

            // Pause an upload 
            // fileUpload.pause() 
            // Resume an upload 
            // fileUpload.resume() 
            // Abort an upload 
            // fileUpload.abort() 
        } catch (error) {
            setStatusMessage({ message: error?.message, status: "error" });
        }
    };

    const handleUploadProcess = async (file) => {
        if (!file) {
            setStatusMessage({
                message: "Please select a video to upload.",
                status: "error",
            });
            return;
        }

        try {

            // The endpoint URL for getting the signed upload URL 
            const url = "https://v1.fastpix.io/on-demand/uploads";

            // Basic authentication credentials 
            const username = "";
            const password = "";

            // Data to send in the POST request to configure the upload 
            const data = {
                corsOrigin: "*", // Specify allowed cross-origin requests 
                pushMediaSettings: {
                    accessPolicy: "public", // Set access policy to public 
                    metadata: { key1: "value1" }, // Metadata associated with the video 
                    generateSubtitles: false, // Disable automatic subtitle generation 
                    normalizeAudio: true, // Enable audio normalization 
                    maxResolution: "1080p", // Set the maximum video resolution 
                },
            };

            const headersRequest = {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    Authorization: "Basic " + btoa(username + ":" + password),
                },
                body: JSON.stringify(data),
            };
            const getSignedUrl = await fetch(url, headersRequest);
            const signedUrl = await getSignedUrl.json();
            if (signedUrl.success) {
                handleUpload(file, signedUrl.data.url);
            } else {
                setStatusMessage({ message: signedUrl.data.error, status: "error" });
            }
        } catch (error) {
            console.error(error);
            setStatusMessage({
                message: "Failed to fetch signed URL.",
                status: "error",
            });
        }
    };

    // Function to simulate a file upload button click 
    const handleButtonClick = () => {
        fileInputRef.current.click();
    };

    // Handle file selection and initiate the upload process 
    const handleFileChange = (event) => {
        const file = event.target.files[0];
        if (file) {
            handleUploadProcess(file);
        }
    };

    return (
        <div
            style={{
                textAlign: "center",
                width: "100%",
                border: "1px dashed #0f0f0f",
                borderRadius: "8px",
            }}
        >
            <h2 style={{ marginBottom: "20px" }}>Fastpix Resumable Uploads</h2>

            {/* Button to select a file for upload */}
            <div
                style={{
                    marginTop: "20px",
                    display:
                        progress > 0 && statusMessage?.status !== "success"
                            ? "none"
                            : "block",
                }}
            >
                <button
                    onClick={handleButtonClick}
                    style={{
                        padding: "10px 20px",
                        cursor: "pointer",
                        backgroundColor: "#0f0f0f",
                        color: "#ffffff",
                    }}
                >
                    Choose Video to Upload
                </button>
                <input
                    type="file"
                    ref={fileInputRef}
                    onChange={handleFileChange}
                    style={{ display: "none" }}
                />
            </div>
            <div style={{ padding: "20px" }}>

                {/* Display the upload progress */}
                <p style={{ display: "block", marginBottom: "10px" }}>
                    Progress: {`${Math.round(progress)}%`}
                </p>
                <div
                    style={{
                        backgroundColor: "#eee",
                        width: "100%",
                        height: "6px",
                        marginTop: "20px",
                    }}
                >
                    <div
                        style={{
                            backgroundColor: "#0f0f0f",
                            transition: "width 0.20s",
                            width: `${progress}%`,
                            height: "6px",
                            marginTop: "20px",
                            borderRadius: "100px",
                        }}
                    ></div>
                </div>

                {/* Display the status message */}
                <p>{statusMessage.message}</p>
            </div>
        </div>
    );
}

export default Uploads; 

import { Uploader } from "@fastpix/uploader";

// Imagine there's an HTML page featuring an input field as follows: <input id="videoFile" type="file" /> 
const videoFile = document.getElementById('videoFile');

videoFile.onchange = async () => {

    try {

        // The endpoint URL for getting the signed upload URL 
        const url = 'https://v1.fastpix.io/on-demand/uploads';

        // Basic authentication credentials 
        const username = '';
        const password = '';

        // Data to send in the POST request to configure the upload 
        const data = {
            corsOrigin: "*", // Specify allowed cross-origin requests 
            pushMediaSettings: {
                accessPolicy: "public", // Set access policy to public 
                metadata: { key1: "value1" }, // Metadata associated with the video 
                generateSubtitles: false, // Disable automatic subtitle generation 
                normalizeAudio: true, // Enable audio normalization 
                maxResolution: "1080p", // Set the maximum video resolution 
            },
        };

        const options = {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                Authorization: 'Basic ' + btoa(username + ':' + password),
            },
            body: JSON.stringify(data),
        };

        const getSignedUrl = await fetch(url, headersRequest);
        const signedUrl = await getSignedUrl.json();

        if (signedUrl.success) {
            handleUpload(videoFile.files[0], signedUrl.data.url)
        } else {
            console.error(signedUrl.data.error)
        }
    } catch (error) {
        console.error(error)
    }
}

const handleUpload = (video, signedUrl) => {

    const fileUpload = Uploader.init({
        endpoint: signedUrl, // The signed URL to upload the file to 
        file: video, // The video file to upload 
        chunkSize: 5120, // The size of each chunk in KB 

        // Additional optional parameters can be specified here as needed 
    });

    // Event listener for tracking upload progress. 
    fileUpload.on('progress', event => {
        setProgress(event.detail);
    });

    // Event listener for handling successful upload completion. 
    fileUpload.on('success', () => {
        setStatusMessage({ message: "Upload completed successfully!", status: "success" });
    });

    // Event listener for handling upload errors. 
    fileUpload.on('error', event => {
        setStatusMessage({ message: event.detail.message, status: "error" });
    });
    // Pause an upload 
    // fileUpload.pause() 
    // Resume an upload 
    // fileUpload.resume() 
    // Abort an upload 
    // fileUpload.abort() 
}