npm package: @kaliber/use-subtitles
Description: Hook to easily consume your HTMLMediaElement WebVTT subtitles.
Latest version: 1.0.3-beta

# `@kaliber/use-subtitles`
Easily consume your video elements' WebVTT subtitles in React.

## Motivation
WebVTT subtitles are a great feature, but they come with some difficulties:
- Styling the subtitles with CSS to achieve a consistent look across browsers can be challenging.
- Third party dependencies hide the underlaying `HTMLMediaElement`, and thus;
- Interfacing with the subtitles from JavaScript code is not straightforward.

**This hook aims to make that easier for you.**

## Installation

```
yarn add @kaliber/use-subtitles
```

#### Transpilation

When working with `@kaliber/build`, add `@kaliber/use-subtitles` to your `compileWithBabel` array. 

## Usage
Here's a short example demonstrating the most common use case.


```jsx
import { useSubtitles } from '@kaliber/use-subtitles'

function Component() {
  const { ref } = useSubtitles({
    language: "en"
  })

  return (
    <video {... { ref }}>
      <source type="audio/mp3" src="./audio.mp3" />
      <track src="./subtitle.vtt" kind="subtitles" srcLang="en" default />
    </video>
  )
}
```

Look at the [`/example`](/example) directory for further examples.

## Usage with `ReactPlayer`
As long as you are able provide the underlying `HTMLMediaElement` of your dependency, the library should work.

Because `ReactPlayer` only provides the underlaying ref whenever it deems it ready, we need to set it through the `onReady` method (up until that time, its value will otherwise be `null`).

```jsx
import { useSubtitles } from '@kaliber/use-subtitles'
import ReactPlayer from 'react-player'

const config = {
  file: { tracks: [{
    kind: "subtitles",
    src: "/subtitle.vtt",
    srcLang: "en",
    default: true
  }]}
}

function Component() {
  const reactPlayerRef = React.useRef(null)
  const { current, ref } = useSubtitles({
    language: "en"
  })

  return (
    <ReactPlayer
      ref={reactPlayerRef}
      onReady={x => { ref.current = x.getInternalPlayer() }}
      url="./audio.mp3"
      {... { config }}
    />
  )
}
```

## Parameters
The hook accepts the following parameters:

| Key          | Type          | Example | Description   |
| ------------- | ------------- | ------------- | --- |
| `language`  | `string`  | `nl` | Expects a language code that matches the `track` language. Bear in mind this has to be a [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) string. For example in case of Japan, `jp` does not work in all browsers, where `ja` does, which is the valid ISO code.  |

## Return values
The `useSubtitles` hook returns the following values:

| Key            | Initial values | Description                                                                                                    |
|-----------------| --- |---------------------------------------------------------------------------------------------------------------|
| `subtitles`     | `[]` | An array of all subtitles available for the specified language.                                              |
| `metadata`     | `[]` | An array of all metadata available for the specified language.                                              |
| `active`       | See below. | An object representing the currently active subtitle and metadata, with metadata containing the properties `startTime`, `endTime`, and `text`, and subtitle also containing `voice`[^1]. |
| `ref`           | `{ current: null }` | A reference that should be attached to the player element ref attribute.                                    |

#### The structure of the `active` object:

```js
{
  subtitles: {
    [key]: null
  },
  metadata: {
    [key]: null
  }
}
```

[^1]: `voice` represents the current speakers' name.


## WebVTT
A WebVTT file typically looks like this: 

```vtt
WEBVTT

00:00:00.000 --> 00:00:20.000
<v Fred>Hi, my name is Fred

00:00:02.500 --> 00:00:22.500
<v Bill>Hi, I’m Bill

00:00:05.000 --> 00:00:25.000
<v Fred>Would you like to get a coffee?

00:00:07.500 --> 00:00:27.500
<v Bill>Sure! I’ve only had one today.

00:00:10.000 --> 00:00:30.000
<v Fred>This is my fourth!

00:00:12.500 --> 00:00:32.500
<v Fred>OK, let’s go.
```

## Metadata

This hook also has the option to extract metadata; additional data to support the subtitles, but are not directly shown to the user. This accepts JSON (which it parses and returns), or a regular string.

Example of a WebVTT metadata file (with `JSON`):

```vtt
WEBVTT

00:00:00.000 --> 00:00:01.000
{ "text": "Living on borrowed time", "color": "red" }

00:00:01.000 --> 00:00:02.400
{ "text": "the clock ticks faster.", "color": "red" }
```

Look at the `Karaoke` example for an implementation.

#### Extracted properties
`use-subtitles` extracts some of the available data from the cues. Here's an overview of _what_ it extracts, and how that is returned.

| Kind | Description |
| ---- | ----------- |
| `00:00:00.000 --> 00:00:20.000` | Timestamp. Outputted under `current.startTime` and `currrent.endTime`, and available for all cues in the `subtitles` array. |
| `<v Fred>` | `voice`-tag. Outputted by hook under `current.voice`. |
| `Hi, my name is Fred` | The `text`, available under `current.text`, and available for all cues in the `subtitles` array as `text`. |

---

![](https://media.giphy.com/media/kKJ8YFi1VVhHFudiz2/giphy.gif)

## Disclaimer
This library is intended for internal use, we provide __no__ support, use at your own risk. It does not import React, but expects it to be provided, which [@kaliber/build](https://kaliberjs.github.io/build/) can handle for you.

This library is not transpiled.