0

I'm trying to style dynamically added VTT cues by trying to target the cue id:

track = video.addTextTrack('captions', 'Captions', 'en');
track.mode = 'showing';

const cue = new VTTCue(0, 10, "Hello world");
cue.id = 'test';
track.addCue(cue);

console.log("ID:", track.cues[0].id)
/* This selector does not work */

::cue(#test) {
  color: red;
}


/* The generic selector works */

::cue {
  background-color: orange;
}
<video id="video" muted autoplay controls width="400px">
  <source type="video/mp4"
          src="https://upload.wikimedia.org/wikipedia/commons/4/46/Panorama_of_the_valley_from_Leh_Palace.webm">     </source>
</video>

I extremely simplified the example, but it shows the problem. I'm not sure what I'm doing wrong, I tried to follow the W3C specs: https://w3c.github.io/webvtt/#introduction-other-features

In this example, the cues have an identifier:

WEBVTT

test

00:00.000 --> 00:02.000 This is a test.

123 00:00.000 --> 00:02.000 That’s an, an, that’s an L!

crédit de transcription 00:04.000 --> 00:05.000 Transcrit par Célestes™ This allows a style sheet to specifically target the cues.

/* style for cue: test */ ::cue(#test) { color: lime; } Due to the syntax rules of CSS, some characters need to be escaped with CSS character escape sequences. For example, an ID that starts with a number 0-9 needs to be escaped. The ID 123 can be represented as "\31 23" (31 refers to the Unicode code point for "1"). See Using character escapes in markup and CSS for more information on CSS escapes.

/* style for cue: 123 / ::cue(#\31 23) { color: lime; } / style for cue: crédit de transcription */ ::cue(#crédit\ de\ transcription) { color: red; }

I don't know if the id selectors work only with .vtt files and not with cues generated via JS. There still are not many info on VTT, since it's still a work in progress technology, I tried different approaches, even using vtt.js to parse a VTT string containing inline ::cue styling, but that doesn't work either.

Cesare Polonara
  • 3,473
  • 1
  • 9
  • 19

1 Answers1

1

You could use a class object inside the VTT text.

But it requires to modify the text attribute for each VTT object.

Then your css rule will be applied.

track = video.addTextTrack('captions', 'Captions', 'en');
track.mode = 'showing';

// wrap text in <c> txt </c>
const cue = new VTTCue(0, 10, "<c>Hello world</c>");
cue.id = "test";
track.addCue(cue);
::cue(#test) {
  color: red;
}
::cue {
  background-color: orange;
}
<video id="video" muted autoplay controls width="400px">
  <source type="video/mp4"
          src="https://upload.wikimedia.org/wikipedia/commons/4/46/Panorama_of_the_valley_from_Leh_Palace.webm">     </source>
</video>
ste-xx
  • 320
  • 1
  • 10
  • That's awesome, I ended up with a workaround using the `onenter` callback and changing dinamically the color and bg globally when the cue switches, this way I don't have to add multiple entries to the style. Anyway this seems to fix it, did you read this on some docs or you got there by trial ? They don't seem to mention it on w3c docs, why should the class span be mandatory in order to make the cue id selectable ? – Cesare Polonara May 02 '22 at 19:00
  • I linked the class object in the w3c doc. I don't know why they made it mandatory. It was a mix by trial, experience (I wrote a subtitle browser extension some time ago) and reading documentation. Always surprising what works and what doesn't. I don't know what you want to archive, but sometimes css variables are easier to handle, but hard to tell if you don't know the use case. – ste-xx May 02 '22 at 19:25
  • In the w3c docs is an explicit an example with your solution, so maybe it is a bug in chrome/firefox ? – ste-xx May 02 '22 at 19:36
  • I'm working on a web VTT editor to live edit a video, adding captions, and when done send captions to a be where I hard encode them into the video with ffmpeg. But I need to display them in real time while the user is creating them, style included, so was just playing here https://stackblitz.com/edit/react-bzikdn?file=src%2FApp.js and got stuck on that issue. – Cesare Polonara May 02 '22 at 20:01