How to stream a local file into a real-time video call
Tags: javascript, webdev, tutorial, webrtc
Published: 2021-04-16 21:41:39

We've joined a lot of video calls over the last year here at Daily. While it’s easy to chat in real-time with someone on the other side of the world, streaming a video to watch simultaneously as part of that conversation quickly complicates things. We’ve all been in meetings, training sessions, discussion groups, and even catch ups with friends where lags and buggy streams make it impossible to watch a video at the same time. 

With great frustration comes great experimentation, and we’ve come up with a quick hack for streaming local video files during our calls: using the Daily API [startScreenShare()](https://docs.daily.co/reference#%EF%B8%8F-startscreenshare?utm_source=dev&utm_campaign=stream-local-video) method. 

This tutorial covers our workaround! We’ll go over uploading the local file and creating a stream from it, sharing that stream, and making sure that our hack is working. 

If you’re looking to implement this feature in your own [embedded prebuilt UI](https://docs.daily.co/docs/embed-the-daily-prebuilt-ui?utm_source=dev&utm_campaign=stream-local-video) or [Daily call object](https://docs.daily.co/docs/build-a-custom-video-chat-interface#daily-call-object?utm_source=dev&utm_campaign=stream-local-video) video app, you can add to your own code as we go. Or, if you want to fiddle with a working prototype, download [our gist](https://gist.github.com/kimberleejohnson/97ef1f01ea8cb63625cdd588b07003b5?utm_source=dev&utm_campaign=stream-local-video) and [create a Daily room](https://docs.daily.co/docs/create-and-manage-rooms-with-the-rest-api?utm_source=dev&utm_campaign=stream-local-video) if you don’t have one already. 

## Before we get started

We put it in the title and we mean it: this is a hack. It’s a workaround, not meant for production, but for low stakes, internal use cases. Somebody may or may not have debuted it by sneaking [mom’s spaghetti](https://www.youtube.com/watch?v=_Yhyp-_hX2s) into a Daily all hands. 

As with any hack, it also comes with a few caveats:  
* If you’ll be using Chrome, you’ll need to [disable hardware acceleration](https://www.lifewire.com/hardware-acceleration-in-chrome-4125122) before you share a video stream. 

* Unfortunately, this solution doesn’t work for streaming video from Safari, because Safari doesn’t support [captureStream()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/captureStream).  

With that, here we go here’s our shot, feet fail us not. 

## Upload the local video file and create a stream  

We need an `<input>` element with three attributes to upload the video: 

1. `id`: so that we can use [`document.getElementById`](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById)
2. [`type`](https://www.w3schools.com/tags/att_input_type.asp): to specify that this input field is for a file upload. 
3. [`accept`](https://www.w3schools.com/tags/att_input_accept.asp): to make sure the uploaded file is a video. 

```html 
<input id="vid-file-picker" type="file" accept="video/*"" />
```

We add an event listener to the `<input>`. On [`'change'`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event), we call our function `playLocalVideoFile()`: 

```javascript
let videoInput = document.getElementById('vid-file-picker'), callObject;
videoInput.addEventListener('change', playLocalVideoFile, false);
```

`playLocalVideoFile()` creates a video stream from the file using [captureStream()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/captureStream) or mozCaptureStream() if you’re using FireFox.

```javascript
function playLocalVideoFile(evt) {
   let videoEl = document.getElementById('local-vid');
   let file = this.files[0];
   let type = file.type;
   if (!videoEl.canPlayType(type)) {
     alert('cannot play that file');
     return;
   }
   videoEl.src = URL.createObjectURL(file);
   videoEl.play().then(() => {
   // Mozilla currently prefixes the function name, so we have to check for either
   if (typeof videoEl.mozCaptureStream == 'function') { 
      window.localVideoStream = videoEl.mozCaptureStream();
      } else if (typeof videoEl.captureStream == 'function') {
          window.localVideoStream = videoEl.captureStream();
      }
    });
}
```

Now that we have the stream, we can share it. 

## Share the stream with call participants 

We add a `<button>` to `shareVideo()` through the screen share stream. 

```html
<button onclick="shareVideo()" />share video through screenshare stream</button>
```

`shareVideo()` calls the Daily [startScreenShare()](https://docs.daily.co/reference#%EF%B8%8F-startscreenshare?utm_source=dev&utm_campaign=stream-local-video) method on the [Daily call object](https://docs.daily.co/docs/build-a-custom-video-chat-interface#daily-call-object?utm_source=dev&utm_campaign=stream-local-video), passing the `localVideoStream` created via `playLocalVideo()` as the media stream to be shared: 

```javascript
async function shareVideo() {
    callObject.startScreenShare({ mediaStream: localVideoStream });
}
```

## Test the stream 

Make sure you have a [Daily room URL](https://docs.daily.co/docs/create-and-manage-rooms-with-the-rest-api?utm_source=dev&utm_campaign=stream-local-video) ready. We hardcoded ours as a `const` in our html file because, again, this is a hack. Relatedly, if you’re using Chrome, don’t forget to [disable hardware acceleration](https://www.lifewire.com/hardware-acceleration-in-chrome-4125122). 

Next, open the file in your browser. In a new tab, visit your Daily room URL. You should see two participants in the room tab, but just you in the file tab. 

Click "Choose File" and upload the local video of your choice. If you need inspiration for what file to choose, try searching on [Pexels](https://www.pexels.com/videos/) for puppies (that’s what I did). Finally, click “share video through screen share stream” and in the tab with the room URL you should see the video coming through. 

![gif shows video call where video of a puppy plays on the biggest video stream ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/niayloktucxucyxv477i.gif)

## Snap back to reality (what’s next) 

That’s it! Thanks for reading. We hope this makes sharing videos for everyone to watch on your calls easier. Let us know in the comments!

And, if you’re interested in building more apps that are all about sharing and streaming content, our [webinar series](https://www.daily.co/blog/webinartc-building-a-webinar-app-with-react-and-daily-prebuilt-ui/?utm_source=dev&utm_campaign=stream-local-video) might spark some ideas.