1

I'm trying to load a mp4 video stream from Django to Vue.js. I followed the solution here and got a byte string via my axios API which I concatenated to data:video/mp4;base64,, and then binded it to the video tag's :src property, but the video is not displaying. Is this the correct way to stream videos from Django 3 to Vue.js? What am I doing wrong?

Api.js code snippet:

import axios from 'axios'

export default () => {
    return axios.create({
        baseURL: `http://127.0.0.1:8000/`,
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
        }
    })
}

Video.vue component code snippet:

    methods: {
        async stream() {
            return await VideoService.stream(this.video)
            .then(function(data) {
                return data.data;
            });
        }
    },
    props: ['data'],
    watch: {
        data: {
            deep: true,
            immediate: true,
            handler(curr, prev) {
                this.video = curr;
                this.stream().then(data => {
                    data = Buffer.from(data, 'binary').toString('base64');
                    this.video = 'data:video/mp4;base64,'+data;
                });
            }
        }
    }

As suggested in the comments of that answer, I also set src to the Django api endpoint e.g. src="/video/test.mp4, but I can see in my terminal that it's not reaching that Django route. How do I get the linked solution to work with Vue.js?

Picture of the raw string I get back from Kevin's Django view: enter image description here

Another image when I convert to base 64 using Buffer: enter image description here

Soubriquet
  • 3,100
  • 10
  • 37
  • 52
  • Try ensuring your html is correct. See https://jsfiddle.net/45y3wtj0/. Are you able to re-create that video in your code? Then replace the `src` attribute with your server's endpoint url. – Kevin Lee Jun 10 '20 at 01:27
  • @KevinLee yup. that video link works with my vue code. – Soubriquet Jun 10 '20 at 01:30
  • Now check that your endpoint is correct. Using a tool like curl or Postman, are you able to successfully hit your Django endpoint? – Kevin Lee Jun 10 '20 at 01:35
  • @KevinLee yeah, works with postman. Displays my videos in the postman ui. – Soubriquet Jun 10 '20 at 01:50
  • Ok, then your error must be elsewhere – Kevin Lee Jun 10 '20 at 01:53
  • why does it not work when i set `src="localhost:8000/video/test.mp4"`? My vue app is running on port 8080 and Django on 8000. – Soubriquet Jun 10 '20 at 02:04
  • Try `src="http://localhost:8000/video/test.mp4"` – Kevin Lee Jun 10 '20 at 04:48
  • @KevinLee when I try `btoa(binary_string)` I get the following: `Uncaught (in promise) DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.` – Soubriquet Jun 10 '20 at 12:10
  • @KevinLee I also tried this example of setting `src` to base 64 string and it worked. https://base64.guru/converter/encode/video. I also updated the original post with an image of the string I get back from your code. Does it look correct? – Soubriquet Jun 10 '20 at 12:11
  • @KevinLee Ah! Sorry for all the confusion. I didn't include `http://` That works. Ugh. Thanks again for all the help! – Soubriquet Jun 10 '20 at 18:39

1 Answers1

1

The final solution needed to stream videos to Vue.js if you're using the same component for videos is to set the src tag using v-html so that you can set src dynamically. Directly doing src="http://localhost:8000/v/video.mp4" won't work once the component is created. So in addition to Kevin's code, just do the following in the video component:

<template>
    <div>
        <video v-html="src" autoplay="" controls="" loop="" muted="" frameborder="0">
            Your browser does not support HTML videos.
        </video>
    </div>
</template>

<script>
export default {
    data() {
        return {
            src: ''
        }
    },
    props: ['data'],
    watch: {
        data: {
            deep: true,
            immediate: true,
            handler(curr, prev) {
                this.src = '<source src="http://localhost:8000/v/"'+curr+' type="video/mp4">'
            }
        }
    }
}
</script>

<style scoped>
</style>
Soubriquet
  • 3,100
  • 10
  • 37
  • 52
  • If you're using a separate Nginx server for an api like in my other post (https://stackoverflow.com/a/63788052/3158028), you need to have `http://` before the api address e.g. `http://api.example.com` for it to hit that appropriate Nginx configuration to route to Gunicorn and then to your Django api. – Soubriquet Sep 08 '20 at 17:11