Integrating Dotsub in to your video CMS

It’s a question we get here at Dotsub all the time. How do I integrate the captioning process into my custom CMS system? In this blog post I’ll show you how simple it is to add subtitles to your CMS workflow with a few calls to the Dotsub API.

I’ll be using cURL to call the Dotsub API and Python to listen for callbacks. This guide will use features from our ‘Extended API‘ which is only available to Enterprise accounts. If you need access to this API please contact us.

We will implement a workflow which will do the following:

  • Upload videos to Dotsub.
  • Orders captions and translations.
  • Listens for Pings from Dotsub server to download completed subtitle files.

The first step is to upload the video to Dotsub. Our team is good, but not good enough to caption your video without the file! Our ‘Media API‘ lets you upload a video file or provide us with a URL directly to a video file.

curl -u "username:password" -L -F file=@/Users/brooks/Movies/foo.mov -F title='My Video' -F description='Example' -F language='eng' -F license='a2be14e1-37d9-11dd-ae16-0800200c9a66' -F project=projectId https://dotsub.com/api/media

Note: You’ll have to replace username, password and projectId with the values for your Dotsub account.
Dotsub will reply with the UUID for your new video.

{"status":{"message":"Media created","error":false,"uuid":"f67c4500-9616-4ee6-962b-122c2aeb1e78","code":200}}

There you have it, your first video uploaded to Dotsub ready to be captioned.

Now we have to tell Dotsub what to do with this video. In this case we want captions and translations in a few languages. Let’s get it translated into French (Canada), Italian and Spanish. We do this by calling the order API:

curl -u "username:password" --form items="transcription,f67c4500-9616-4ee6-962b-122c2aeb1e78" 
--form items="translation,f67c4500-9616-4ee6-962b-122c2aeb1e78,fre_ca" --form items="translation,f67c4500-9616-4ee6-962b-122c2aeb1e78,ita" --form items="translation,f67c4500-9616-4ee6-962b-122c2aeb1e78,spa" https://dotsub.com/api/order

Note: You’ll have replace f67c4500-9616-4ee6-962b-122c2aeb1e78 with a UUID of your uploaded Dotsub video.
Dotsub will reply with all the details of your order:

