Daily.co API server-side (rtp tracks) recording

How to use server-side recording with the Daily.co video call API

Our API gives you the option to add video call recording to your meetings. For many of our API customers, recording is critical to their use case. You can read more about recording in our [developer docs](https://docs.daily.co/reference#recordings).

For developers and product teams with more advanced recording needs, we’ve released a new option. That is: server-side recording that allows developers to manage individual media tracks.

- If you are using this new server-side recording feature, Chrome is no longer required. Recording is supported on Chrome, Safari, iOS Safari and Android Chrome.
- If you **are not** using rtp-tracks, Chrome is still required for recording.

We wrote the first section below for both developers and non-technical readers. If you’re a developer looking for sample code, jump to the implementation section.

## Which recording feature should your team use?

We now offer a couple options: (1) our drop-in recording feature and (2) server-side recording.

Please keep in mind any kind of recording, with the API, requires you to upgrade your API plan. [See our API pricing](https://www.daily.co/api/pricing).

### Option 1

Because our goal is to make integrating video calls as easy as possible, the Daily.co API has a quick option to turn on recording.

Once you’ve upgraded, simply enable recording using the `enable_recording` configuration property, with a meeting token. [Please see our docs](https://docs.daily.co/reference#recordings) for more details.

- Recording is part of the video chat widget UI
- With this simple approach, users do have to use Chrome to record
- You can save recordings locally or to the cloud

### Option 2

We now have added the second option of server-side recording. This means a local client is not involved in compositing the recording:

- Developers can manage individual media tracks
- Chrome is not required if you are using rtp-tracks as described below. Sessions can be recorded from Chrome, Safari, iOS Safari and Android Chrome.
- Composting is **currently in beta**

Server-side recording is great for use cases like:

- High-quality audio transcription
- Media production (podcasts and video blogs)
- Recording meetings that include mobile devices — mobile devices often aren't powerful enough to record and composite locally

The rest of this post is rather detailed, and geared towards engineers. If you have any questions about our recording offering, just [reach out](https://www.daily.co/contact-us).

## Developers: how to implement server-side recording

**Note: Please note composting is currently in beta.**

1. Create a room with `enable_recording` property set to `rtp-tracks`
2. Start a recording using the front-end library's `startRecording()` method
3. Stop the recording using the front-end library's `stopRecording()` method
4. Get info for the recording, from the REST API `/recordings` endpoint
5. Create a compositing "recipe" using the track ids from the recording info struct, and POST the recipe to `/recordings/:recording_id/composites` REST API endpoint
6. Get info for the new composited video from the REST API `/recordings/:recording_id/composites`
7. Download the recording via the `download_url` in the composited video's info struct

## 1. Create a room set to record

To get started you will want to create a room set to record, using the new `rtp-tracks` recording type. Here's an example:

    -- CODE language-bash --
    curl -H "Content-Type: application/json" -H "Authorization: Bearer $API_KEY" -d '{"properties":{"enable_recording":"rtp-tracks"}}' 'https://api.daily.co/v1/rooms)'

You can also set the `enable_recording` property to `rtp-tracks` on an existing room.

## 2. Use the daily-js front-end library to start and stop recording

To start and stop a recording you'll want to use the following instance methods: `startRecording()` and `stopRecording()`. Check out our [front-end docs](https://docs.daily.co/reference#using-the-dailyco-front-end-library) for more details.

## 3. Get the recording's track info

Here's how you can get the info struct for the latest recording from a specific room:

    -- CODE language-bash --
    curl -H "Content-Type: application/json" -H "Authorization: Bearer $API_KEY" 'https://api.daily.co/v1/recordings/?room=qz2gz0IkrwPUtGjwx41h&limit=1'

Please note that the info struct will be available a few seconds after the recording starts, but `status` will be set to `in-progress` and the `tracks` array will be empty. The `tracks` array will be populated about 30 seconds after the recording is stopped.

Example struct:

    -- CODE language-json --
   {
     "total_count": 3,
     "data": [
       {
         "id": "cb4f904e-9a4c-4603-8b87-1489b84e6d6f",
         "room_name": "qz2gz0IkrwPUtGjwx41h",
         "start_ts": 1574041799,
         "status": "finished",
         "max_participants": 1,
         "duration": 26,
         "share_token": "gBhvoLgc0nsn",
         "tracks": [
           {
             "id": "254829fb-9031-4ed5-d5db-536013e49581",
             "download_url": "/v1/recordings/cb4f904e-9a4c-4603-8b87-1489b84e6d6f/track/254829fb-9031-4ed5-d5db-536013e49581.webm",
             "size": 104262,
             "track_start_ts": "1574041800.133000",
             "track_end_ts": "1574041824.573000",
             "duration": 24.44000005722046,
             "resolution": "",
             "session_id": "e6269475-0058-4aeb-f984-a12f44537d03",
             "media_tag": "cam-audio",
             "type": "audio",
             "user_name": "Test User Name",
             "user_id": ""
           },
           {
             "id": "cbd4e7fa-eecd-4297-d676-6ce379afafa2",
             "download_url": "/v1/recordings/cb4f904e-9a4c-4603-8b87-1489b84e6d6f/track/cbd4e7fa-eecd-4297-d676-6ce379afafa2.webm",
             "size": 1897322,
             "track_start_ts": "1574041800.144000",
             "track_end_ts": "1574041824.463000",
             "duration": 24.319000005722046,
             "resolution": "1280x720",
             "session_id": "e6269475-0058-4aeb-f984-a12f44537d03",
             "media_tag": "cam-video",
             "type": "video",
             "user_name": "Test User Name",
             "user_id": ""
           }
         ]
       }
     ]
   }

## 5. Create a "recipe" for a composited video (beta)

Using the information about the recording's tracks, you can create a json data structure that describes which tracks to include in the composited video and how to size and position the video tracks.

Here's an example recipe:

    -- CODE language-json --
    {
      "composite_mode": "tracks-layout",
      "size": "1280x720",
      "tracks": [
        { "id": "df12a81d-2be5-49d5-97d5-c7d5de00d794" },
        {
          "id": "1b0956df-67c6-4f37-ee59-fe3ad7cc7909",
          "size": "1280x720",
          "position": "0x0"
        }
      ]
    }

### Required fields

- `composite_mode`  must be set to `tracks-layout`
- `size` is the size (resolution) of the video you are creating. It must be a string in the format "WIDTHxHEIGHT"
- `tracks` is a list of tracks to include in the video. Audio tracks are easy — just give the track `id`. Video tracks require an `id`, `size`, and `width`.
   - `size` is the size, in pixels, to scale this video track to. Note that you'll need to make sure you give a size that doesn't distort the video's aspect ratio (which means you'll need to use the `resolution` values from the track info).
   - `position` is where to place the video track within the overall video canvas. Specify this as the top, left corner of this track, relative to the top/left of the of the canvas.

### Optional fields

- `title` the new video's "title" metadata
- `duration` create a new video this many seconds long. This is useful for doing quick trial-runs of recipes.
- `background_color` set the background color to something other than black. See here for color options: [https://ffmpeg.org/ffmpeg-utils.html#Color](https://ffmpeg.org/ffmpeg-utils.html#Color)

### Example POSTing of a recipe

This curl command POSTs a json recipe from the file `comp-recipe.json` in the current directory.

    -- CODE language-bash --
    curl -H "Content-Type: application/json" -H "Authorization: Bearer $API_KEY" --data "@comp-recipe.json"  .     'https://api.daily.co/v1/recordings/3ab6318e-bd2d-4d9d-837a-a3a36ae7b58b/composites'

The API endpoint returns a composite video id:

    -- CODE language-json --
    {    
      "status": "in-progress",
      "id": "500856c9-5d52-427f-cdf9-56fc0fd2d483"
    }

### One composite allowed per room

Please note that you are allowed to have only one compositing process happening at a time for each room.

If you try to start another compositing process for room, without letting the previous one finish, you'll get an API response that looks like this:

    -- CODE language-json --
    {
      "error": "invalid-request-error",
      "info": "another compositing process is already running"
    }

The compositing happens faster than real-time, but can still take several minutes per video.

**Also, we only save one composited video per room. If you run the compositing process again, your new video will overwrite the previous one.**

## 6. Getting results and errors of the most recent compositor run

When the compositing process is finished, information about the most recent video is available from the `/recordings/:recording_id/composites` API endpoint.

Running this curl command ...

    -- CODE language-bash --
    curl -H "Content-Type: application/json" -H "Authorization: Bearer $API_KEY" 'https://api.daily.co/v1/recordings/3ab6318e-bd2d-4d9d-837a-a3a36ae7b58b/composites'

... gives this output:

    -- CODE language-json --
    {
      "newest_composite": {
     "id": "500856c9-5d52-427f-cdf9-56fc0fd2d483",
      "upload_ts": "2019-11-18T02:21:24.000Z",
      "download_url": "/v1/recordings/3ab6318e-bd2d-4d9d-837a-a3a36ae7b58b/composites/500856c9-5d52-427f-cdf9-56fc0fd2d483.mp4"
      },
      "current_error": null
    }

If an error had happened during the most recent compositor run, the `current_error` field will include as much information as we have about the error (in the form of a multi-line string of text).

## 7. Download the recording

Use the `download_url` to fetch the video file:

    -- CODE language-bash --
    curl -L -H "Authorization: Bearer $API_KEY" 'https://api.daily.co/v1/recordings/3ab6318e-bd2d-4d9d-837a-a3a36ae7b58b/composites/00856c9-5d52-427f-cdf9-56fc0fd2d483.mp4' > video.mp4

---

As mentioned at the top of the post, Compositing is currently in beta. We are eager to learn from developers using our API. If you encounter any bugs, or simply have some questions, just [contact us](https://www.daily.co/contact-us). We do our best to respond as swiftly as possible! Thanks for reading.

Photo by [Florian Krumm](https://unsplash.com/@floriankrumm?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/server?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)

Recent posts