user12098841
user12098841

Reputation:

Add subtitle line by line dynamically to a video element in javascript

I wanted to know if this is currently possible

below is my HTML:

<video src="something.mp4"> </video>

I also have an array of Object that has all the captions I need to display...

example:

captions_array = [
    {start: 0, end: 2, message: "hello"}, 
    {start: 3, end: 4, message: "how"}, 
    {start: 5, end: 8, message: "are"}
]

Now based on the video's current time I want to just pick one caption out of this array and display that, remove that when needed, and display another...

Note:

1. I must supply captions on video playback, by choosing text from that array dynamically.

2. I cannot use any subtitle file (VTT), I get captions from this array only

3. I can't do anything on the backend, I want to do this on the front-end in the browser only.

Edit: In response to answers to this question:

4. I cannot use source element inside thee video tag

5. The captions Array will get populated with time dynamically

You can use this mp4 URL to create a short demo:
http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4

Upvotes: 2

Views: 2395

Answers (1)

Kaiido
Kaiido

Reputation: 136717

You can create WebVTT files from the browser directly and load them using a blob:// URI.

The syntax for WebVTT is quite strict but also quite simple to grasp.

So if we say that your start and end values do represent seconds in the media we could make a generator this way:

const captions_array = [
  { start: 0, end: 2, message: "hello" }, 
  { start: 3, end: 4, message: "how" }, 
  { start: 5, end: 8, message: "are" }
];
const VTTFile = makeVTT( captions_array );
const vid = document.querySelector( "video" );
const track = document.createElement( "track" );
track.kind = "captions";
track.label = "English";
track.srclang = "en";
track.src = URL.createObjectURL( VTTFile );
vid.addEventListener( "loadedmetadata", (evt) => {
  track.mode = "showing";
  vid.textTracks[0].mode = "showing"; // thanks Firefox 
});
vid.append( track );

function makeVTT( array ) {
  const text = array.reduce( (str, { start, end, message }, index) => {
    // you would also have to make a "seconds to timestamp" parser
    // but I leave it to the reader as an exercise
    return str + `
00:00:${ start.toFixed(3).padStart(6, "0") } --> 00:00:${ end.toFixed(3).padStart(6, "0") }
${ message }`;
  }, `WEBVTT`);
  return new Blob( [ text ], { type: "text/plain" } );
}
video { max-height: 100vh; max-width: 100vw; }
<video controls src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4">
</video>

Upvotes: 5

Related Questions