-
Notifications
You must be signed in to change notification settings - Fork 188
Emy Storage
Emy storage was implemented after multiple requests for persistent storage for audio fingerprints generated by the SoundFingerprinting
library. It powers emysound.com, a commercial cloud version of it. Almost everything available in the cloud is also available in the Docker community edition. The community edition is free for non-commercial use.
First thing, you need to start Docker container for Emy.
docker run -d -p 3399:3399 -p 3340:3340 addictedcs/soundfingerprinting.emy:latest
Once it is started, you can access the dashboard at the following address: http://localhost:3340.
The Swagger for the JSON API that Emy offers is available on http://localhost:3340/docs.
The next thing you can do is insert tracks, using the tracks page.
Once inserted, you can start monitoring external broadcasts using the streams page. By enabling the checkbox Save audio for matches playback, Emy will store matched regions that you will be able to playback on the Query Match Page.
Query matches page will show all matches that happened on any particular stream.
The below program will insert a list of tracks from the specified directory into Emy. Please note that it uses SoundFingerprinting.Emy.
Create a new .NET Core app.
dotnet new console -f net6.0 -n Emy.Test
To install the NuGet package, navigate into the project directory cd Emy.Test
and use the following command:
dotnet add package SoundFingerprinting.Emy
Copy the following program into Program.cs
.
namespace Emy.Test
{
using System;
using System.IO;
using System.Threading.Tasks;
using SoundFingerprinting.Audio;
using SoundFingerprinting.Builder;
using SoundFingerprinting.Data;
using SoundFingerprinting.Emy;
class Program
{
private static readonly EmyModelService ModelService = EmyModelService.NewInstance("localhost", 3399);
private static readonly IAudioService AudioService = new FFmpegAudioService();
static async Task Main(string[] args)
{
if (args.Length < 1)
{
Console.WriteLine("Specify directory for inserting data");
return;
}
var directory = args[0];
foreach (string file in Directory.GetFiles(directory))
{
if (ModelService.ReadTrackById(file) != null)
{
Console.WriteLine($"We've already inserted {file}. Skipping.");
continue;
}
var track = new TrackInfo(file, Path.GetFileNameWithoutExtension(file), string.Empty);
var hashes = await FingerprintCommandBuilder
.Instance
.BuildFingerprintCommand()
.From(file)
.UsingServices(AudioService)
.Hash();
ModelService.Insert(track, hashes);
Console.WriteLine($"Inserted {file} with {hashes.Count} fingerprints.");
}
}
}
}
Compile the project (from the same Emy.Test directory).
dotnet clean -c Release && dotnet build -c Release
Now you are ready to run it. Specify the directory with files as a program argument.
cd bin/Release/net6.0
dotnet Emy.Test.dll <PATH_TO_DIRECTORY_WITH_AUDIO_FILES>
You can navigate into the Tracks tab at http://localhost:3340/tracks and check if the files are getting inserted.
FFmpegAudioService
is used in this example since it's the best decoding and downsampling implementation. For those who don't know ffmpeg is an external library that has to be installed on the running machine. Installation steps can be found here.
Similar to insertion, in order to query you can use the following code snippet.
static async Task Query(string pathToQueryFile)
{
var result = await QueryCommandBuilder.Instance
.BuildQueryCommand()
.From(pathToQueryFile)
.UsingServices(ModelService, AudioService)
.Query();
if (result.ContainsMatches)
{
foreach (var (entry, _) in result.ResultEntries)
{
if (entry?.Confidence > 0.3)
{
Console.WriteLine($"Found {entry.Track.Id} with coverage {entry.TrackRelativeCoverage}");
Console.WriteLine($"Query match starts at: {entry.QueryMatchStartsAt:0.00}");
Console.WriteLine($"Track match starts at: {entry.TrackMatchStartsAt:0.00}");
ModelService.RegisterMatches(new []{entry}, new Dictionary<string, string>());
}
}
}
}
Note how we register the match by calling RegisterMatches
. This will persist match information in Emy storage. Navigate to http://localhost:3340/matches Matches tab to view the latest query matches.
List of other available storage is available here.
You can use Emy by taking advantage of its rich API interface available on http://localhost:3340/docs. The description of the available methods can be viewed here: https://emysound.readme.io