Documentation
¶
Overview ¶
Package phonmatchnet detects text-defined wake words in 16 kHz mono PCM with naptrap's PhonMatchNet model and ONNX Runtime.
Example ¶
Detect a keyword in one clip. The models are embedded, so no paths are needed.
package main
import (
"context"
"fmt"
"log"
phonmatchnet "github.com/androiddrew/go-phonmatchnet"
)
// loadClip stands in for the application's audio decoding. The engine requires
// one 0.5-2 second clip of 16 kHz mono float32 PCM in [-1, 1].
func loadClip() []float32 { return make([]float32, phonmatchnet.SampleRate) }
func main() {
engine, err := phonmatchnet.New(phonmatchnet.Config{
ORTLibrary: "libonnxruntime.so", // OS loader name or a path to the library
})
if err != nil {
log.Fatal(err)
}
defer engine.Close()
ctx := context.Background()
keyword, err := engine.Keyword(ctx, "hey computer") // reuse across clips
if err != nil {
log.Fatal(err)
}
result, err := engine.Detect(ctx, phonmatchnet.Request{
Samples: loadClip(), SampleRate: phonmatchnet.SampleRate, Keyword: keyword,
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("score %.3f accepted %v\n", result.Score, result.Accepted)
}
Output:
Example (CallerOwnedEnvironment) ¶
An application that already initializes ONNX Runtime itself leaves ORTLibrary empty. The engine then uses that environment and never destroys it.
package main
import (
"fmt"
"log"
phonmatchnet "github.com/androiddrew/go-phonmatchnet"
ort "github.com/yalue/onnxruntime_go"
)
func main() {
ort.SetSharedLibraryPath("libonnxruntime.so")
if err := ort.InitializeEnvironment(); err != nil {
log.Fatal(err)
}
defer ort.DestroyEnvironment() // runs after engine.Close
engine, err := phonmatchnet.New(phonmatchnet.Config{})
if err != nil {
log.Fatal(err)
}
defer engine.Close()
fmt.Println(engine.Initialization().RuntimeVersion)
}
Output:
Index ¶
- Constants
- Variables
- func NormalizeKeyword(text string) (string, error)
- type Config
- type Engine
- func (e *Engine) Close() error
- func (e *Engine) Detect(ctx context.Context, r Request) (Result, error)
- func (e *Engine) Initialization() Initialization
- func (e *Engine) Keyword(ctx context.Context, text string) (Keyword, error)
- func (e *Engine) ModelInfo() ModelInfo
- func (e *Engine) Thresholds() map[float64]float64
- type GraphInfo
- type Initialization
- type Keyword
- type ModelInfo
- type Request
- type Result
- type TensorInfo
- type Timings
Examples ¶
Constants ¶
const ( MinSamples = SampleRate / 2 MaxSamples = 2 * SampleRate )
Clip length bounds: one clip of 0.5 to 2 seconds.
const DefaultFAR = 0.01
DefaultFAR selects the strictest calibrated operating point when Request.FAR is zero.
const MaxKeywordPositions = 128
MaxKeywordPositions bounds a keyword's text features: decoder steps plus one separator between words.
const SampleRate = 16000
SampleRate is the required input rate in Hz. Input is mono.
Variables ¶
var ( // ErrNotInitialized is returned by New when ORTLibrary is empty and the // caller has not initialized the ONNX Runtime environment. ErrNotInitialized = ortruntime.ErrNotInitialized // ErrClosed is returned by requests on a closed engine. ErrClosed = errors.New("phonmatchnet engine is closed") // ErrInvalidAudio reports a wrong sample rate, a clip outside 0.5-2 seconds, // or a sample that is nonfinite or outside [-1, 1]. ErrInvalidAudio = errors.New("invalid audio") // ErrInvalidKeyword reports keyword text with no English letters, with // digits, or longer than MaxKeywordPositions features. It is also returned // for a zero Keyword. ErrInvalidKeyword = errors.New("invalid keyword") // ErrUnknownFAR is returned when Request.FAR is not a calibrated operating // point; see Engine.Thresholds. ErrUnknownFAR = errors.New("FAR is not a calibrated operating point") )
Functions ¶
func NormalizeKeyword ¶
NormalizeKeyword applies the policy used during training: NFKD, accents and punctuation removed, lowercase, words joined by single spaces. Apostrophes inside words are kept. Numbers must be spelled out.
Types ¶
type Config ¶
type Config struct {
// ORTLibrary is an ONNX Runtime library path or OS-loader name. When set, the
// engine initializes the environment through ortenv, which retains it until
// process exit. When empty, the caller owns the environment and must
// initialize it before New and destroy it only after Close.
ORTLibrary string
// ModelDir overrides the embedded models with a directory holding
// phonmatchnet/, google/ and g2p/ laid out like the embedded models/ (the
// three Hugging Face -onnx downloads). Usually empty.
ModelDir string
// Threads sets intra-op threads per session. Zero selects 1.
Threads int
}
Config selects the models and configures the sessions.
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine detects keywords. Requests and Close are serialized.
func New ¶
New loads and validates the models before accepting requests. Close is mandatory. Concurrent calls on one engine are serialized, including Close.
func (*Engine) Close ¶
Close destroys the sessions. It is idempotent. The ONNX Runtime environment stays initialized for other engines and later calls to New.
func (*Engine) Initialization ¶
func (e *Engine) Initialization() Initialization
Initialization returns how long New spent in each loading stage.
func (*Engine) Keyword ¶
Keyword normalizes text and computes its g2p decoder features. Each word is encoded, then decoded greedily; every decoder state before the end token is one feature row, and a separator row sits between words.
func (*Engine) Thresholds ¶
Thresholds returns the calibrated operating points: target false-accept rate to score threshold. Each was fitted on held-out development speakers; the achieved rate on other audio differs, so applications should validate a threshold on their own positive and negative clips and compare it with Result.Score.
Example ¶
Choose the more sensitive calibrated operating point, or compare Result.Score with a threshold validated on your own recordings.
package main
import (
"context"
"fmt"
"log"
phonmatchnet "github.com/androiddrew/go-phonmatchnet"
)
// loadClip stands in for the application's audio decoding. The engine requires
// one 0.5-2 second clip of 16 kHz mono float32 PCM in [-1, 1].
func loadClip() []float32 { return make([]float32, phonmatchnet.SampleRate) }
func main() {
engine, err := phonmatchnet.New(phonmatchnet.Config{ORTLibrary: "libonnxruntime.so"})
if err != nil {
log.Fatal(err)
}
defer engine.Close()
for far, threshold := range engine.Thresholds() {
fmt.Printf("target FAR %g: score >= %.4f\n", far, threshold)
}
keyword, err := engine.Keyword(context.Background(), "okay naptrap")
if err != nil {
log.Fatal(err)
}
result, err := engine.Detect(context.Background(), phonmatchnet.Request{
Samples: loadClip(), SampleRate: phonmatchnet.SampleRate, Keyword: keyword, FAR: 0.1,
})
if err != nil {
log.Fatal(err)
}
fmt.Println(result.Accepted)
}
Output:
type GraphInfo ¶
type GraphInfo struct {
Inputs []TensorInfo `json:"inputs"`
Outputs []TensorInfo `json:"outputs"`
}
GraphInfo describes one ONNX graph's inputs and outputs.
type Initialization ¶
type Initialization struct {
RuntimeVersion string `json:"runtime_version"`
RuntimeSeconds float64 `json:"runtime_initialization_seconds"`
ModelSeconds float64 `json:"model_load_seconds"`
}
Initialization is a diagnostic breakdown of New's loading time. ModelSeconds includes reading, hashing and inspecting the graphs as well as creating the sessions. RuntimeVersion is the loaded native ONNX Runtime version.
type Keyword ¶
type Keyword struct {
// contains filtered or unexported fields
}
Keyword holds a keyword's precomputed text features. Create it with Engine.Keyword and reuse it across clips. The zero Keyword is invalid.
type ModelInfo ¶
type ModelInfo struct {
Google GraphInfo `json:"google"`
Detector GraphInfo `json:"detector"`
G2PEncoder GraphInfo `json:"g2p_encoder"`
G2PDecoder GraphInfo `json:"g2p_decoder"`
}
ModelInfo describes the four loaded graphs.
type Request ¶
type Request struct {
Samples []float32 `json:"-"`
SampleRate int `json:"sample_rate"`
// Keyword comes from Engine.Keyword. Reuse it across clips.
Keyword Keyword `json:"-"`
// FAR selects the operating point by its target false-accept rate. Zero
// selects DefaultFAR.
FAR float64 `json:"far"`
}
Request scores one clip against a keyword. Samples must remain unmodified until Detect returns. No gain, clipping, trimming, channel conversion or resampling is performed.
type Result ¶
type Result struct {
Keyword string `json:"keyword"` // normalized keyword text
Score float64 `json:"score"`
Logit float64 `json:"logit"`
Threshold float64 `json:"threshold"`
TargetFAR float64 `json:"target_far"`
Accepted bool `json:"accepted"`
Timings Timings `json:"timings"`
}
Result is one detection. Score is sigmoid(Logit), the keyword-match probability. Accepted reports Score >= Threshold.
type TensorInfo ¶
type TensorInfo struct {
Name string `json:"name"`
Shape []int64 `json:"shape"`
Type string `json:"type"`
}
TensorInfo describes one graph input or output. Dynamic dimensions are -1.
type Timings ¶
type Timings struct {
EmbeddingSeconds float64 `json:"embedding_seconds"` // Google speech embedding graph
DetectorSeconds float64 `json:"detector_seconds"` // PhonMatchNet graph
}
Timings is a diagnostic breakdown of one Detect call. Each stage includes tensor creation, the synchronous Run and output validation.
Directories
¶
| Path | Synopsis |
|---|---|
|
internal
|
|
|
nativetest
Package nativetest runs native ONNX Runtime tests in fresh processes.
|
Package nativetest runs native ONNX Runtime tests in fresh processes. |
|
ortruntime
Package ortruntime decides who owns the process-global ONNX Runtime environment.
|
Package ortruntime decides who owns the process-global ONNX Runtime environment. |