Demos
Below you will find many different examples and demos of OpenShot Cloud API. Sample code is provided in many common programming languages, including Python, C#, and JavaScript.
Demo App (simple-editor)
Check out our free demo app (simple-editor), built with JavaScript, Node.js, and Vue 3, powered by OpenShot Cloud API. This demo is designed as both a showcase for how OpenShot Cloud API can be used and a jump-start for your own software development projects based on OpenShot Cloud API! The source code is licensed under the MIT license, and can be used with both open-source and commercial applications.
Create and manage video editing projects:

Upload files, preview videos, and create clips:

Python Example Script
Here is a simple example client script, using Python 3. It connects, creates a new project, uploads a file, creates a clip, and then exports a new video. It should give you a good sense of how things work in general, regardless of programming language. Learn more about the API Endpoints.
import os
import time
from requests import get, post
from requests.auth import HTTPBasicAuth
PATH = os.path.dirname(os.path.realpath(__file__))
CLOUD_URL = 'http://cloud.openshot.org'
CLOUD_AUTH = HTTPBasicAuth('demo-cloud', 'demo-password')
##########################################################
# Get list of projects
end_point = '/projects/'
r = get(CLOUD_URL + end_point, auth=CLOUD_AUTH)
print(r.json())
##########################################################
# Create new project
end_point = '/projects/'
project_data = {
"name": "API Project",
"width": 1920,
"height": 1080,
"fps_num": 30,
"fps_den": 1,
"sample_rate": 44100,
"channels": 2,
"channel_layout": 3,
"json": "{}",
}
r = post(CLOUD_URL + end_point, data=project_data, auth=CLOUD_AUTH)
print(r.json())
project_id = r.json().get("id")
project_url = r.json().get("url")
##########################################################
# Upload file to project
end_point = '/projects/%s/files/' % project_id
source_path = os.path.join(PATH, "example-video.mp4")
source_name = os.path.split(source_path)[1]
file_data = {
"media": None,
"project": project_url,
"json": "{}"
}
r = post(CLOUD_URL + end_point, data=file_data, files={"media": (source_name, open(source_path, "rb"))}, auth=CLOUD_AUTH)
file_url = r.json().get("url")
print(r.json())
##########################################################
# Create a clip for the previously uploaded file
end_point = '/projects/%s/clips/' % project_id
clip_data = {
"file": file_url,
"position": 0.0,
"start": 0.0,
"end": 30.0,
"layer": 1,
"project": project_url,
"json": "{}"
}
r = post(CLOUD_URL + end_point, data=clip_data, auth=CLOUD_AUTH)
print(r.json())
##########################################################
# Create export for final rendered video
end_point = '/projects/%s/exports/' % project_id
export_data = {
"video_format": "mp4",
"video_codec": "libx264",
"video_bitrate": 8000000,
"audio_codec": "ac3",
"audio_bitrate": 1920000,
"start_frame": 1,
"end_frame": None,
"project": project_url,
"json": "{}"
}
r = post(CLOUD_URL + end_point, data=export_data, auth=CLOUD_AUTH)
export_url = r.json().get("url")
print(r.json())
##########################################################
# Wait for Export to finish (give up after around 40 minutes)
export_output_url = None
is_exported = False
countdown = 500
while not is_exported and countdown > 1:
r = get(export_url, auth=CLOUD_AUTH)
print(r.json())
is_exported = float(r.json().get("progress", 0.0)) == 100.0
countdown -= 1
time.sleep(5.0)
# Get final rendered url
r = get(export_url, auth=CLOUD_AUTH)
export_output_url = r.json().get("output")
print(r.json())
print("Export Successfully Completed: %s!" % export_output_url)
Node.js Example Script
Here is a simple example client script, using JavaScript and Node.js. It connects, creates a new project, uploads some files, creates some clips, exports a video, and then downloads the new video file. It should give you a good sense of how things work using asynchronous JavaScript. Learn more about the API Endpoints.
var request = require('request-promise');
var fs = require('fs');
var Promise = require("promise");
var promisePoller = require('promise-poller').default;
var projectId = '';
var projectUrl = '';
var exportId = '';
const projectData = {
'json': '{}',
'name': 'My Project Name'
};
const protocol = 'http';
const server = 'cloud.openshot.org';
const auth = { 'user': 'demo-cloud',
'pass': 'demo-password'};
// Create a new project
post('/projects/', projectData)
.then(function(response){
projectUrl = JSON.parse(response).url;
projectId = JSON.parse(response).id;
console.log('Successfully created project: ' + projectUrl);
// Add a couple clips (to be asynchronously processed)
const promiseArray = [];
promiseArray.push(
createClip({
"path": "media-files/MyVideo.mp4",
"position": 0.0,
"end": 10.0
}));
promiseArray.push(
createClip({
"path": "media-files/MyAudio.mp4",
"position": 0.0,
"end": 10.0
}));
promiseArray.push(
createClip({
"path": "media-files/Watermark.JPG",
"position": 0.0,
"end": 10.0,
"layer": 2
}));
// Wait until all files and clips are uploaded
Promise.all(promiseArray).then(function(responseArray){
// Export as a new video
exportData = {
"export_type": "video",
"video_format": "mp4",
"video_codec": "libx264",
"video_bitrate": 8000000,
"audio_codec": "ac3",
"audio_bitrate": 1920000,
"project": projectUrl,
"json": '{}'
};
post('/exports/', exportData)
.then(function(response){
// Export has been created and will begin processing soon
var exportUrl = JSON.parse(response).url;
exportId = JSON.parse(response).id;
console.log('Successfully created export: ' + exportUrl);
// Poll until the export has finished
var poller = promisePoller({
taskFn: isExportCompleted,
interval: 1000,
retries: 60*60*1000,
timeout: 2000
}).then(function(exportOutputUrl) {
// New exported video is ready for download now
console.log('Download ' + exportOutputUrl);
request(exportOutputUrl).pipe(fs.createWriteStream('Output-' + projectId + '.mp4'));
});
});
});
});
function isExportCompleted() {
return new Promise(function (resolve, error) {
get('/exports/' + exportId + '/', {})
.then(function(response) {
var exportStatus = JSON.parse(response).status;
var exportOutputUrl = JSON.parse(response).output;
if (exportStatus == 'completed') {
console.log('Export completed: ' + JSON.stringify(response));
resolve(exportOutputUrl);
}
});
});
}
function createClip(clip) {
// Create new File object (and upload file from filesystem)
var fileData = {
'json': '{}',
'project': projectUrl,
'media': fs.createReadStream(clip.path)
};
return new Promise(function (resolve) {
post('/files/', fileData)
.then(function(response) {
// File uploaded and object created
var fileUrl = JSON.parse(response).url;
console.log('Successfully created file: ' + fileUrl);
// Now we need to add a clip which references this new File object
var clipData = {
'file': fileUrl,
'json': '{}',
'position': clip.position || 0.0,
'start': clip.start || 0.0,
'end': clip.end || JSON.parse(response).json.duration,
'layer': clip.layer || 0,
'project': projectUrl
};
return post('/clips/', clipData).then(function(response){
var clipUrl = JSON.parse(response).url;
console.log('Successfully created clip: ' + clipUrl);
resolve();
});
});
});
}
function post(endpoint, data) {
// Prepare request object and POST data to OpenShot API
const r = request.post(protocol + '://' + auth.user + ':' + auth.pass + '@' + server + endpoint, function (err, response, body) {
if (err) {
return err;
} else {
console.log(response.statusCode + ': ' + body);
return body;
}
});
// Append form data to request form-data
const form_data = r.form();
for ( var key in data ) {
form_data.append(key, data[key]);
}
return r;
}
function get(endpoint, data) {
// Prepare request object and GET data to OpenShot API
return request.get(protocol + '://' + auth.user + ':' + auth.pass + '@' + server + endpoint, function (err, response, body) {
if (err) {
return err;
} else {
console.log(response.statusCode + ': ' + body);
return body;
}
});
}
C# Example Script
Here is a simple example client script, using C# (.NET version: 5.0.103). It connects, creates a new project, uploads a file, creates a clips, exports a video, and then prints the new video file link. It should give you a good sense of how things work in C# (This code has been made synchronous on purpose). Learn more about the API Endpoints. This also uses 2 NuGet packages: Newtonsoft, MimeMapping
using System;
using System.Collections.Generic;
using System.Threading;
using System.Net.Http;
using System.Net.Http.Headers;
using System.IO;
using Newtonsoft.Json.Linq;
using MimeMapping;
namespace OpenShot
{
class Program
{
static void Main(string[] args)
{
String MakeGetRequest(string url, HttpClient client)
{
Console.WriteLine("GET: " + url);
var response = client.GetAsync(url).GetAwaiter().GetResult();
Console.WriteLine("Response StatusCode: " + (int)response.StatusCode);
if (response.IsSuccessStatusCode){
return response.Content.ReadAsStringAsync().GetAwaiter().GetResult();;
}else{
Console.WriteLine("Request Failed with message:" +
response.Content.ReadAsStringAsync().GetAwaiter().GetResult());
}
return "";
}
String MakePostRequest(string url, Dictionary<string, string> formData, HttpClient client)
{
var requestContent = new FormUrlEncodedContent(formData);
Console.WriteLine("POST: " + url);
var response = client.PostAsync(url, requestContent).GetAwaiter().GetResult();
Console.WriteLine("Response StatusCode: " + (int)response.StatusCode);
if (response.IsSuccessStatusCode){
return response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
}else{
Console.WriteLine("Request Failed with message:" +
response.Content.ReadAsStringAsync().GetAwaiter().GetResult());
}
return "";
}
String MakePostRequestWithFile(string url, Dictionary<string, string> formData, HttpClient client, FileInfo fileInfo)
{
var requestContent = new MultipartFormDataContent();
var fileContent = new StreamContent(fileInfo.OpenRead());
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
Name = "\"media\"",
FileName = "\"" + fileInfo.Name + "\""
};
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse(MimeMapping.MimeUtility.GetMimeMapping(fileInfo.Name));
foreach (KeyValuePair<string, string> kvp in formData)
{
requestContent.Add(new StringContent(kvp.Value), kvp.Key);
}
requestContent.Add(fileContent);
Console.WriteLine("POST: " + url);
var response = client.PostAsync(url, requestContent).GetAwaiter().GetResult();
Console.WriteLine("Response StatusCode: " + (int)response.StatusCode);
if (response.IsSuccessStatusCode){
return response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
}else{
Console.WriteLine("Request Failed with message:" +
response.Content.ReadAsStringAsync().GetAwaiter().GetResult());
}
return "";
}
HttpClient client = new HttpClient();
// Connection info
string serverUrl = "http://cloud.openshot.org/";
// Basic Auth
String username = "demo-cloud";
String password = "demo-password";
String encoded = System.Convert.ToBase64String(
System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(
username + ":" + password));
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", encoded);
////////////////////////////////////////////////////////////////////////////////////////
// Get list of projects
Console.WriteLine("\n Get list of projects \n");
String responseGetRequest = MakeGetRequest(serverUrl + "projects/", client);
Console.WriteLine(responseGetRequest);
////////////////////////////////////////////////////////////////////////////////////////
// Create new project
Console.WriteLine("\n Create new project \n");
Dictionary<string, string> payload = new Dictionary<string, string>
{
{ "name", "API Project" },
{ "width", "1920" },
{"height", "1080"},
{"fps_num", "30"},
{"fps_den", "1"},
{"sample_rate", "44100"},
{"channels", "2"},
{"channel_layout", "3"},
{"json", "{}" }
};
String responsePostRequest = MakePostRequest(serverUrl + "projects/", payload, client);
Console.WriteLine(responsePostRequest);
dynamic jsonObj = JObject.Parse(responsePostRequest);
Int32 projectId = jsonObj.id;
String projectUrl = jsonObj.url;
Console.WriteLine("Project ID: " + projectId);
Console.WriteLine("Project URL: "+ projectUrl);
////////////////////////////////////////////////////////////////////////////////////////
// Upload file to project
Console.WriteLine("\n Upload file to project \n");
payload = new Dictionary<string, string>
{
{"media", ""},
{"project", projectUrl},
{"json", "{}" }
};
String filePath = "D:\\test-file.mp4";
responsePostRequest = MakePostRequestWithFile(
projectUrl + "files/",
payload,
client,
new FileInfo(filePath)
);
Console.WriteLine(responsePostRequest);
jsonObj = JObject.Parse(responsePostRequest);
String fileUrl = jsonObj.url;
Console.WriteLine("File URL:" + fileUrl);
////////////////////////////////////////////////////////////////////////////////////////
// Create a clip for the previously uploaded file
Console.WriteLine("\n Create a clip for the previously uploaded file \n");
payload = new Dictionary<string, string>
{
{"file", fileUrl},
{"position", "0.0"},
{"start", "0.0"},
{"end", "2.0"},
{"layer", "1"},
{"project", projectUrl},
{"json", "{}"}
};
responsePostRequest = MakePostRequest(projectUrl + "clips/", payload, client);
Console.WriteLine(responsePostRequest);
////////////////////////////////////////////////////////////////////////////////////////
// Create export for final rendered video
Console.WriteLine("\n Create export for final rendered video \n");
payload = new Dictionary<string, string>
{
{"video_format", "mp4"},
{"video_codec", "libx264"},
{"video_bitrate", "8000000"},
{"audio_codec", "ac3"},
{"audio_bitrate", "1920000"},
{"start_frame", "1"},
{"end_frame", ""},
{"project", projectUrl},
{"json", "{}"}
};
responsePostRequest = MakePostRequest(projectUrl + "exports/", payload, client);
Console.WriteLine(responsePostRequest);
jsonObj = JObject.Parse(responsePostRequest);
String exportUrl = jsonObj.url;
Boolean isExported = false;
Int16 countdown = 500;
while (!isExported && countdown > 1){
String responseExportGetRequest = MakeGetRequest(exportUrl, client);
jsonObj = JObject.Parse(responseExportGetRequest);
String progress = jsonObj.progress;
if (progress != null && progress !=""){
float progressFloat = float.Parse(progress);
if (progressFloat == 100.0){
isExported = true;
}
}
countdown -= 1;
Thread.Sleep(5000);
}
responseGetRequest = MakeGetRequest(exportUrl, client);
jsonObj = JObject.Parse(responseGetRequest);
Console.WriteLine(responseGetRequest);
Console.WriteLine("Export Successfully Completed: " + jsonObj.output);
}
}
}