HTML 5 video and src value with vue - javascript

I have an HTML 5 video inside my page and I would like to set the src dynamically.
I'm using vue, inside my js controller I set a variable with the video path then I use the variable in my page as below:
<video width="450" controls>
<source v-model="controller.var" v-bind:src="var" type="video/mp4">
</video>
The player doesn't load the video but my var is properly set with the right url.
What I'm missing here?
Thanks

Adding the key attribute with the source's URL to the video element will cause both video and source to be updated when the URL changes:
<video
:key="video.mp4"
width="450"
controls
>
<source
:src="video.mp4"
type="video/mp4"
>
</video>
This supports dynamic replacement of a video + source.

First, I don't know if you are actually using var in your template, but if you are, Vue will throw a warning in the template.
avoid using JavaScript keyword as property name: "var" in expression :src="var"
Second, you cannot dynamically change the source element.
From the HTML5 specification,
Dynamically modifying a source element and its attribute when the
element is already inserted in a video or audio element will have no
effect. To change what is playing, just use the src attribute on the
media element directly, possibly making use of the canPlayType()
method to pick from amongst available resources. Generally,
manipulating source elements manually after the document has been
parsed is an unnecessarily complicated approach.
So, bind your data to the src attribute of the video element.
<video width="450" controls :src="video"></video>
console.clear()
new Vue({
el:"#app",
data:{
video: "https://www.w3schools.com/tags/movie.mp4"
},
methods:{
changeVideo(){
this.video = "http://techslides.com/demos/sample-videos/small.mp4"
}
}
})
<script src="https://unpkg.com/vue#2.2.6/dist/vue.js"></script>
<div id="app">
<video width="450" controls :src="video"></video>
<div>
<button #click="changeVideo">Change</button>
</div>
</div>

If you need to change the src dynamically, you can change the src and load the new src with the .load() function.
new Vue({
el:"#app",
data:{
src: ""
},
methods:{
changeVideo(newSrc){
this.$data.src = newSrc;
//Force video load.
var vid = this.$refs.video;
vid.load();
}
}
})
<script src="https://unpkg.com/vue#2.2.6/dist/vue.js"></script>
<div id="app">
<video width="450" controls :src="src" ref="video"></video>
<div>
<button #click="changeVideo('http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4')">Change1</button>
<button #click="changeVideo('https://www.w3schools.com/tags/movie.mp4')">Change2</button>
</div>
</div>

Try setting the entire source as variable in the controller.
<video controls autoplay>
{{{ src }}}
</video>
new Vue({
el: '#app',
data: {
src: '<source src="#url" type="video/mp4">'
}
})

Related

How can I remove this shadow-root custom button from an HTML video?

I have used a slide show on my web site. There are a couple of images and a video. I have not enabled any shadow elements or controls for this video, however there is a custom button to open it externally and I cannot disable it in any ways.
I have tried different JS scripts to attach a shadow and set the mode on closed, but I get the error that this video element cannot have an attached shadow.
Here's the button I am talking about
An example script that I have used:
function makeShadowTree(shadowClose) {
var root = shadowClose.attachShadow({mode: 'closed'});
}
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.slides--i').forEach(makeShadowTree);
});
<div class="slides">
<div class="slides--i" id="slide--1"></div>
<div class="slides--i" id="slide--2"></div>
<video autoplay muted loop class="slides--i" id="slide--video">
<source src="img/slides/slide-03-video.mp4" type="video/mp4">
</video>
</div>

vue.js: hero background video with self hosting (local) video file

