Providing transcriptions from the local file system

In this guide you'll learn how to upload a video and provide a transcription when both files reside on the local file system. For a description of each field in the request and response, see the API Reference > Create a video indexing task page.

Note that, although the example code in this guide is written in Python and Node.js the API is compatible with most programming languages, and you can also use Postman or other REST clients to send requests and view responses.


  • Your transcription must be in the SRT or VTT format.
  • Your video must meet the following requirements:
    • Video resolution: must be greater or equal than 360p and less than 1080p (FHD)
    • Duration: must be between 10 seconds and 2 hours (7,200s)
      If you require different options, send us an email at support[at]
  • A valid Twelve Labs account. For details about creating an account and retrieving your API key, see the Authentication page.
  • You’re familiar with the concepts that are described on the Quickstart page.
  • You’ve created at least one index, and the unique identifier of your index is stored in a variable named INDEX_ID. For details, see the Creating indexes page.


  • For consistent search results, Twelve Labs recommends you upload 360p videos.


  1. Declare the /tasks endpoint:

    TASKS_URL = f"{API_URL}/tasks"
    const TASKS_URL = `${API_URL}/tasks`
  2. Read your video file. Open a stream, making sure to replace the placeholders surrounded by <> with your values:

    video_file_path = "<YOUR_VIDEO_FILE_PATH>"
    video_file_name = "<YOUR_VIDEO_FILE_NAME>"
    video_file_stream = open(video_file_path, "rb")
    const video_file_path = '<YOUR_VIDEO_FILE_PATH>'
    const video_file_stream = fs.createReadStream(video_file_path)
  3. Read your transcription file. Open a stream, making sure to replace the placeholders surrounded by <> with your values:

    transcription_file_path = "<YOUR_TRANSCRIPTION_FILE_PATH>"
    transcription_file_name = "<YOUR_TRANSCRIPTION_FILE_NAME>"
    transcription_file_stream = open(transcription_file_path, "rb")
    const transcription_file_path = '<YOUR_TRANSCRIPTION_FILE_PATH>'
    const transcription_file_stream = fs.createReadStream(transcription_file_path)
  4. To provide a transcription file, you must set the provide_transcription parameter to true and specify the index ID, the language of your video, and the video and transcription files.
    If you're using Python, store the provide_transcription parameter, the index ID, and the language of your video in a dictionary named data. Then, store the video and transcription files in an array named file_param.
    If you're using Node.js, store all the required parameters in a variable named formData of type FormData:

    data = {
       "provide_transcription": True
       "index_id": INDEX_ID,
       "language": "en",
    file_param = [
        ("video_file", (video_file_name, video_file_stream, "application/octet-stream")),
        ("transcription_file", (transcription_file_name, transcription_file_stream, "application/octet-stream")),
      let formData = new FormData()
      formData.append('provide_transcription', 'true')
      formData.append('INDEX_ID', INDEX_ID)
      formData.append('language', 'en')
      formData.append('video_file', video_file_stream)
      formData.append('transcription_file', transcription_file_stream)
  5. Upload your video and transcription files. Call the /tasks endpoint and store the result in a variable named response:

    response =, headers=headers, data=data, files=file_param)
    config = {
          method: 'post',
          url: TASKS_URL,
          headers: headers,
          data : formData
    resp = await axios(config)
    response = await
  6. Store the ID of your task in a variable named TASK_ID and print the status code and response:

    TASK_ID = response.json().get("_id")
    print (f"Status code: {response.status_code}")
    pprint (response.json())
    const TASK_ID = response._id
    console.log(`Status code: ${resp.status}`)
  7. (Optional) You can use the /tasks/{_id} endpoint to monitor the indexing process. Wait until the status shows as ready:

    TASK_STATUS_URL = f"{API_URL}/tasks/{TASK_ID}"
    while True:
        response = requests.get(TASK_STATUS_URL, headers=headers)
        STATUS = response.json().get("status")
        if STATUS == "ready":
            print (f"Status code: {STATUS}")
            pprint (response.json())
    const TASK_STATUS_URL = `${API_URL}/tasks/${TASK_ID}`
    config = {
      method: 'get',
      url: TASK_STATUS_URL,
      headers: headers,
    let STATUS
    do {
      resp = await axios(config)
      response = await
      STATUS = response.status
      if (STATUS !== 'ready')
        await new Promise(r => setTimeout(r, 10000));
    } while (STATUS !== 'ready')
    console.log(`Status code: ${STATUS}`)

    The output should look similar to the following one:

    Status code: 200
    {'_id': '6391c89afb14854546891276',
     'created_at': '2022-12-08T11:20:58.859Z',
     'estimated_time': '2022-12-08T11:34:54.585Z',
     'index_id': '6391c88bfb14854546891275',
     'metadata': {'duration': 810.84,
                  'filename': 'best-racing-moments.mp4',
                  'height': 480,
                  'width': 854},
     'status': 'ready',
     'type': 'index_task_info',
     'updated_at': '2022-12-08T11:34:50.474Z',
     'video_id': '6391c8a669ff3402ec515aba'}



For details about the possible statuses, see the API Reference > Tasks page.