Repository navigation
v0.2.0
Minor Changes
-
#4
f59cf26Thanks @polvallverdu! -SOXRAudioResamplerandSOXRStreamAudioResamplernow resample instead of throwing "not ported yet" when the rates differ. This also fixescreateFileResampler(),createStreamResampler(), the μ-law/A-law helpers at other rates,loadDtmfAudio()at rates other than 8 kHz,LocalSmartTurnAnalyzerV3at rates other than 16 kHz, and output transports and TTS services whose rates differ. The resampling goes through a small engine interface in@pipedog/core/audio/resamplers/engine:- The default engine is
@pipedog/resampler-wasm, which core now depends on. It loads lazily on first use, and on Cloudflare Workers it loads through the package'sworkerdexport condition. - If WebAssembly cannot be loaded, core logs one warning and falls back to a pure-TypeScript windowed-sinc engine with soxr-like presets (
createSincResamplerEngine()). setResamplerEngine(engine)lets apps inject their own engine, for example a native soxr binding.getResamplerEngine()resolves to the engine in use.
The quality presets (VHQ by default, then HQ, MQ, LQ and QQ), clearing after inactivity,
flush()andreset()behave as before. Equal rates still return the input unchanged.@pipedog/resampler-wasm:initResampler()falls back to an embedded copy of the module (src/wasm_bytes.ts) when the.wasmfile next to the package cannot be read, for example after bundling.@pipedog/resampler-wasm: the quality presets now follow libsoxr's quality table. The stopband starts at the Nyquist frequency of the lower rate. MQ, HQ and VHQ are flat to about 0.91 of it and differ mainly in attenuation: about 111, 138 and at least 157 dB. LQ (about 112 dB) and QQ (about 75 dB) have earlier roll-offs. The filter is stretched when downsampling, so it no longer leaks aliases at large ratios: a 5 kHz tone resampled from 48 kHz to 8 kHz is now 87 to 163 dB down, depending on the preset. Processing is now done in f64. Output samples, filter delays (about 8.5 ms at VHQ) andqualityInfo()values change; the output lengths do not. - The default engine is
-
#4
f59cf26Thanks @polvallverdu! - Fill four gaps in core that upstream tests exercise:- Resampling works:
SOXRAudioResampler,SOXRStreamAudioResamplerandsoxrResamplerun on
@pipedog/resampler-wasm(now a dependency) instead of throwing, so TTS services, output
transports and the audio buffer processor can convert sample rates. Callawait initSoxr()
before the synchronoussoxrResample; the async resamplers do it themselves. encodeImage()JPEG-encodes rawL/LA/RGB/RGBA/RGBXpixels with a built-in baseline
encoder (utils/jpeg_encoder), so raw image frames reach LLMs and classifiers.utils/yaml:includeLoader()/addIncludeConstructor()work, with a PyYAML-style
SafeLoader(YAML 1.1 resolvers, per-class constructors) andload()on top of theyaml
package. Included files are read with an injectedreadFile.LocalFileStoragesaves, loads, deletes and trims files through an injectedfs
(node:fs/promisesfits as is).
- Resampling works:
-
#4
f59cf26Thanks @polvallverdu! - Core is fully ported (all 361 upstream modules): the text transforms that make text speakable for
TTS (numbers, currency, dates, percentages, phone numbers, units, acronyms, email, markdown,
replacements, pronunciations,VoiceFormatter) and the WebSocket proxy client. Numbers are spoken
withnum2words-ts, as upstream usesnum2words; Unicode digits (e.g. "٥٠") are recognised and
read like upstream does. -
#6
72b8cb8Thanks @polvallverdu! - Local ONNX models.@pipedog/onnxis a small inference backend overonnxruntime-node(native,
fastest) oronnxruntime-web(WASM), both optional peer dependencies;createOnnxBackend()picks
the native one when it is installed. On Cloudflare Workers theworkerdexport condition runs
onnxruntime-web from its.wasmimported as a module.@pipedog/audio-sileroports
SileroVADAnalyzerwith the upstreamsilero_vad.onnxincluded, and
@pipedog/audio-smart-turnprovidescreateLocalSmartTurnAnalyzerV3(), core's analyzer wired to
an ONNX backend and the upstreamsmart-turn-v3.2-cpu.onnx. On Workers both models are passed in
as bytes. In core,VADAnalyzer.voiceConfidence()may now return a promise. -
#6
72b8cb8Thanks @polvallverdu! - OpenTelemetry tracing, as in Pipecat'spipecat-ai[tracing]extra, on Bun, Node, Deno and Cloudflare Workers.@pipedog/core:@opentelemetry/apiis now an optional peer dependency. When it is installed, core imports it on its own (a dynamicimport()started whenutils/tracing/setuploads, with no top-level await), andisTracingAvailable()turns true, like upstream'sis_tracing_available(). Without it, core runs as before and tracing stays a no-op.PipelineWorkerawaits that import in its async setup before deciding whether to trace, so construction order does not matter (a worker built at module top level traces too);loadOpenTelemetry()exposes the same wait.registerOpenTelemetry()still registers the modules explicitly and now wins over the automatic import. The structural OpenTelemetry types accept the real@opentelemetry/apiand@opentelemetry/sdk-trace-basemodules (array attribute values may holdnull/undefined, as in OpenTelemetry). Span names, attributes and hierarchy are unchanged and match upstream's.@pipedog/tracing(new):setupTracing({ serviceName, exporter, consoleExport }), matching upstream'ssetup_tracing(): it registers@opentelemetry/api,@opentelemetry/sdk-trace-baseand@opentelemetry/resourceswith core and installs a global tracer provider with batch span processors for the given exporter and, optionally, the console. It re-exportsOTLPTraceExporter(OTLP/HTTP JSON, from@opentelemetry/exporter-trace-otlp-http),ConsoleSpanExporter,InMemorySpanExporterand the span processors.forceFlushTracing()andshutdownTracing()export what the batch processors still hold, e.g.ctx.waitUntil(forceFlushTracing())on Cloudflare Workers.@opentelemetry/apiis a peer dependency.
Patch Changes
-
#7
122b72fThanks @polvallverdu! -@pipedog/asyncionow schedules like asyncio, so ported code interleaves exactly as it does in
Python. Waking a waiter (a future's result,Event.set(),Queue.put(), a task finishing, a
timer) no longer resumes it on the next microtask: the wakeup goes on a FIFO ready queue
(callSoon), and queued wakeups run one at a time, each once the microtask queue is empty. A task
therefore runs until it awaits something that is not done;get()on a non-empty queue,put()on
an unbounded one,wait()on a set event and awaiting a done task do not let any other task run,
andsleep(0)yields exactly one turn. The turn is driven by a MessageChannel on Node,
setImmediateon Bun and Deno, and a body read on Cloudflare Workers.- New:
Future(asyncio.Future:setResult,setException,cancel, done callbacks; awaitable),
callSoon/callLaterreturning a cancellableHandle,isFuture.TaskextendsFuture. Event,Queue(andPriorityQueue,LifoQueue),Lock,Semaphore,gather,wait,
shield,waitForandtimeoutare ported from CPython on top ofFuture, with its wakeup
rules: a wokenget()takes whatever is at the head when it runs (so aPriorityQueuehands
out the smallest item of a burst), a cancellation that arrives after the wakeup was queued wins,
gatherraises a cancellation once its children are done, andaddDoneCallbackcallbacks run
on the ready queue.waitFor(fn, t)andtimeout(t, fn)runfnin the current task, like Python 3.12+: on
expiry the task is cancelled and theCancelledErrorbecomesTimeoutError. When every
cancellation request has been withdrawn withuncancel(),task.signalis a fresh signal.Queueuses O(1) removal from the front (it usedArray.shift(), which is O(n) on V8 and made
long queues quadratic on Node, Deno and Workers).- 32 interleaving scenarios recorded from CPython 3.14 (
test/python/scenarios.py) are replayed in
the tests and in the compat smoke test on all four runtimes.
@pipedog/core:LLMAssistantAggregatorruns the LLM once for a burst of
LLMMessagesAppendFrame/FunctionCallResultFrameinstead of once per frame. Its
hasQueuedFrame(...)check now sees the later frames of the burst queued, as upstream does, so
there are no more duplicate responses. Other frame orderings that depend on asyncio scheduling
(system frames overtaking queued data frames, bus priority, interruption handling) now match
upstream too. - New:
-
Updated dependencies [
122b72f,f59cf26]:- @pipedog/asyncio@0.2.0
- @pipedog/resampler-wasm@0.2.0
- @pipedog/sentencex-wasm@0.2.0
All @pipedog/* packages are released at 0.2.0: