Prdb.Hashing
0.1.0
dotnet add package Prdb.Hashing --version 0.1.0
NuGet\Install-Package Prdb.Hashing -Version 0.1.0
<PackageReference Include="Prdb.Hashing" Version="0.1.0" />
<PackageVersion Include="Prdb.Hashing" Version="0.1.0" />
<PackageReference Include="Prdb.Hashing" />
paket add Prdb.Hashing --version 0.1.0
#r "nuget: Prdb.Hashing, 0.1.0"
#:package Prdb.Hashing@0.1.0
#addin nuget:?package=Prdb.Hashing&version=0.1.0
#tool nuget:?package=Prdb.Hashing&version=0.1.0
Prdb.Hashing
Computes the osHash and pHash values that the
prdb Public API identifies video files by — the same
values Stash computes, bit for bit.
Separate from the Prdb.Sdk package on purpose: this one starts processes and
needs ffmpeg, which an HTTP client has no business doing. Use them together or
either alone.
Install
dotnet add package Prdb.Hashing
The perceptual hash shells out to ffmpeg and ffprobe, which have to be on
PATH or configured explicitly. OSHash does not need them.
Use
using Prdb.Hashing;
// OSHash: cheap, exact, and null for a file under 128 KiB.
string? osHash = OsHash.Compute("/media/scene.mkv");
// Perceptual hash: decodes 25 frames, so it belongs in a background queue.
var hasher = new VideoPerceptualHasher();
var result = await hasher.ComputeAsync("/media/scene.mkv");
if (result.IsComputed)
Console.WriteLine(result.Hash); // 16 lowercase hex characters
else
Console.WriteLine(result.Outcome); // ProbeFailed, FrameCaptureFailed, TimedOut, ...
Point it at a specific ffmpeg, and give it longer on slow storage:
var hasher = new VideoPerceptualHasher(new VideoHashingOptions
{
FfmpegPath = "/opt/ffmpeg/bin/ffmpeg", // ffprobe is found next to it
FrameTimeout = TimeSpan.FromMinutes(5),
});
Compare two perceptual hashes by Hamming distance, never for equality:
int? distance = PerceptualHashDistance.Between(left, right);
if (distance <= PerceptualHashDistance.DefaultThreshold) // 8 of 64 bits, as Stash uses
// ... the same content in a different encode
Two things worth knowing
Failures are returned, not thrown. On a real library, a truncated download or a container ffmpeg cannot seek is routine. A caller working through a backlog needs to record the outcome against that file and carry on, so only cancellation propagates.
Casing differs across the API boundary. This package produces lowercase hex;
the API normalises to uppercase on write. Its validation is case-insensitive, so
lookups work either way — but a local store usually compares bytes, and there a
mirrored uppercase hash never matches a locally computed one. The miss is
silent. FileHashes.Normalize and FileHashes.ForPrdbLookup convert in each
direction.
Compatibility
The method is specified in
docs/video-hashing.md,
in enough detail to reimplement from, with public test vectors. This package is
a transcription of it and reproduces the reference's quirks deliberately — a
perceptual hash that does not match what everyone else computes is worth very
little.
License
MIT — see LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0 | 1,163 | 8/9/2026 |