Detalhes do pacote

subtitle

gsantiago80.9kMIT4.2.2-alpha.0

Stream-based library for parsing and manipulating subtitles

subtitle, webvtt, srt, vtt

readme (leia-me)

subtitle

Build Status Code Climate Coverage Status downloads npm

Stream-based library for parsing and manipulating subtitle files.

"Thanks for this rad package!" John-David Dalton, creator of Lodash

:white_check_mark: Stream API
:white_check_mark: Written in TypeScript
:white_check_mark: SRT support
:white_check_mark: Partial support for WebVTT (full support comming soon)
:white_check_mark: 100% code coverage
:white_check_mark: Actively maintained since 2015

Installation

npm

npm install subtitle

yarn

yarn add subtitle

Usage

This library provides some stream-based functions to work with subtitles. The following example parses a SRT file, resyncs it and outputs a VTT file:

import fs from 'fs'
import { parse, resync, stringify } from 'subtitle'

fs.createReadStream('./my-subtitles.srt')
  .pipe(parse())
  .pipe(resync(-100))
  .pipe(stringify({ format: 'WebVTT' }))
  .pipe(fs.createWriteStream('./my-subtitles.vtt'))

It also provides functions like map and filter:

import { parse, map, filter, stringify } from 'subtitle'

inputStream
  .pipe(parse())
  .pipe(
    filter(
      // strips all cues that contains "𝅘𝅥𝅮"
      node => !(node.type === 'cue' && node.data.text.includes('𝅘𝅥𝅮'))
    )
  )
  .pipe(
    map(node => {
      if (node.type === 'cue') {
        // convert all cues to uppercase
        node.data.text = node.data.text.toUpperCase()
      }

      return node
    })
  )
  .pipe(stringify({ format: 'WebVTT' }))
  .pipe(outputStream)

Besides the stream functions, this module also provides synchronous functions like parseSync and stringifySync. However, you should avoid them and use the stream-based functions for better performance:

import { parseSync, stringifySync } from 'subtitle'

const nodes = parseSync(srtContent)

// do something with your subtitles
// ...

const output = stringify(nodes, { format: 'WebVTT' })

API

The module exports the following functions:

parse

  • parse(): DuplexStream

It returns a Duplex stream for parsing subtitle contents (SRT or WebVTT).

import { parse } from 'subtitle'

inputStream
  .pipe(parse())
  .on('data', node => {
    console.log('parsed node:', node)
  })
  .on('error', console.error)
  .on('finish', () => console.log('parser has finished'))

Check out the Examples section for more use cases.

parseSync

  • parseSync(input: string): Node[]

NOTE: For better perfomance, consider using the stream-based parse function

It receives a string containing a SRT or VTT content and returns an array of nodes:

import { parseSync } from 'subtitle'
import fs from 'fs'

const input = fs.readFileSync('awesome-movie.srt', 'utf8')

parseSync(input)

// returns an array like this:
[
  {
    type: 'cue',
    data: {
      start: 20000, // milliseconds
      end: 24400,
      text: 'Bla Bla Bla Bla'
    }
  },
  {
    type: 'cue',
    data: {
      start: 24600,
      end: 27800,
      text: 'Bla Bla Bla Bla',
      settings: 'align:middle line:90%'
    }
  },
  // ...
]

stringify

  • stringify({ format: 'SRT' | 'vtt' }): DuplexStream

It returns a Duplex that receives parsed nodes and transmits the node formatted in SRT or WebVTT:

import { parse, stringify } from 'subtitle'

inputStream.pipe(parse()).pipe(stringify({ format: 'WebVTT' }))

Check out the Examples section for more use cases.

