HTML5 video player won't load .vtt subtitle track - html5-video

I'm trying to add a subtitle track to a video and I can't figure out why it isn't working correctly. Here is my HTML:
<video controls>
<source src="../assets/video/sample.mp4" type="video/mp4" />
<track
src="../assets/video/sample.vtt"
kind="subtitles"
srclang="en"
label="English"
/>
</video>
And here is my .vtt file:
WEBVTT
00:00:00.500 --> 00:00:02.000
The Web is always changing
00:00:02.500 --> 00:00:04.300
and the way we access it is changing
Problem:
When I run my website locally the video will load, but when I click on the closed captions button and select English, there is a console error that reads:
GET http://localhost:8080/assets/video/sample.vtt 404 (Not Found).
If I deploy the website and run it from the server instead, selecting the English subtitle track doesn't display any errors, but...
The subtitles don't appear on the video.
The Closed Captions button is removed from the video player controls on Chrome.
In other browsers, the Closed Caption button remains, but everything else is identical.
If I check the Network tab in Chrome dev tools, I can see that the request was made for sample.vtt at the correct request URL and returned a 200 status code.
The odd thing is that when I look at the response for that request, instead of seeing the text of the .vtt file, it shows the full text of my website's index.html file, which is located in an entirely separate folder.
I'm not sure why this is happening, and it seems like this should be a relatively simple thing to set up, so I can't figure out what's going wrong.

This ended up being an issue with Webpack. This app is in Vue, so I added the following options under the "vue" rule in vue.config.js, and it worked:
config.module
.rule("vue")
.use("vue-loader")
.loader("vue-loader")
.tap((options) => {
options.transpileOptions = {
transforms: {
dangerousTaggedTemplateString: true,
},
};
options["transformAssetUrls"] = {
video: ["src", "poster"],
source: "src",
img: "src",
image: ["xlink:href", "href"],
use: ["xlink:href", "href"],
"b-embed": ["src", "poster"],
track: "src",
};
return options;
});
config.module
.rule("media")
.test(/\.(vtt|mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/);

Related

Access to image has been blocked by CORS only on Windows

Vue component has a photo block and the "edit" button.
<template>
<div>
<tui-image-editor ref="editor" > </tui-image-editor>
<div class="">
<img :src="img">
<button #click="edit()">Edit</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
img: "cdn.domain.shop/eaa49b02e350627622904290a83599d6.png",
};
},
methods: {
edit() {
this.$refs.editor.invoke("loadImageFromURL", this.img, "Editable image");
},
},
};
</script>
As a photo editor, I use TUI image editor. In the click handler, I pass the url to the editor by loadImageFromURL function
when I click the "edit" button in Chrome in Windows I get an error
Access to image at
'cdn.domain.shop/eaa49b02e350627622904290a83599d6.png' from origin
'example.org' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
But when I do the same thing in Chrome in Ubuntu, everything works fine.
What am I doing wrong?
just add random string to url
this.$refs.editor.invoke("loadImageFromURL",this.img+'?'+Math.random(), "Editable image");
the error was due to caching in the browser
After that you have to make sure that every URL you request from Chrome and Safari uses http:// instead of https://. HTTPS retrieval will not work in these browsers at all.
some allows both http and https requests I solved it with a small regular expression that replaced our https URL string with http.
What's the quick solution ?
Add the attribute crossorigin="anonymous" in the <img> tag that displays the image before opening it in the editor.
ie: <img src="targetUri" crossorigin="anonymous" />
Explain the issue and solution
The main issue is related to caching and how the browser send the Origin header.
First you have to know that by default the browser does not send the Origin header when you load an image with the <img> tag that does not have the crossorigin="anonymous" attribute.
More info
What's happening is that the browser tries to load the image from the <img> tag before the image editor is opened, and the puts it into its cache.
So when you open the editor, it tries to load the image a second time, and you actually get a cached response of the first request that was made without the Origin header. Without this header, that cached response does not contain all the allow-control-* headers necessary to pass the CORS check, that why you get the error.
You can check this, by opening Chrome's inspector with "disable cache" checked. It should work.
The previous posts that suggested to include a parameter ?t=<random_number> had the effect to bypass the browser cache, but this solution is not possible when using pre-signed urls.
So adding crossorigin="anonymous" in the img tag should solve the problem.