{
    "order": {
        "completionDate": 1424375078795,
        "createdBy": "admin",
        "dateCreated": 1424375078760,
        "discount": 0,
        "id": "e94503e7-c253-4ed6-a8f3-1dda65833363",
        "invoiceNumber": "",
        "invoiced": false,
        "notes": "",
        "orderItems": [
            {
                "actor": "",
                "completionDate": 1424375078781,
                "dateCreated": 1424375078781,
                "deliveryDate": 0,
                "id": "e4b97aed-1918-44d8-b3b9-5743b350b903",
                "itemType": "TranscriptionOrderItem",
                "language": "eng",
                "languageName": "English",
                "mediaExternalIdentifier": "",
                "mediaId": "f67c4500-9616-4ee6-962b-122c2aeb1e78",
                "mediaLanguage": "eng",
                "mediaLanguageName": "English",
                "mediaTitle": "My Video",
                "orderId": "e94503e7-c253-4ed6-a8f3-1dda65833363",
                "orderNumber": "249",
                "orderProjectId": "",
                "orderProjectName": "",
                "orderStatus": "PENDING",
                "orderUsername": "admin",
                "percentageComplete": 0,
                "period": null,
                "price": 0,
                "readyToAssign": true,
                "subtitleSpecification": null,
                "userName": "",
                "vendorAssignedDate": 0,
                "vendorId": "",
                "vendorName": "",
                "videoMinutes": 0
            },
            {
                "actor": "",
                "completionDate": 1424375078783,
                "dateCreated": 1424375078783,
                "deliveryDate": 0,
                "id": "529c8a1b-0e50-491b-a3ac-6813441405f6",
                "itemType": "TranslationOrderItem",
                "language": "spa",
                "languageName": "Spanish",
                "mediaExternalIdentifier": "",
                "mediaId": "f67c4500-9616-4ee6-962b-122c2aeb1e78",
                "mediaLanguage": "eng",
                "mediaLanguageName": "English",
                "mediaTitle": "My Video",
                "orderId": "e94503e7-c253-4ed6-a8f3-1dda65833363",
                "orderNumber": "249",
                "orderProjectId": "",
                "orderProjectName": "",
                "orderStatus": "PENDING",
                "orderUsername": "admin",
                "percentageComplete": 0,
                "period": null,
                "price": 0,
                "readyToAssign": true,
                "subtitleSpecification": null,
                "userName": "",
                "vendorAssignedDate": 0,
                "vendorId": "",
                "vendorName": "",
                "videoMinutes": 0
            },
            {
                "actor": "",
                "completionDate": 1424375078782,
                "dateCreated": 1424375078782,
                "deliveryDate": 0,
                "id": "8d065be9-e72f-47b5-8cca-720eb6ea9078",
                "itemType": "TranslationOrderItem",
                "language": "ita",
                "languageName": "Italian",
                "mediaExternalIdentifier": "",
                "mediaId": "f67c4500-9616-4ee6-962b-122c2aeb1e78",
                "mediaLanguage": "eng",
                "mediaLanguageName": "English",
                "mediaTitle": "My Video",
                "orderId": "e94503e7-c253-4ed6-a8f3-1dda65833363",
                "orderNumber": "249",
                "orderProjectId": "",
                "orderProjectName": "",
                "orderStatus": "PENDING",
                "orderUsername": "admin",
                "percentageComplete": 0,
                "period": null,
                "price": 0,
                "readyToAssign": true,
                "subtitleSpecification": null,
                "userName": "",
                "vendorAssignedDate": 0,
                "vendorId": "",
                "vendorName": "",
                "videoMinutes": 0
            },
            {
                "actor": "",
                "completionDate": 1424375078782,
                "dateCreated": 1424375078782,
                "deliveryDate": 0,
                "id": "6a2c0dfa-d814-45ca-9d72-ac1deaea827d",
                "itemType": "TranslationOrderItem",
                "language": "fre_ca",
                "languageName": "French (Canada)",
                "mediaExternalIdentifier": "",
                "mediaId": "f67c4500-9616-4ee6-962b-122c2aeb1e78",
                "mediaLanguage": "eng",
                "mediaLanguageName": "English",
                "mediaTitle": "My Video",
                "orderId": "e94503e7-c253-4ed6-a8f3-1dda65833363",
                "orderNumber": "249",
                "orderProjectId": "",
                "orderProjectName": "",
                "orderStatus": "PENDING",
                "orderUsername": "admin",
                "percentageComplete": 0,
                "period": null,
                "price": 0,
                "readyToAssign": true,
                "subtitleSpecification": null,
                "userName": "",
                "vendorAssignedDate": 0,
                "vendorId": "",
                "vendorName": "",
                "videoMinutes": 0
            }
        ],
        "orderNumber": 249,
        "orderSource": "ADMIN",
        "orderStatus": "PENDING",
        "price": 0,
        "projectId": "",
        "projectName": "",
        "totalItems": 4,
        "videoMinutes": 0
    }
}

Now we will build a Python script that listens for pings from the Dotsub API. The address Dotsub sends pings to is configured under ‘Project Settings’ in your project.

We will listen for ‘order pings‘ where their status is ‘ITEM_COMPLETED’. When we see that an item is completed we will download it using the ‘Order Download‘ API.

from BaseHTTPServer import BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
import base64
import urllib2
import cgi
#An example script that listens for HTTP order pings from the Dotsub API.

username = "username"
password = "password"

auth_header = base64.b64encode(("%s:%s" % (username, password)))

download_url = "https://dotsub.com/api/order/%s/items/%s/download"

class PostHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        # Parse the form data posted
        form = cgi.FieldStorage(
            fp=self.rfile,
            headers=self.headers,
            environ={'REQUEST_METHOD': 'POST',
                     'CONTENT_TYPE': self.headers['Content-Type'],
                     })
        #There are the 4 fields the Dotsub Order Ping API posts in a callback.
        orderId = form['orderId'].value
        itemId = form['itemId'].value
        language = form['language'].value
        state = form['state'].value
        #only download an item when the item has been completed
        if state == 'ITEM_COMPLETE':
            file_url = download_url % (orderId, itemId)
            sub_req = urllib2.Request(file_url)
            sub_req.add_header('Authorization', 'Basic %s' % auth_header)
            u = urllib2.urlopen(sub_req)
            filename =  "%s_%s.srt" % (itemId, language)
            localFile = open( filename, 'w')
            localFile.write(u.read())
            localFile.close()
        self.send_response(200)

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    """Handle requests in a separate thread."""

if __name__ == '__main__':
    server = ThreadedHTTPServer(('', 9088), PostHandler)
    print 'Starting server, use  to stop'
    server.serve_forever()

And there you have it. In under 100 lines of code, we are submitting video files to Dotsub, ordering captions and translations, and handling the download of completed caption files.сайтповедение клиентоввзлом пользователей вконтакте