I have embedded DASH videos in webpage using <video>
tag. This content has multiple audio tracks. I want to support audio track change.
I used audioTracks[i].enable
feature to select a audio track. But the audio track is not changing.
if (selected == i) {
audioTracks[i].enable = TRUE;
}
- Is this the right way ?
- Is there any other way for changing the audio track of DASH(.mpd) content?
By audio track change, i mean to initiate a track change event that can propogate to lower level. not to implement a track change itself.
I further tried,
audioLanguage and lang attributes of video tag as
document.getElementById(id).lang = selectedIndex;
and
document.getElementById(id).audioLanguage = selectedIndex;
Even this doesnt seem to work.
To be more clear, as mentioned in answer by @Svenskunganka audioTracks[i].enable=TRUE;
is not supported in chromium in version that is used.
So, Is there any alternate way of doing what audioTracks[i].enable=TRUE
does.
I dont want to implement track change functionality. Requirement here is to just indicate a track change to the browser.
EDIT
:
As we can see in https://www.w3schools.com/tags/av_prop_audiotracks.asp. This property is not supported in chrome. so what is the alternate way of indicating that track has to be changed?
Is there any other way ?. Or audioTrack is the only way (as i understand from search so far)?
You can request the .mpd
file using fetch()
or XMLHttpRequest()
, read the application/dash+xml
response as text using .text()
or .responseText
, pass the text to DOMParser()
instance .parseFromString()
to create a #document
, iterate AdaptationSet
child nodes of document.documentElement
Period
element, use .querySelector()
to get Representation
child node then get BaseURL
child node of Representation
, where the URLs are .textContent
having path to, at least at the file referenced, a file at the same directory.
We can also select the video URL, use Promise.all()
to load and play both video and audio tracks for ability to call HTMLMediaElement.captureStream()
, which we .clone()
and pass to resolve()
of Promise
constructor, at chained .then()
call .addTrack()
on a MediaStream()
instance for each track, then set <video>
.srcObject
to the MediaStream
containing both audio and video tracks.
const video = document.querySelector("video");
const mediaStream = new MediaStream();
const url = "https://dash.akamaized.net/dash264/TestCases/10a/1/"
const mpd = "iis_forest_short_poem_multi_lang_480p_single_adapt_aaclc_sidx.mpd";
const avc = [];
video.oncanplay = video.play;
fetch(`${url}${mpd}`)
.then(response => response.text())
.then(text => {
const parser = new DOMParser();
const xml = parser.parseFromString(text, "application/xml");
const period = xml.documentElement;
const tracks = period.querySelectorAll("AdaptationSet");
for (let track of tracks) {
const representation = track.querySelector("Representation");
const {textContent:currentTrack} = representation.querySelector("BaseURL");
console.log(currentTrack);
// filter for specific track here, for example
// where "english" is included within `.textContent` of node
if (/english/i.test(currentTrack) || /avc/.test(currentTrack)) {
avc.push(`${url}${currentTrack}`);
}
}
Promise.all(avc.map(media => {
return new Promise(resolve => {
let v = document.createElement("video");
v.src = media;
v.volume = 0.5;
v.muted = true;
v.oncanplay = () => {
v.play();
resolve({
currentMedia:v
, stream:v.captureStream().clone().getTracks()[0]
})
}
})
}))
.then(tracks_ => {
for (let {stream, currentMedia} of tracks_) {
mediaStream.addTrack(stream);
currentMedia.muted = false;
}
video.srcObject = mediaStream;
})
})
<video controls></video>
The Audio Track API is not fully implemented cross-browser yet. See caniuse for Audio Track. Your issue is likely that you use either Chrome or Firefox to test this.
Chrome has implemented it but have not yet announced when it will land.
It is implemented in Firefox 33 but is not enabled by default and has to be toggled via user preference. There seems to also be some issues with Gecko not being able to perform multi-track playback, which is why this feature has been disabled for so long (Firefox is at version 57 at the time of writing).