Videojs can't play m3u8 blob URL

I am using Videojs version 7.6.6. It will not play a html5 video if the src is a blob URL. It will load the video time however, but will not play. I get this warning, and then it loads forever:
VIDEOJS: WARN: Problem encountered with the current HLS playlist. Trying again since it is the only playlist.
This is the way my code runs:
<video id="my_video" class="video-js vjs-matrix vjs-default-skin vjs-big-play-centered" controls
preload="none" width="640" height="268" data-setup="{}"></video>
<script type="text/javascript" src="/js/video-766.min.js"></script>
<script>
fetch("https://server/hls/index.m3u8").then(result => result.blob())
.then(blob => {
var blobURL = URL.createObjectURL(blob);
var player = videojs("my_video");
player.src({ src: blobURL, type: "application/x-mpegURL" });
}
);
</script>
If I try it without a blob, just a regular URL to the index.m3u8 file, then it works. So this is a problem with the creation of the blob URL I think. This works, the video starts playing:
<video id="my_video" class="video-js vjs-default-skin" height="360" width="640" controls preload="none">
<source src="https://server/hls/index.m3u8" type="application/x-mpegURL" />
</video>
<script>
var player = videojs('my_video');
</script>
I have searched for this issue and found a lot, but none of it helps me. Am I creating the blob wrong?
The object URL that is generated for the blob will start with file:// protocol if I'm not wrong. Browsers doesn't let you load data with file:// URL. I ran into a similar problem so I created a simple server on my app which returns the requested file over https:// .
The reason why your index.m3u8 is running because it is served over https protocol

constant spin loading but no image popping up - colorbox

When clicking the links, I get the popup box as expected however the images won't load, it just spins and spins. all the paths are ok as far as I can see.
HTML:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<link rel="stylesheet" href="colorbox/colorbox.css" />
<script src="colorbox/jquery.colorbox.js"></script>
<p><a class="group1" href="http://www.paycoservices.co.uk/colorbox/content/ohoopee1.jpg" title="Me and my grandfather on the Ohoopee.">Grouped Photo 1</a></p>
<p><a class="group1" href="http://www.paycoservices.co.uk/colorbox/content/ohoopee1.jpg" title="On the Ohoopee as a child">Grouped Photo 2</a></p>
<p><a class="group1" href="http://www.paycoservices.co.uk/colorbox/content/ohoopee1.jpg" title="On the Ohoopee as an adult">Grouped Photo 3</a></p>
JS
$(document).ready(function(){
//Examples of how to assign the Colorbox event to elements
$(".group1").colorbox({rel:'group1'});
$(".group2").colorbox({rel:'group2', transition:"fade"});
$(".group3").colorbox({rel:'group3', transition:"none", widt h:"75%", height:"75%"});
$(".group4").colorbox({rel:'group4', slideshow:true});
$(".ajax").colorbox();
$(".youtube").colorbox({iframe:true, innerWidth:640, innerHeight:390});
$(".vimeo").colorbox({iframe:true, innerWidth:500, innerHeight:409});
$(".iframe").colorbox({iframe:true, width:"80%", height:"80%"});
$(".inline").colorbox({inline:true, width:"50%"});
$(".callbacks").colorbox({
onOpen:function(){ alert('onOpen: colorbox is about to open'); },
onLoad:function(){ alert('onLoad: colorbox has started to load the targeted content'); },
onComplete:function(){ alert('onComplete: colorbox has displayed the loaded content'); },
onCleanup:function(){ alert('onCleanup: colorbox has begun the close process'); },
onClosed:function(){ alert('onClosed: colorbox has completely closed'); }
});
$('.non-retina').colorbox({rel:'group5', transition:'none'})
$('.retina').colorbox({rel:'group5', transition:'none', retinaImage:true, retinaUrl:true});
//Example of preserving a JavaScript event for inline calls.
$("#click").click(function(){
$('#click').css({"background-color":"#f00", "color":"#fff", "cursor":"inherit"}).text("Open this window again and this message will still be here.");
return false;
});
});
and a jsfiddle http://jsfiddle.net/Kuaet/2/
Chrome console gives these errors which are general as far as I can see and not related to this (although I know, they need sorting!)
GET http://www.paycoservices.co.uk/resources/demos/style.css 404 (Not Found) newsliderdev.asp:20
GET http://www.paycoservices.co.uk/ahkerrigan-light-webfont.woff 404 (Not Found) newsliderdev.asp:1
Resource interpreted as Font but transferred with MIME type application/octet-stream: "http://www.paycoservices.co.uk/ahkerrigan-light-webfont.ttf".
After using various versions of colorbox and jQuery I finally found a set that works well together and solves this issue as it was simply down to the versions of colorbox and jQuery I was using. jQuery 1.6.4 and the current version of colorbox work together perfectly.

