I tried to implement add chapters using .vtt files to a video in vue here is what I came up with.
Reference link https://codepen.io/adrianparr/pen/EENrgy/ (NOT BY ME, but I learned from his pen) thanks to adrianparr for the amazing codepen♥♥,
My live link https://codepen.io/panzar/pen/YzVGbyw ( almost similar but in vue)
Several sections of this article is framework independant and vue is used only for demonstration, basic concept should apply to any framework, even in vanilla JS
What’s a VTT

VTT files usually contain metadata, information like subtitles, chapters etc.
A vtt file for chapters contains cues which in turn contains id , startTime , endTime and text.
Cues can be accessed with this.$refs.chapters.track.cues
Setup
<video @timeupdate="updateTime" ref="video1" poster="https://s3.amazonaws.com/demo.jwplayer.com/text-tracks/assets/sintel.jpg" controls crossorigin="anonymous">
<source src="https://content.jwplatform.com/videos/q1fx20VZ-kNspJqnJ.mp4" type="video/mp4">
<source src="https://content.jwplatform.com/videos/q1fx20VZ-27m5HpIu.webm" type="video/webm">
<track id="chaptersTrack01" class="chaptersTrack" src="https://s3.amazonaws.com/demo.jwplayer.com/text-tracks/assets/chapters.vtt" kind="chapters" ref="chapters" v-on:load="getChaptersReady" default>
</video>
Have a closer look on track element
<track id="chaptersTrack01" class="chaptersTrack" src="https://s3.amazonaws.com/demo.jwplayer.com/text-tracks/assets/chapters.vtt" kind="chapters" ref="chapters" v-on:load="getChaptersReady" default>
the getChaptersReady method (this.chapters is declared as a reactive property (in data section))
getChaptersReady() {
let chapters = this.$refs.chaptersthis.chapters =chapters.track.cues
},
Once all chapters loaded loop through them and display them
<div v-for = "chapter in chapters">
<span :class="{chapters: true}" @click="skipTo(chapter.startTime)">
Chapter-{{chapter.id}}: {{chapter.text}} </span>
</div>
Finally — implement skipTo
Once we click on the chapter the video must skipTo that time
skipTo(time){
this.$refs.video1.currentTime = time
},
//that was easy
Don’t forget CSS
.chapters {
margin-top: 2rem;
margin-left: 2rem;
}
.chapters:hover {
cursor: pointer;
text-decoration: underline;
}
One last thing
To implement chapters you don’t necessarily need a .vtt file, any way to get chapter name, start and end time will be good enough, usally you won’t have the choice, but if you do keep that in mind that you could have made the same using JSON instead of a .vtt file.