stringifySync

  • stringify(nodes: Node[], options: { format: 'SRT' | 'vtt }): string

NOTE: For better perfomance, consider using the stream-based stringify function

It receives an array of captions and returns a string in SRT (default), but it also supports VTT format through the options.

import { stringifySync } from 'subtitle'

stringifySync(nodes, { format: 'SRT' })
// returns a string in SRT format

stringifySync(nodes, { format: 'WebVTT' })
// returns a string in VTT format

map

  • map(callback: function): DuplexStream

A useful Duplex for manipulating parsed nodes. It works similar to the Array.map function, but for streams:

import { parse, map, stringify } from 'subtitle'

inputStream
  .pipe(parse())
  .pipe(
    map((node, index) => {
      if (node.type === 'cue') {
        node.data.text = node.data.text.toUpperCase()
      }

      return node
    })
  )
  .pipe(stringify({ format: 'SRT' }))
  .pipe(outputStream)

filter

  • filter(callback: function): DuplexStream

A useful Duplex for filtering parsed nodes. It works similar to the Array.filter function, but for streams:

import { parse, filter, stringify } from 'subtitle'

inputStream
  .pipe(parse())
  .pipe(
    filter((node, index) => {
      return !(node.type === 'cue' && node.data.text.includes('𝅘𝅥𝅮'))
    })
  )
  .pipe(stringify({ format: 'SRT' }))
  .pipe(outputStream)

resync

  • resync(time: number): DuplexStream

Resync all cues from the stream:

import { parse, resync, stringify } from 'subtitle'

// Advance subtitles by 1s
readableStream
  .pipe(parse())
  .pipe(resync(1000))
  .pipe(outputStream)

// Delay 250ms
stream.pipe(resync(captions, -250))

parseTimestamp

  • parseTimestamp(timestamp: string): number

Receives a timestamp (SRT or VTT) and returns its value in milliseconds:

import { parseTimestamp } from 'subtitle'

parseTimestamp('00:00:24,400')
// => 24400

parseTimestamp('00:24.400')
// => 24400

parseTimestamps

  • parseTimestamps(timestamps: string): Timestamp

It receives a timestamps string, like 00:01:00,500 --> 00:01:10,800. It also supports VTT formats like 12:34:56,789 --> 98:76:54,321 align:middle line:90%.

import { parseTimestamps } from 'subtitle'

parseTimestamps('00:01:00,500 --> 00:01:10,800')
// => { start: 60500, end: 70800 }

parseTimestamps('12:34:56,789 --> 98:76:54,321 align:middle line:90%')
// => { start: 45296789, end: 357414321, settings: 'align:middle line:90%' }

formatTimestamp

  • formatTimestamp(timestamp: number, options?: { format: 'SRT' | 'vtt' }): string

It receives a timestamp in milliseconds and returns it formatted as SRT or VTT:

import { formatTimestamp } from 'subtitle'

formatTimestamp(142542)
// => '00:02:22,542'

formatTimestamp(142542, { format: 'WebVTT' })
// => '00:02:22.542'

Examples

Nodes

This is what a list of nodes looks like:

[
  {
    type: 'header',
    data: 'WEBVTT - Header content'
  },
  {
    type: 'cue',
    data: {
      start: 150066, // timestamp in milliseconds,
      end: 158952,
      text: 'With great power comes great responsibility'
    }
  },
  ...
]

For now, it only supports two types of node: header and cue. Soon, it will support more types like comment.

Convert SRT file to WebVTT

import fs from 'fs'
import { parse, stringify } from 'subtitle'

fs.createReadStream('./source.srt')
  .pipe(parse())
  .pipe(stringify({ format: 'WebVTT' }))
  .pipe(fs.createWriteStream('./dest.vtt'))

Extract subtitles from a video

The following example uses the rip-subtitles for extracting subtitles from a mkv video and save it as WebVTT.

import extract from 'rip-subtitles'
import { parse, stringify } from 'subtitle'

extract('video.mkv')
  .pipe(parse())
  .pipe(stringify({ format: 'WebVTT' }))
  .pipe(fs.createWriteStream('./video.vtt'))

Create subtitles

import { stringifySync } from 'subtitle'

const list = []

list.push({
  type: 'cue',
  data: {
    start: 1200,
    end: 1300,
    text: 'Something'
  }
})

stringifySync(list)

License

MIT

changelog (log de mudanças)

Change Log

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog and this project adheres to Semantic Versioning.

[4.2.1] - 2022-07-02

  • Add support for single digits in timestamps by @nbarnett

[4.1.2] - 2022-01-02

  • Implement filter as a Transform stream to fix piping #77 by @marnusw

[4.1.1] - 2021-08-14

  • Remove decimals from ms #73

[4.1.0] - 2021-03-20

  • Ignore VTT comments #66

[4.0.1] - 2020-09-19

  • Update README
  • Add tests for parser errors

[4.0.0] - 2020-09-19

  • Fixes #6 by introducing the stream interface (parse, stringify and resync are now stream-based functions)
  • Add parseSync and stringifySync as synchronous version of parse and stringify
  • Add map and filter to manipulate the parse stream
  • Update the nodes tree so it can support more types than just a cue
  • Refactor the internals by creating the Parser and Formatter classes
  • Format types are now "SRT" and "WebVTT" instead of "srt" and "vtt"

[3.0.0] - 2020-08-31

  • Rewrite the project with TypeScript
  • Fixes #43 and #39
  • Update the API to export only these functions:
    • parse(input: string): Caption[]
    • stringify(captions: Caption[], options?: { format: 'srt' | 'vtt }): string
    • resync(captions: Caption[], time: number): Caption[]
    • parseTimestamp(timestamp: string): number
    • parseTimestamps(timestamps: string): Timestamp
    • formatTimestamp(timestamp: number, options?: { format: 'srt' | 'vtt' }): string
    • parse supports optional indexes

[2.0.5] - 2020-08-28

  • Remove zero-fill dependency
  • Rewrite and refactor tests with Jest
  • Remove some devDependencies

[2.0.4] - 2020-08-27

Added

  • Add one-digit hour support #45 which fixes #31

[2.0.3] - 2019-04-04

Added

  • Add ESM module field to package.json

[2.0.2] - 2019-01-22

Added

  • Support separated texts in subtitles #36

[2.0.1] - 2018-10-24

Added

  • Support for WebVTT headers support #32

[2.0.0] - 2018-06-22

Changed

  • Fix parsing of the text with the new line and whitespace at the end #25

[1.2.0] - 2018-03-07

Added

  • toVttTime and stringifyVtt functions #24

Changed

  • Fix broken tests #21

[1.1.1] - 2018-02-16

Added

  • Webpack instead of Browserify.
  • Fix #18 and #19.
  • ES2015 modules.

[1.1.0] - 2018-02-15

Added

  • Support for both SRT and WebVTT input strings #21

[1.0.1] - 2017-10-13

Changed

  • Fix parsing of 00:00:00,000 timestamp #17

[1.0.0] - 2017-09-18

Changed

  • Almost everything. Subtitle.js has a new API now.
  • Code rewritten to ES6.
  • Tests improved.

[0.1.5] - 2017-02-27

Changed

  • Ensure text is an empty string instead of null or undefined, #15

[0.1.4] - 2017-02-27

Changed

  • Normalize extra newlines, #44

[0.1.3] - 2017-01-11

Added

  • .npmignore
  • .codeclimate.yml
  • Additional tests.
  • Code Coverage with coveralls.
  • Changelog.

Changed

  • Use AVA and nyc instead of Mocha, Chai and Istanbul.
  • Improve code organization.

[0.1.2] - 2016-09-09

Added

Changed

  • Use NPM scripts instead of Make.
  • Use xtend module instead of underscore.
  • Change code style to Standard rules.

[0.1.1] - 2016-01-12

Changed

  • Rename stringfy method to stringify.

Old Versions

Old versions are undocumented.