video-hash
v1.0.0
Published
Generates unique fingerprints for video files
Downloads
18
Maintainers
Readme
video-hash
Algorithm to fingerprint videos with relatively high accuracy and returns a hash. Achieved by capturing screenshots at particular intervals, hashing the pixels of each screenshot and creating a single hash from all of the generated pixel hashes. This package uses FFmpeg to take screenshots and FFprobe to retrieve metadata. Please note that this package is going to be slow depending on the size of video you are fingerprinting.
Usage
Requirements
In order to use this package, you must have the following requirements met:
- FFmpeg installed and in your PATH or a local binary.
- You can use a package like ffmpeg-installer to provide precompiled binaries for your OS.
- FFprobe installed and in your PATH or a local binary.
- You can use a package like ffprobe-installer to provide precompiled binaries for your OS.
Install
npm install --save video-hash
Quick Start
This example shows how to get started using precompiled binaries:
npm install --save video-hash @ffmpeg-installer/ffmpeg @ffprobe-installer/ffprobe
const ffmpeg = require('@ffmpeg-installer/ffmpeg');
const ffprobe = require('@ffprobe-installer/ffprobe');
const vHash = require('video-hash')({
ffmpegPath: ffmpeg.path,
ffprobePath: ffprobe.path
});
async createFingerprint(videoPath) {
const video = vHash.video(videoPath);
try {
let hash = await video.hash();
return hash;
} catch(err) {
throw err;
}
}
API Documentation
video-hash
- video-hash
- VideoHash([options]) ⇒ this ⏏
- .video(videoPath) ⇒ Video
- .options : Object
- VideoHash([options]) ⇒ this ⏏
VideoHash([options]) ⇒ this ⏏
Function exported from this module. Call with options
object. May be called with or without new
.
Kind: Exported function
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| [options] | Object | {} | Optional options to pass into the module. |
| [options.ffmpegPath] | String | | Overrides the path to the ffmpeg
binary. If not provided, it will attempt to locate on the system. |
| [options.ffprobePath] | String | | Overrides the path to the ffprobe
binary. If not provided, it will attempt to locate on the system. |
| [options.hashAlgorithm] | String | 'sha256' | The hashing algorithm to use when generating the hash. Must be one of the available from crypto.createHash. |
| [options.tempDir] | String | os.tmpdir() | Overrides the temp directory where various metadata during hashing is stored. |
| [options.hashBits] | Number | 12 | Hash length when generating hashes of screenshots. The longer the value, the more unique. See imghash.hash. |
| [options.strength] | Number | 2 | The strength of the generated video hash. Must be a number between 0.1 and 10. Determines the percentage in which each screenshot is taken based on the video duration. Setting this option to a higher value will provide a stronger fingerprint, but will take longer to generate the hash. |
Example
// Using default options:
const vHash = require('video-hash')();
// With options:
const vHash = require('video-hash')({
// options...
});
vHash.video(videoPath) ⇒ Video
Prepares a video for hashing at the provided videoPath
. Returns a new instance of Video
.
Kind: instance method of VideoHash
Returns: Video - New instance of Video
.
Throws:
- Error If
videoPath
is not provided.
| Param | Type | Description | | --- | --- | --- | | videoPath | String | Path to video file to load for hashing. |
Example
const video = vHash.video('/path/to/some-video.mp4');
// => Video { ... }
vHash.options : Object
Compiled options object. All options except ffmpegPath
and ffprobePath
can be changed at any time.
Kind: static property of VideoHash
Video
Kind: global class
- Video
- new Video(options, video)
- video.hash() ⇒ Promise.<String>
- video.metadata() ⇒ Promise.<Object>
new Video(options, video)
Creates an instance of Video. This constructor cannot be called directly.
| Param | Type | Description |
| --- | --- | --- |
| options | Object | Options passed from VideoHash. |
| video | FfmpegCommand | Instance of FfmpegCommand
from fluent-ffmpeg
for the video. |
video.hash() ⇒ Promise.<String>
Generates the hash/fingerprint for a single video.
Kind: instance method of Video
Returns: Promise.<String> - The generated hash/fingerprint for the video.
Example
const vHash = require('video-hash')({
// options...
});
async function hashVideo(videoPath) {
const video = vHash.video(videoPath);
try {
let hash = await video.hash();
return hash;
} catch(err) {
throw err;
}
video.metadata() ⇒ Promise.<Object>
Returns basic metadata for a single video from ffprobe
.
Kind: instance method of Video
Returns: Promise.<Object> - The format
metadata object for the video. See metadata.
Example
async function getMetadata(videoPath) {
const video = vHash.video(videoPath);
let metadata = await video.metadata();
}
Algorithm
Video Hash uses a basic algorithm to generate a hash for a video that will provide consistent results each time for the same provided options. This works by taking captures at percentage-based intervals based off of the duration of the video. The module generates a number of captures to take from the video using an equation like:
⌈(⌈duration⌉ * strength)⌉
To simplify, the video duration is rounded up to the nearest whole number and multiplied by the provided strength
option. The resulting number is then rounded
up to the nearest whole number. From there, the dependency fluent-ffmpeg
will generate an array of percentages based on the duration of the video for when
FFmpeg shoud capture a screenshot. If the duration of the video does not change, neither will the hash.
After all of the captures are taken by FFmpeg, each one is hashed using perceptual hashing and stored. Once the hashes are generated, all are combined and a final hash (SHA256 by default) is generated and returned.
Tests
To run tests locally, ensure you have all of the requirements installed and run:
npm test
Contributing
When contributing to this package, please follow the guidelines below:
- Ensure the there are no ESLint errors in the code, following the
.eslintrc.yml
file in the repo. - Write or update tests for any changes. I strive for 100% coverage, but 95% or higher is acceptable.
- Run the tests locally and ensure they pass.
- Commits must use the conventional commits spec. If you do not, your commit will fail.
- Submit a pull request.
License
MIT License