5

Is there a good way to delete a single TextTrack added via JavaScript to a HTML5 <video> tag? The following code is a simple demo of how to add a track, but I haven't found a good way to remove one:

document.querySelector('video#myVideo').addTextTrack(...);
frapontillo
  • 10,499
  • 11
  • 43
  • 54
  • Give this issue a https://github.com/whatwg/html/issues/1921 a thumb up to raise awareness and make a PR – Endless Jan 16 '21 at 12:48

5 Answers5

5

There is no mechanism to remove an added text-track (probably a flaw (?) in the current specification. There is also an onremovetrack event but...).

The only thing we can do is to disable or hide it. Make sure you keep a reference to the track:

var video = document.querySelector('video#myVideo');
var track = video.addTextTrack("...");
...
track.mode = "showing";  // when cues are added and is ready

Then when you no longer need it:

track.mode = "disabled"; // or "hidden"

(you might get around resetting the src as well, but I haven't tried this..)

  • 3
    Yeah, that's what I am doing, I just wanted to be sure there's no way around this, for now. The only way to trigger an `onremovetrack` event is by removing the `` node from the video tag, which of course is not possible for "non-DOM" tracks. – frapontillo Mar 27 '15 at 22:45
  • You can add regular tracks with a `` node, and by removing it the related element from the `textTracks` property is immediately removed as well. – frapontillo Mar 27 '15 at 23:43
2

Implementation of TextTrackList

Please refer to this URL first if you did not read. https://developer.mozilla.org/en-US/docs/Web/API/TextTrackList

It metioned that

addtrack

Fired when a new text track has been added to the media element.

removetrack

Fired when a new text track has been removed from the media element.

As you can see from the above, addtrack and removetrack events are dependent on HTMLMediaElement.

Remove track with DOM element .removeChild()

<!-- HTML -->
<video src="foo.ogv">
    <track kind="subtitles" label="English subtitles" src="subtitles_en.vtt" srclang="en" default>
    </track>
    <track kind="subtitles" label="Deutsche Untertitel" src="subtitles_de.vtt" srclang="de">
    </track>
</video>

videoElement.textTracks console output

var videoElement = document.querySelector("video");
console.log(videoElement.textTracks);
//output
TextTrackList {0: TextTrack, 1: TextTrack, length: 2, onchange: null, onaddtrack: null, onremovetrack: null}
0: TextTrack {kind: "subtitles", label: "English subtitles", language: "en", id: "", mode: "showing", …}
1: TextTrack {kind: "subtitles", label: "Deutsche Untertitel", language: "de", id: "", mode: "disabled", …}
length: 2
videoElement.textTracks.onremovetrack = function(event){
    console.log('DOM removed',event)
    console.log(videoElement.textTracks)
}
var tracks = videoElement.querySelectorAll('track')
videoElement.removeChild(tracks[0])

//output
DOM removed TrackEvent {isTrusted: true, track: TextTrack, type: "removetrack", target: TextTrackList, currentTarget: TextTrackList, …}
TextTrackList {0: TextTrack, 1: TextTrack, length: 1,...}
0: TextTrack {kind: "subtitles", label: "Deutsche Untertitel", language: "de", id: "", mode: "disabled", …}

Disable Track

videoElement.textTracks[0].mode = "disabled"; // Disable English
videoElement.textTracks[1].mode = "showing";  // Enable Deutsche

addTextTrack & removeTextTrack

addTextTrack method will not create track element to HTMLMediaElement, thus you need to create and append track element manually if you need to remove a track using DOM element.

There is no removeTextTrack method at the moment. If you need removeTextTrack please visit the following as @Endless mentioned from the above comment. https://github.com/whatwg/html/issues/1921

John
  • 3,304
  • 1
  • 18
  • 26
  • Please consider editing your answer and **delete** the "Remove Track" part as it might cause damage! `` is **not** the only type of children ` – LWC Oct 05 '22 at 17:55
  • @LWC , thank you for the suggestion. I modified the above to use `videoElement.querySelectorAll('track')` to avoid affect other tags. – John Oct 07 '22 at 06:16
  • Thanks! But my other line missed the word "not" ("might not") - textTracks might not even match s (if JS was used to create textTracks directly), so how to deal with that? – LWC Oct 07 '22 at 09:12
  • @LWC , would you be able to provide a reproducible code of your issue? – John Oct 07 '22 at 21:20
  • Guess you can just try https://www.w3schools.com/jsref/met_video_addtexttrack.asp while **also** already using HTML s. – LWC Oct 07 '22 at 22:16
  • @LWC, there is no `removeTextTrack` method as you know. When you use `addTextTrack` , you may add `track` element to DOM as well. – John Oct 08 '22 at 07:22
  • Not having `removeTextTrack` is exactly why we're all here. It's a complex situation. But none of the scripts I saw online (not even MDN/W3) bothered to add HTML `` when they used `addTextTrack`. – LWC Oct 08 '22 at 07:31
1

//best way to do this thing
//disable The Old Subtitles From The Dom
var tracks = document.querySelector("video").textTracks;
var numTracks = tracks.length;
for (var i = numTracks - 1; i >= 0; i--)
  document.querySelector("video").textTracks[i].mode = "disabled";
<video>
    <track>
    <track>
</video>
Michael M.
  • 10,486
  • 9
  • 18
  • 34
anu go
  • 11
  • 1
0

This can be done using javascript and the VideoJS library (tested and works with 1 or more tracks):

Get the media player object in the DOM using some sort of selector, then get all it's tracks, then remove them one by one by iterating through the array in reverse order.

var player = videojs(document.getElementById(playerId));
var tracks = player.remoteTextTracks();
var numTracks = tracks.length;
for(var i = numTracks - 1; i >=0 ; i--) {
    player.removeRemoteTextTrack(tracks[i]);
}
Phong Phuong
  • 369
  • 4
  • 8
0

Much more verbose, but you could use the DOM API. Most of the work is to find the correspondence between the DOM TrackElement and the TextTrack from video.textTracks.

A track added with video.addTextTrack strangely do not get added to the DOM.

Add track

const textTracksBefore = Array.from(videoElement.textTracks);
const trackElement = document.createElement('track');
trackElement.kind = 'subtitles';
trackElement.label = PlayerShakaTextDisplayer.TextTrackLabel_;
trackElement.srclang = language;
videoElement.appendChild(trackElement);
this.trackElement_ = trackElement;
const textTracksAfter = Array.from(videoElement.textTracks);
const newTracks = textTracksAfter.filter(x => !textTracksBefore.includes(x));
this.textTrack_ = newTracks[0];

Remove track

this.videoElement.removeChild(this.trackElement_);
this.trackElement_ = null;
this.textTrack_ = null;
FredG
  • 712
  • 7
  • 10