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 / Schema.
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 / Schema.
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 / Schema. 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);
}
}
}