What is the right way to create a hero background video in vue.js?
The following way doesn't work.
html:
<template>
<div id="hero">
<video playsinline autoplay muted loop poster="../assets/img/hero-1.jpg" id="bgvideo" width="1080" height="720">
<source :src="videoUrl" :type="videoType">
</video>
</div>
</template>
javascript:
<script>
export default {
name: 'SectionHome',
data() {
return {
videoUrl: '#/assets/videos/hero-1.mp4',
videoType: 'video/mp4'
}
},
};
</script>
I also tried to pass the file path directly to the html tag: <source src="#/assets/video.mp4" type="video/mp4">, but according to this issue this way doesn't work at all. By the way I have the same problem with vuetify <v-img ...>, passing local files doesn't work, whereby <img ...> does work.
To solve passing local files in Vuetify you just need to add require to your src
From Vuetify :
Vue loader converts relative paths into require functions automatically for you. Unfortunately, this is not the case when it comes to custom components. You can circumvent this issue by using require. If you're using Vuetify as a Vue-CLI 3 plugin, you can edit your project's vue.config.js file by modifying the options for vue-loader.
Incorrect
<v-img src="../path/to/img" />
Correct
<v-img :src="require('../path/to/img')" />
You can also do the same with <source :src="require('#/path/to/video')">
<video playsinline autoplay muted loop poster='#/assets/img/hero-1.jpg'>
<source :src='require("#/assets/videos/hero-1.mp4")' type='video/mp4'>
</video>

Updating source URL on HTML5 video with React

I want to update the source tag in a HTML5 video element so that when I click a button, whatever's playing switches to a new video.
I have a Clip component that returns an HTML5 video element, with the source URL provided via props.
function Clip(props) {
return (
<video width="320" height="240" controls autoPlay>
<source src={props.url} />
</video>
)
}
I also have a Movie component, which contains multiple URLs, each corresponding to a section of the movie. It also contains a position attribute, which acts like an iterator by remembering which section is currently playing.
class Movie extends Component {
constructor() {
super();
this.state = {
sections: [
'https://my-bucket.s3.amazonaws.com/vid1.mp4',
'https://my-bucket.s3.amazonaws.com/vid2.mp4'
],
position: 0
};
}
render() {
const sections = this.state.sections
const position = this.state.position
return (
<div>
{position}
<Clip url={sections[position]} />
<button onClick={() => this.updatePosition()}>Next</button>
</div>
)
}
updatePosition() {
const position = this.state.position + 1;
this.setState({ position: position });
}
}
The Movie component renders a Clip component and a "Next" button. When the Next button gets clicked, I want to update the position attribute and re-render the HTML5 video element using the next URL from sections.
As of now, when I hit Next the HTML5 video source tag updates, but the element continues playing the video from the previous URL. Can anyone help me figure out how to reset the video element?
Update: I created a JSFiddle, which you can see here.
Update 2: Updating the src attribute on the video element works!
Quick and dirty awnser: Add a key prop to <Clip> or <video>, e.g.:
function Clip({ url }) {
return (
<video key={url}>
<source src={url} />
</video>
);
}
Recommended awnser: Trigger a load event for the video element whenever there's a new URL, e.g.:
function Clip({ url }) {
const videoRef = useRef();
useEffect(() => {
videoRef.current?.load();
}, [url]);
return (
<video ref={videoRef}>
<source src={url} />
</video>
);
}
Explanation: The video initially doesn't change because in essence you're only modifying the <source> element and React understands that <video> should remain unchanged, so it does not update it on the DOM and doesn't trigger a new load event for that source. A new load event should be triggered for <video>.
The dirty answer works because when you change the key of a React element, React understands that's a whole new element. It then creates a new element in the DOM which naturally will have its own load event triggered on mount.
Changing the src of <source /> doesn't seem to switch the video for some reason. This isn't a react issue I don't think. Probably just how <source /> works. Maybe you have to call .load() on the element again. But it's just easier to set it directly on the element itself.
See the comment to the top answer: Can I use javascript to dynamically change a video's source?
You can set src directly on element instead:
function Clip(props) {
return (
<video width="320" height="240" src={props.url} controls autoPlay>
</video>
)
}
Bind the URL in the src property of Video tag and not Source Tag
<video autoplay loop muted playsinline="true" webkit-playsinline="true" [src]="videoSrc" type="video/mp4">
Add a parent div to second video
My code:
{isMobile ? (
<video
autoPlay={true}
loop
className="moviles"
muted
playsInline
poster="/totto/kids.png"
>
<source src="/totto/losmoviles.webm"></source>
<source src="/totto/losmoviles.mp4"></source>
</video>
) : (
<div>
<video
autoPlay={true}
loop
className="moviles2"
muted
playsInline
poster="/totto/portada.jpg"
>
<source src="/totto/moviles.webm"></source>
<source src="/totto/moviles.mp4"></source>
</video>
</div>
)}
You can use the key attribute :
<video key={videoUrl} autoPlay width="100%">
<source src={videoUrl} type="video/mp4"></source>
</video>
If the video's key attribute change, the video component will be re-mounted

