# node-video-lib [![build status](https://github.com/gkozlenko/node-video-lib/actions/workflows/node.js.yml/badge.svg)](https://github.com/gkozlenko/node-video-lib/actions/workflows/node.js.yml) [![test coverage](https://gkozlenko.github.io/node-video-lib/badges/coverage.svg)](https://github.com/gkozlenko/node-video-lib/actions/workflows/node.js.yml) [![npm version](https://img.shields.io/npm/v/node-video-lib.svg)](https://www.npmjs.com/package/node-video-lib) [![license](https://img.shields.io/github/license/gkozlenko/node-video-lib.svg)](https://github.com/gkozlenko/node-video-lib/blob/master/LICENSE) Node.js Video Library / MP4 & FLV parser / MP4 builder / HLS muxer ## Limitations **This library works only with MP4 and FLV video files encoded using H.264/H.265 video codecs and AAC audio codec.** ## Installation ```bash $ npm install node-video-lib ``` ## Usage ### Parse video file ```javascript const fs = require('fs'); const VideoLib = require('node-video-lib'); let fd = fs.openSync('/path/to/file', 'r'); try { let movie = VideoLib.MovieParser.parse(fd); // Work with movie console.log('Duration:', movie.relativeDuration()); } catch (ex) { console.error('Error:', ex); } finally { fs.closeSync(fd); } ``` ### Create MPEG-TS chunks ```javascript const fs = require('fs'); const VideoLib = require('node-video-lib'); let fd = fs.openSync('/path/to/file', 'r'); try { let movie = VideoLib.MovieParser.parse(fd); let fragmentList = VideoLib.FragmentListBuilder.build(movie, 5); for (let i = 0; i < fragmentList.count(); i++) { let fragment = fragmentList.get(i); let sampleBuffers = VideoLib.FragmentReader.readSamples(fragment, fd); let buffer = VideoLib.HLSPacketizer.packetize(fragment, sampleBuffers); // Now buffer contains MPEG-TS chunk } } catch (ex) { console.error('Error:', ex); } finally { fs.closeSync(fd); } ``` ### Build MP4 file ```javascript const fs = require('fs'); const VideoLib = require('node-video-lib'); let fd = fs.openSync('/path/to/file', 'r'); try { let movie = VideoLib.MovieParser.parse(fd); let fw = fs.openSync('/path/to/output.mp4', 'w'); try { VideoLib.MP4Builder.build(movie, fd, fw); } catch (ex) { console.error('Error:', ex); } finally { fs.closeSync(fw); } } catch (ex) { console.error('Error:', ex); } finally { fs.closeSync(fd); } ``` ### Create index file ```javascript const fs = require('fs'); const VideoLib = require('node-video-lib'); let fd = fs.openSync('/path/to/file', 'r'); try { let movie = VideoLib.MovieParser.parse(fd); let fragmentList = VideoLib.FragmentListBuilder.build(movie, 5); console.log('Duration:', fragmentList.relativeDuration()); let fdi = fs.openSync('/path/to/index.idx', 'w'); try { VideoLib.FragmentListIndexer.index(fragmentList, fdi); } catch (ex) { console.error('Error:', ex); } finally { fs.closeSync(fdi); } } catch (ex) { console.error('Error:', ex); } finally { fs.closeSync(fd); } ``` ### Create MPEG-TS chunks using index file ```javascript const fs = require('fs'); const VideoLib = require('node-video-lib'); let fd = fs.openSync('/path/to/file', 'r'); let fdi = fs.openSync('/path/to/index.idx', 'r'); try { let fragmentList = VideoLib.FragmentListIndexer.read(fdi); console.log('Duration:', fragmentList.relativeDuration()); for (let i = 0; i < fragmentList.count(); i++) { let fragment = fragmentList.get(i); let sampleBuffers = VideoLib.FragmentReader.readSamples(fragment, fd); let buffer = VideoLib.HLSPacketizer.packetize(fragment, sampleBuffers); // Now buffer contains MPEG-TS chunk } } catch (ex) { console.error('Error:', ex); } finally { fs.closeSync(fd); fs.closeSync(fdi); } ``` ## Classes ### MovieParser A tool for parsing video files (MP4 or FLV). ```javascript const MovieParser = require('node-video-lib').MovieParser ``` Methods: * **parse(source)** - Parse video file * **source** *\*|[*\*](https://nodejs.org/api/buffer.html) - Source (File descriptor or Buffer) * Return: [*\*](#movie) ### MP4Parser A tool for parsing MP4 video files. ```javascript const MP4Parser = require('node-video-lib').MP4Parser ``` Methods: * **parse(source)** - Parse MP4 file * **source** *\*|[*\*](https://nodejs.org/api/buffer.html) - Source (File descriptor or Buffer) * Return: [*\*](#movie) * **check(buffer)** - Check MP4 header * **buffer** [*\*](https://nodejs.org/api/buffer.html) - File header (first 8 bytes) * Return: *\* ### FLVParser A tool for parsing FLV video files. ```javascript const FLVParser = require('node-video-lib').FLVParser ``` Methods: * **parse(source)** - Parse FLV file * **source** *\*|[*\*](https://nodejs.org/api/buffer.html) - Source (File descriptor or Buffer) * Return: [*\*](#movie) * **check(buffer)** - Check FLV header * **buffer** [*\*](https://nodejs.org/api/buffer.html) - File header (first 8 bytes) * Return: *\* ### MP4Builder A tool for building MP4 video files. ```javascript const MP4Builder = require('node-video-lib').MP4Builder ``` Methods: * **build(movie, source, fd)** - Build MP4 file * **movie** [*\*](#movie) - Movie * **source** *\*|[*\*](https://nodejs.org/api/buffer.html) - Source (File descriptor or Buffer) * **fd** *\* - File descriptor ### HLSPacketizer A tool for creating MPEG-TS chunks. ```javascript const HLSPacketizer = require('node-video-lib').HLSPacketizer ``` Methods: * **packetize(fragment, sampleBuffers)** - Create MPEG-TS chunk from movie fragment * **fragment** [*\*](#fragment) - Movie fragment * **sampleBuffers** *\* - Array of buffers * Return: [*\*](https://nodejs.org/api/buffer.html) ### FragmentListBuilder A tool for splitting the movie into a list of fragments. ```javascript const FragmentListBuilder = require('node-video-lib').FragmentListBuilder ``` Methods: * **build(movie, fragmentDuration)** - Split the movie to a list of fragments with an appropriate duration * **movie** [*\*](#movie) - Movie * **fragmentDuration** *\* - Fragment duration * Return: [*\*](#fragmentlist) ### FragmentListIndexer A tool to work with index files. ```javascript const FragmentListIndexer = require('node-video-lib').FragmentListIndexer ``` Methods: * **index(fragmentList, fd)** - Index fragment list * **fragmentList** [*\*](#fragmentlist) - Fragment list * **fd** *\* - File descriptor * **read(fd)** - Read fragment list from index * **fd** *\* - File descriptor * Return: [*\*](#fragmentlist) ### FragmentReader A tool for reading samples data of the given movie fragment. ```javascript const FragmentReader = require('node-video-lib').FragmentReader ``` Methods: * **readSamples(fragment, source)** - Read samples data * **fragment** [*\*](#fragment) - Movie fragment * **source** *\*|[*\*](https://nodejs.org/api/buffer.html) - Source (File descriptor or Buffer) * Return: *\* Array of buffers ### Movie A movie class ```javascript const Movie = require('node-video-lib').Movie ``` Properties: * **duration** *\* - Movie duration * **timescale** *\* - Movie timescale * **tracks** *\* - List of movie tracks Methods: * **relativeDuration()** - Movie duration in seconds * Return: *\* * **resolution()** - Video resolution * Return: *\* * **size()** - Samples size * Return: *\* * **addTrack(track)** - Add a track to the tracks list * **track** *\* - Track * **videoTrack()** - Get the first video track * Return: *\* * **audioTrack()** - Get the first audio track * Return: *\* * **samples()** - Get a list of movie samples ordered by relative timestamp * Return: *\* * **ensureDuration()** - Calculate and set duration based on the track durations (only if duration is zero) * Return: *\* ### FragmentList A list of movie fragments class. ```javascript const FragmentList = require('node-video-lib').FragmentList ``` Properties: * **fragmentDuration** *\* - Target fragment duration * **duration** *\* - Movie duration * **timescale** *\* - Movie timescale * **video** *\* - Video info * **timescale** *\* - Video timescale * **codec** *\* - Codec string * **extraData** [*\*](https://nodejs.org/api/buffer.html) - Video codec information * **size** *\* - Video samples size * **width** *\* - Video width * **height** *\* - Video height * **audio** *\* - Audio info * **timescale** *\* - Audio timescale * **codec** *\* - Codec string * **extraData** [*\*](https://nodejs.org/api/buffer.html) - Audio codec information * **size** *\* - Audio samples size Methods: * **relativeDuration()** - Movie duration in seconds * Return: *\* * **maxFragmentDuration()** - Maximum fragment duration in seconds * Return: *\* * **count()** - Fragments count * Return: *\* * **size()** - Samples size * Return: *\* * **get(index)** - Get fragment by index * Return: [*\*](#fragment) ### Fragment A movie fragment class ```javascript const Fragment = require('node-video-lib').Fragment ``` Properties: * **timestamp** *\* - Fragment timestamp * **duration** *\* - Fragment duration * **timescale** *\* - Fragment timescale * **videoExtraData** [*\*](https://nodejs.org/api/buffer.html) - Video codec information * **audioExtraData** [*\*](https://nodejs.org/api/buffer.html) - Audio codec information * **samples** *\* - List of fragment samples Methods: * **relativeTimestamp()** - Fragment timestamp in seconds * Return: *\* * **relativeDuration()** - Fragment duration in seconds * Return: *\* * **hasVideo()** - Fragment has a video track * Return: *\* * **hasAudio()** - Fragment has an audio track * Return: *\* ### Track A general track class ```javascript const Track = require('node-video-lib').Track ``` Properties: * **duration** *\* - Track duration * **timescale** *\* - Track timescale * **codec** *\* - Codec string * **extraData** [*\*](https://nodejs.org/api/buffer.html) - Codec information * **samples** *\* - List of track samples Methods: * **relativeDuration()** - Track duration in seconds * Return: *\* * **ensureDuration()** - Calculate and set duration based on the sample durations (only if duration is zero) * Return: *\* * **size()** - Samples size * Return: *\* ### AudioTrack An audio track class. Extends the general track class ```javascript const AudioTrack = require('node-video-lib').AudioTrack ``` Properties: * **channels** *\* - Number of audio channels * **sampleRate** *\* - Audio sample rate * **sampleSize** *\* - Audio sample size ### VideoTrack A video track class. Extends the general track class ```javascript const VideoTrack = require('node-video-lib').VideoTrack ``` Properties: * **width** *\* - Video width * **height** *\* - Video height Methods: * **resolution()** - Video resolution * Return: *\* ### Sample A general video sample class ```javascript const Sample = require('node-video-lib').Sample ``` Properties: * **timestamp** *\* - Sample timestamp * **timescale** *\* - Sample timescale * **size** *\* - Sample size * **offset** *\* - Sample offset in the file Methods: * **relativeTimestamp()** - Sample timestamp in seconds * Return: *\* ### AudioSample An audio sample class. Extends the general sample class ```javascript const AudioSample = require('node-video-lib').AudioSample ``` ### VideoSample A video sample class. Extends the general sample class ```javascript const VideoSample = require('node-video-lib').VideoSample ``` Properties: * **compositionOffset** *\* - Composition offset * **keyframe** *\* - Keyframe flag