Transcoding and Live-streaming with Mux

How we use Mux.com to transcode and stream video call recordings in the cloud

With the Daily.co API, you can [enable recording](https://docs.daily.co/reference#recordings) for any video call. However, we don't directly support cloud transcoding or adaptive streaming. Instead, we suggest that you consider using the terrific [Mux Video APIs](https://www.mux.com/).

# Simple and affordable recording

When we designed our recording feature set, our number one goal was to make video call recording both easy and affordable. We want to make all kinds of new video call workflows and use cases possible!

You can configure call recording in several different ways:  

- You can save recordings directly to local disk, or
- Save recordings in the cloud in real time, and
- Start recording automatically when a specific user joins a call

Local recording is completely free. Cloud recording is $0.015 per minute, no matter how many people are participating in the call. (So making a half-hour long cloud recording costs $0.45.)

# Sending recording files to Mux

[Mux](https://www.mux.com/) is an API-first video platform, built by a team with deep experience optimizing video for streaming.

With a single API call you can [send a video file](https://docs.mux.com/reference#create-an-asset) to Mux. After the video file is transcoded and turned into a MUX `asset`, you can [play the video back on any platform](https://docs.mux.com/docs/playback), or [retrieve mp4 versions](https://docs.mux.com/docs/mp4-support) of the video.

[](https://www.notion.so/24537090b6da48dd89fc54426f06d4f3#1a963bb4fdac4622aa8517f689894250)

Here's sample code to send a Daily.co cloud recording straight to Mux.

   -- CODE language-bash --
   # let's grab our most recent cloud recording's share_token
   # and make a download link to pass to Mux
   SHARE_TOKEN=`curl -H "Authorization: Bearer $DAILY_API_KEY" \
     https://api.daily.co/v1/recordings | jq -r '.data[0].share_token'`
   DL_LINK="https://api.daily.co/v1/recordings/$SHARE_TOKEN/download"
   
   # sanity check
   echo $DL_LINK
   
   # create a Mux asset
   curl https://api.mux.com/video/v1/assets \
     -H 'Content-Type: application/json' \
     -u "$MUX_ACCESS_TOKEN:$MUX_SECRET_KEY" \
     -d '{ "input": "'$DL_LINK'",
           "playback_policy": ["public"],
           "mp4_support": "standard" }'

Mux will transcode the video to a high-quality "mezzanine" format, and to mp4 as well. Here's what the asset data structure looks like once Mux's `preparing` phase is finished.

   -- CODE language-bash --
   # retrieve info about your most recently created Mux asset
   curl https://api.mux.com/video/v1/assets?limit=1 \
        -H 'Content-Type: application/json' \
        -u "$MUX_ACCESS_TOKEN:$MUX_SECRET_KEY" | jq '.'

    

   -- CODE language-json --
   {
     "data": [
       {
         "tracks": [
           {
             "type": "video",
             "max_width": 1280,
             "max_height": 720,
             "max_frame_rate": -1,
             "id": "Ih5PynkzFB9wiaY1vek00zJCzzjumsSm4"
           },
           {
             "type": "audio",
             "max_channels": 1,
             "max_channel_layout": "mono",
             "id": "GCiGs02V3c01kQVs8B9C1UG4gkqWU1LSQao2TifzIBwvI"
           }
         ],
         "status": "ready",
         "static_renditions": {
           "status": "ready",
           "files": [
             {
               "width": 640,
               "name": "low.mp4",
               "height": 360,
               "filesize": "3983487",
               "ext": "mp4",
               "bitrate": 196504
             },
             {
               "width": 960,
               "name": "medium.mp4",
               "height": 540,
               "filesize": "7453191",
               "ext": "mp4",
               "bitrate": 367672
             },
             {
               "width": 1280,
               "name": "high.mp4",
               "height": 720,
               "filesize": "12288116",
               "ext": "mp4",
               "bitrate": 606184
             }
           ]
         },
         "playback_ids": [
           {
             "policy": "public",
             "id": "vb1ABJ02Xg5YY1Id1NPu3FECJp800W2bwF"
           }
         ],
         "mp4_support": "standard",
         "max_stored_resolution": "HD",
         "max_stored_frame_rate": -1,
         "master_access": "none",
         "id": "nzbD9qK77Lq00ayVSBcOt8sKDaPNhx4BA",
         "duration": 162.19,
         "created_at": "1552939217",
         "aspect_ratio": "16:9"
       }
     ]
   }

Using the `playback_ids[0].id`, you can link to this video as an [adaptive HLS stream](https://docs.mux.com/docs/playback) that will give your users the highest quality possible playback on every network and device. An HLS playback link looks like this:

   -- CODE language-html --
   https://stream.mux.com/{PLAYBACK_ID}.m3u8

You can also download or link to one of the `static_renditions` of the video, if you need an [mp4 version](https://docs.mux.com/docs/mp4-support). An mp4 download/playback link looks like this:

   -- CODE language-html --
   https://stream.mux.com/{PLAYBACK_ID}/{MP4_FILE_NAME}

Mux offers lots more functionality! To get started, create a Mux account and API Access Tokens as described in [this tutorial](https://docs.mux.com/docs/video).

# Under the covers — using the HTML MediaRecorder API

We made some very specific engineering trade-offs when we designed the Daily.co recording feature set.

We want to make both local and cloud recording as affordable as possible. And we also want you to be able to do anything you can imagine with your recordings.

To create recordings, we use the [HTML MediaRecorder](https://developers.google.com/web/updates/2016/01/mediarecorder) API. A recording is composited and rendered locally, in a background process, by the web browser of the call participant who started the recording. For local recording, we simply write the file to disk when the recording is stopped. For cloud recording, we stream the file up to our storage servers in real time during the call.

The code to make in-browser recording work robustly is a little bit tricky. (We did a *lot* of testing and debugging and had a months-long beta before we were completely satisfied with our recording implementation. We worked closely with Mux's engineers during our beta.)

Now that we have rock solid in-browser recording we can price cloud recording at a *much more affordable* per-minute cost than other API providers do.

But there are some limitations of this approach:

- You can only create recordings using desktop Chrome. (This will change, soon, though. Apple has announced Safari support for MediaRecorder.)
- The client who is creating the recording needs to have enough CPU available to encode the recording in a background process, and — for cloud recording — needs to have enough upstream network available to send the recording to our servers in real time.
- The recording files are not optimized for online streaming and interactive playback.

That last limitation is a big one. Fortunately, Mux enables streaming, playback, and transcoding with a simple API and a proven cloud infrastructure. We've been working with Mux since we first started developing our recording feature set, and the existence of Mux's solution was critical to our ability to ship affordable, flexible meeting recording.

If your video recording use case is mostly archival, then you can record large amounts of Daily.co video at a low cost.

If your video use cases involve streaming, you can send video files directly to Mux from Daily.co and deliver video to anyone, anywhere in the world, at the highest possible quality.

Recent posts