Loading audio via a Blob URL fails in Safari

Following code works in Chrome (22.0) but not in Safari (6.0)
<!DOCTYPE html>
<html>
<head>
<script>
function onGo(e) {
var fr = new FileReader();
var file = document.getElementById("file").files[0];
fr.onload = function(e) {
var data = new Uint8Array(e.target.result);
var blob = new Blob([data], {type: 'audio/mpeg'});
var audio = document.createElement('audio');
audio.addEventListener('loadeddata', function(e) {
audio.play();
}, false);
audio.addEventListener('error', function(e) {
console.log('error!', e);
}, false);
audio.src = webkitURL.createObjectURL(blob);
};
fr.readAsArrayBuffer(file);
}
</script>
</head>
<body>
<input type="file" id="file" name="file" />
<input type="submit" id="go" onclick="onGo()" value="Go" />
</body>
</html>
In Safari, neither callback (loadeddata nor error) is called.
The content used is an mp3 file, which is normally played back with audio tag.
Is there any special care needed for Safari?
Many years later, I believe the example in the OP should work just fine. As long as you somehow set the mime type when creating the blob, like the OP does above with the type property of the options passed in:
new Blob([data], {type: 'audio/mpeg'});
You could also use a <source> element inside of an audio element and set the type attribute of the <source> element. I have an example of this here:
https://lastmjs.github.io/safari-object-url-test
And here is the code:
const response = await window.fetch('https://upload.wikimedia.org/wikipedia/commons/transcoded/a/ab/Alexander_Graham_Bell%27s_Voice.ogg/Alexander_Graham_Bell%27s_Voice.ogg.mp3');
const audioArrayBuffer = await response.arrayBuffer();
const audioBlob = new Blob([audioArrayBuffer]);
const audioObjectURL = window.URL.createObjectURL(audioBlob);
const audioElement = document.createElement('audio');
audioElement.setAttribute('controls', true);
document.body.appendChild(audioElement);
const sourceElement = document.createElement('source');
audioElement.appendChild(sourceElement);
sourceElement.src = audioObjectURL;
sourceElement.type = 'audio/mp3';
I prefer just setting the mime type of the blob when creating it. The <source> element src attribute/property cannot be updated dynamically.
I have the same problem, and I spend a couple days troubleshooting this already.
As pwray mentioned in this other post, Safari requires file extensions for media requests:
HTML5 Audio files fail to load in Safari
I tried to save my blob to a file, named it file.mp3 and Safari was able to load the audio that way, but after I renamed the file to have no extension (just "file"), it didn't load.
When I tried the url created from the blob in another tab in Safari:
url = webkitURL.createObjectURL(blob);
it download a file right away called "unknown", but when I tried the same thing in Chrome (also on Mac), it showed the content of the file in the browser (mp3 files start with ID3, then a bunch of non-readable characters).
I couldn't figure out yet how I could force the url made of blob to have an extension, because usually it looks like this:
blob:https://example.com/a7e38943-559c-43ea-b6dd-6820b70ca1e2
so the end of it looks like a session variable.
This is where I got stuck and I would really like to see a solution from some smart people here.
Thanks,
Steven
Sometimes, HTML5 audio can just stop loading without any apparent reason.
If you take a look to the Media Events (http://www.w3schools.com/tags/ref_eventattributes.asp) you´ll see an event called: "onStalled", the definition is "Script to be run when the browser is unable to fetch the media data for whatever reason" and it seems that it should be helpful for you.
Try listening for that event and reloading the file if necessary, with something like this:
audio.addEventListener('onstalled', function(e) {
audio.load();
}, false);
I hope it helps!
Just use source tag in audio.
<audio controls>
<source src="blob" type="blobType">
</audio>

flowplayer streaming mp4 from apache

I'm having some problems getting this to work. I think I've done it right based on http://flowplayer.org/forum/5/14664#post-14830). The clip starts to play fine, but when I skip to a part of the clip which hasn't loaded yet it just goes back to the start of the file/video
Sadly the browser used is IE6 for the most part :(
Apache 2 running on Redhat
I've created an mp4 file with ffmpeg.
Run qt-faststart 1.mp4 1.qt.mp4
Installed mod_flvx.c
Added:
LoadModule flvx_module modules/mod_flvx.so
AddHandler flv-stream .flv
To Apache httpd.conf
Using the example page:
<script type="text/javascript">
flowplayer("player", "flash/flowplayer-3.0.3.swf", {
clip: {
url: 'http://servername/player/media/1.qt.mp4',
// default provider: 'h264streaming'
provider: flashembed.isSupported([9, 115]) ? 'h264streaming' : 'lighttpd',
scaling: 'fit',
autoBuffering: true,
autoplay: false,
bufferLength: 3
},
log: {
level: 'debug'
},
plugins: {
h264streaming: {
url: 'flash/flowplayer.h264streaming-3.0.5.swf'
},
controls: {
url: 'flash/flowplayer.controls-3.0.3.swf',
// which buttons are visible and which not ?
play:false,
fullscreen:true,
// scrubber is a well known nickname to the timeline/playhead combination
scrubber: true
}
}
});
</script>
Anyone have any suggestions?
Thanks
First off, you need to see if your apache is configured to correctly seek to parts of the video. You can do that by passing a get parameter like my_vide_path.mp4?start=10 to have it start 10 seconds in. If it successfully starts 10 seconds in, then apache is set up correctly and you need to make flowplayer work. If apache isn't set up correctly, then even the correct flowplayer config won't help.
I doubt your apache is set up correctly though. You're telling apache to handle .flv files and yet you're using mp4s.
I've successfully gotten this to work with the apache module from http://h264.code-shop.com/trac/wiki.
You'll need to add and load the module into apache and tell apache to handle .mp4 files with it.
Next step would be to test with that get parameter ?start=10 to see if it is seeking correctly.
After that, all you need to do is:
<script type="text/javascript">
flowplayer("player", "flash/flowplayer-3.0.3.swf", {
clip: {
url: 'http://servername/player/media/1.qt.mp4',
default provider: 'h264streaming'
},
plugins: {
h264streaming: {
url: 'flash/flowplayer.h264streaming-3.0.5.swf'
}
}
});
</script>
I used the updated flowplayer swf and instead of h264's swf, the flowplayer plugin for psuedostreaming, as it works with the newer version of flowplayer and apparently the h264 one didnt.