Injected video src attribute via javascript not appearing

I have a popup that contains a video with empty source attributes.
<div id="event-popup">
<video width="320" height="240" controls id="event-popup-video">
<source src="" type="video/mp4" id="epv-mp4"></source>
<source src="" type="video/ogg" id="epv-ogg"></source>
</video>
</div>
This is used for multiple Leaflet map markers the a user can click on, which will trigger the popup to appear and then inject the correct src attribute based on the id of the clicked item.
var marker = L.marker(new L.LatLng(a.lat, a.lon), {
alt: a.cartodb_id,
icon: starIcon,
clickable: true
}).on('click', onClick);
The onClick function displays the popup and injects the correct src file location (S3 bucket item) into the .
function onClick(e){
// other code to display popup
showChangeEventVideo(e.target.options.alt);
}
function showChangeEventVideo(id){
$("#epv-mp4").attr("src", "s3_URL_based_on_ID.mp4");
$("#epv-ogg").attr("src", "s3_URL_based_on_ID.ogg");
}
The code executes, displays the popup, and inserts the correct src URL into the , but doesn't show the video. I can hard code a video URL into the HTML src attribute and the video appears.
Simply need to add .load() at the end of each .attr() call to force the source to refresh itself.

Change data-src to src via jquery

Im using a flexslider that has audio files for each slide, but I don't want to load countless audio files right away on the page. So im trying to get the data-src to become the src after each slide
the slides are currently as follows:
<div class="flexslider carousel">
<ul class="slides">
<li>
<img src="http://www.quinnmedical.com/skin/frontend/gigasavvy/quinn/ppt/Slide01.jpg" />
<audio id="demo" controls>
<source src="/skin/frontend/gigasavvy/quinn/audio/Slide1.mp3" type="audio/mpeg" />
</audio>
</li>
<li>
<img src="http://www.quinnmedical.com/skin/frontend/gigasavvy/quinn/ppt/Slide03.jpg" />
<audio id="demo" controls>
<source data-src="/skin/frontend/gigasavvy/quinn/audio/Slide3.mp3" src="" type="audio/mpeg" />
</audio>
</li>
</ul>
</div>
In the after function i want to change data-src to src. Any help would be greatly appreciated as how to go from data-src to src
Renaming an attribute is not be possible. You can add new attribute and remove the old one.
Suppose there is a click event as in the following example:
$('#demo').on("click", "img", function () {
var t = this;
var source = $(t).children("source");
$source.attr({
src: $t.attr('data-src')
}).removeAttr('data-src');
}
Please modify the event according to your requirements.
Try this:
$('source').attr("src", $(this).data('src'));
$('source').removeAttr('data-src');
This should move the url from data-src to src, and then remove the data-src attribute.
Inside the after function get the currently visible slide and then get the auto on it and it's source. Next check to see if it already has a src attribute. If not then set it to it's own .data('src'). Add this into the flexslider object.
after: function(){
var $currentAudio = $('.flex-active-slide audio source');
if(!$currentAudio.attr('src')){
$currentAudio.attr('src', $currentAudio.data('src'));
}
}

Categories