Scenario
I encountered an issue while trying to play a video in the Edge browser. The project framework consists of:
.NET 6 MVC
and VUE
for the client side
.NET 6 WebApi
for the server side
The Vue component on the client will send a request with a range header (1MB) to retrieve fragmented MP4, and utilize the Media Source Extensions (MSE) to append arrayBuffer to the blobUrl that points to video.src
.
For example:
var mediaSource = new MediaSource;
mediaSource.addEventListener('sourceopen', sourceOpen);
video.src = URL.createObjectURL(mediaSource);
This setup works flawlessly in Windows' EDGE browser, BUT it does not function properly on an iPhone (tested using iPhone SE's Edge browser). In this case, the video tag displays a blank page only.
Image from iPhone SE
(EDGE Version 100.0.1185.50):
https://i.sstatic.net/E3Sdr.jpg
However, it works perfectly on Windows' EDGE Version 100.0.1185.50.
Image from Windows 10
:
https://i.sstatic.net/D3SkZ.png
Solution Attempts
I have attempted adding the playsinline
property to the video tag and tried other solutions mentioned in HTML5 Video tag not working in Safari, iPhone, and iPad, but unfortunately, none of them resolved the issue.
Relevant Code
The method within the Vue component is as follows:
/*
* check if the videoId matches the course or not.
* If not, fetch a new video stream and create a blob URL pointing to this.videoUrl
*/
async displayVideo() {
if (this.videoId != this.course) {
//common.loader.show("#255AC4", 1.5, "Loading...");
this.videoId = this.course;
let video = document.querySelector("video");
let assetURL = FrontEndUrl + `/Stream/${this.videoId}`;
let mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
let sourceBuffer;
let chunkSize;
let contentRange;
let loop;
let index;
const token = common.cookieManager.getCookieValue(`signin`);
if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {
let mediaSource = new MediaSource;
mediaSource.addEventListener('sourceopen', sourceOpen);
video.src = URL.createObjectURL(mediaSource);
} else {
console.error('Unsupported MIME type or codec: ', mimeCodec);
}
function sourceOpen() {
// chunkSize set to 1MB
chunkSize = 1024 * 1024 * 1;
// index set to 1 because the fetchNextSegment starts from the second fragment
index = 1;
// Retrieve mediaSource and add updateend event to sourceBuffer
let mediaSource = this;
sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
sourceBuffer.addEventListener("updateend", fetchNextSegment);
fetchArrayBuffer(assetURL, chunkSize * 0, appendBuffer);
// 📌 Here we encounter a DOM interact error
//video.play();
}
function fetchNextSegment() {
if (index > loop) {
sourceBuffer.removeEventListener("updateend", fetchNextSegment);
return;
}
fetchArrayBuffer(assetURL, chunkSize * index, appendBuffer);
index++;
}
function fetchArrayBuffer(url, range, appendBuffer) {
fetch(url, {
headers: {
"Range": `bytes=${range}-`,
"Authorization": `Bearer ${token}`,
}
})
.then(response => {
if (!loop) {
contentRange = response.headers.get("x-content-range-total");
loop = Math.floor(contentRange / chunkSize);
}
return response.arrayBuffer();
})
.then(data => { appendBuffer(data) });
}
function appendBuffer(videoChunk) {
if (videoChunk) {
sourceBuffer.appendBuffer(videoChunk);
}
}
// 📌 This was the old way, which did not attach the JWT token
// this.videoUrl = await this.fetchVideoStream(this.videoId); //FrontEndUrl + `/Stream/${this.videoId}`;
//common.loader.close();
}
},
And My Vue's template
<p-card>
<template #header>
</template>
<template #title>
<h2>Course Name: {{courseName}}</h2>
</template>
<template #subtitle>
</template>
<template #content>
<video id="video" style="width: 100%; height: auto; overflow: hidden;" :key="videoUrl" v-on:loadeddata="setCurrentTime" v-on:playing="playing" v-on:pause="pause" controls autoplay playsinline>
</video>
</template>
<template #footer>
All Rights Reserved. Unauthorized reproduction prohibited.
</template>
</p-card>
In addition to checking logs on my machine, everything appeared normal. Any insights on why this isn't working on iOS's EDGE would be greatly appreciated. Thank you!