Release 2026-02-09: Merge staging with profiling toggle fix#34
Release 2026-02-09: Merge staging with profiling toggle fix#34
Conversation
The `transcribe` method is now fully implemented in `ParakeetModel`, supporting various features like streaming and timestamps. The TODO comment indicating it was an early scaffold was outdated and misleading. This commit removes that comment to improve documentation accuracy. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
globalThis.ort is sufficient as globalThis covers self in modern environments. This simplifies the code and removes an unnecessary check. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
- Replace dynamic `import(...)` with static top-level imports for `ParakeetModel`, `getParakeetModel`, and `MODELS`. - Remove `await` on imports. - Update `fromUrls` and `fromHub` to use imported modules. - Add `tests/index.test.mjs` to verify `fromUrls` and `fromHub` behavior. - Ensure `package-lock.json` is consistent with `package.json`. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
- Updated `transcribe` method in `src/parakeet.js` to accept `enableProfiling` option. - Changed performance logging logic to depend on `debug` or `enableProfiling` options. - Added test case `tests/transcribe_perf.test.mjs` to verify conditional metrics collection. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
…wMel` and `normalizeFeatures` This change eliminates duplicated logic in the `process` method of `JsPreprocessor` by reusing the existing `computeRawMel` and `normalizeFeatures` methods. This improves maintainability and ensures consistency between full and incremental processing pipelines. The logic for handling empty audio or zero features is preserved. All tests in `tests/mel.test.mjs` and `tests/test_mel.mjs` pass. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Consolidates redundant method implementations in IncrementalMelProcessor. The clear() method now calls reset() to ensure consistent behavior and reduce code duplication. Verified with updated tests in tests/mel.test.mjs. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Add `maxIncrementalCacheSize` option (default 50) to ParakeetModel constructor and `clearIncrementalCache()` method. Implement LRU eviction logic in `transcribe` to prevent unbounded growth of `_incrementalCache` during long-running sessions. Fixes potential memory leak where unique cache keys would accumulate indefinitely. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Replaced hardcoded version string in `src/backend.js` with `ort.env.versions.common`. This ensures that the WASM binary URL always matches the loaded JS runtime version, improving maintainability and preventing version mismatches. Added error handling if the version cannot be detected. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Replaced `Array.prototype.slice()` with `TypedArray.prototype.subarray()` for `tokenLogits` and `durLogits` extraction. This creates a view on the existing buffer instead of copying data, resulting in a ~22x speedup for this operation in microbenchmarks (25ms -> 1ms for 10M iterations). Verified with `bun test` and benchmark script. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
- Modify `JsPreprocessor.computeRawMel` to accept `startFrame` to skip redundant STFT/Mel computations for cached prefixes. - Update `IncrementalMelProcessor.process` to utilize `startFrame` for a ~3x speedup in streaming scenarios (26ms vs 78ms). - Refactor `IncrementalMelProcessor.process` non-cached path to avoid double computation, yielding a ~2x speedup (78ms vs 153ms). Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
- Pre-compute sanitized tokens (SentencePiece marker replacement) in `ParakeetTokenizer` constructor. - Use `this.sanitizedTokens` lookup in `decode` method instead of repeated regex replacement. - Optimize blank token check to use integer comparison (`id === this.blankId`) instead of string comparison. - Benchmark showed ~36% speedup (748ms -> 477ms for 1M tokens). Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
…60191462' into staging/release-2026-02-09
…893802667249' into staging/release-2026-02-09
…49377570' into staging/release-2026-02-09
…93746588552' into staging/release-2026-02-09
…53576085822775' into staging/release-2026-02-09
…5019006915315' into staging/release-2026-02-09
…8603949' into staging/release-2026-02-09
…353489943' into staging/release-2026-02-09
…2663042696932520' into staging/release-2026-02-09
…163951053442' into staging/release-2026-02-09
…74266680745745899' into staging/release-2026-02-09
…0997344201347' into staging/release-2026-02-09
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@tests/transcribe_perf.test.mjs`:
- Around line 22-24: The mock encoder output shape doesn't match how parakeet.js
extracts the tensor: parakeet code does enc = encOut['outputs'] ??
Object.values(encOut)[0] and then uses enc.dims, so update the test's
mockEncoderSession.run to resolve to a tensor-like object (i.e., the resolved
value should be an object whose top-level properties are dims and data) or
ensure the 'outputs' key itself is the tensor-like object; modify
mockEncoderSession.run.mockResolvedValue accordingly so it returns either {
dims: [1,64,10], data: new Float32Array(640) } or { outputs: { dims: [...],
data: ... } } to match how enc is consumed in parakeet.js (referencing
mockEncoderSession.run, encOut and enc).
🧹 Nitpick comments (2)
tests/index.test.mjs (2)
31-51: Consider adding test coverage for model key resolution.The
fromHubfunction resolves model keys viaMODELS[repoIdOrModelKey]?.repoId(seesrc/index.jsline 33), but this test only covers the pass-through case where the input is not a known model key. Consider adding a test case that verifies the model key resolution path:it('fromHub should resolve model key to repo ID', async () => { // You'd need to mock MODELS or use an actual key from MODELS // to verify that the resolved repoId is passed to getParakeetModel });
24-52: Add mock cleanup between tests.If additional tests are added later, mock state from previous tests could leak and cause flaky behavior. Consider adding:
describe('index.js', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + it('fromUrls should call ParakeetModel.fromUrls', async () => {
| const mockEncoderSession = { | ||
| run: vi.fn().mockResolvedValue({ outputs: { dims: [1, 64, 10], data: new Float32Array(640) } }), | ||
| }; |
There was a problem hiding this comment.
Mock encoder output format may not match actual usage.
The mock returns { outputs: { dims: [...], data: ... } }, but in parakeet.js line 543, the code does enc = encOut['outputs'] ?? Object.values(encOut)[0], then later accesses enc.dims. This means enc should be a tensor-like object directly, not a wrapper with dims inside.
Proposed fix for mock format
const mockEncoderSession = {
- run: vi.fn().mockResolvedValue({ outputs: { dims: [1, 64, 10], data: new Float32Array(640) } }),
+ run: vi.fn().mockResolvedValue({
+ outputs: new mockOrt.Tensor('float32', new Float32Array(640), [1, 64, 10])
+ }),
};🤖 Prompt for AI Agents
In `@tests/transcribe_perf.test.mjs` around lines 22 - 24, The mock encoder output
shape doesn't match how parakeet.js extracts the tensor: parakeet code does enc
= encOut['outputs'] ?? Object.values(encOut)[0] and then uses enc.dims, so
update the test's mockEncoderSession.run to resolve to a tensor-like object
(i.e., the resolved value should be an object whose top-level properties are
dims and data) or ensure the 'outputs' key itself is the tensor-like object;
modify mockEncoderSession.run.mockResolvedValue accordingly so it returns either
{ dims: [1,64,10], data: new Float32Array(640) } or { outputs: { dims: [...],
data: ... } } to match how enc is consumed in parakeet.js (referencing
mockEncoderSession.run, encOut and enc).
Post-merge review of all PRs included in this staging branchAll PRs in this branch (#18-#31) were created by Google Jules (coding agent). I reviewed every diff for correctness, backward compatibility, and potential risks. Below is the full assessment. Safe -- No Issues Found
Needs Attention -- Issues Filed#28 - #20 - Dynamic imports replaced with static imports (Medium risk) #21 - Performance logging made conditional (Medium-High risk, handled by @ysdede) #25 - LRU eviction for incremental decoder cache (Medium risk) #26 - Derive ort version from runtime (Medium-High risk) Excluded PRs (correct decisions)
Overall AssessmentThe agent produced reasonable, well-tested changes. Most are genuinely useful (mel optimization, tokenizer speedup, LRU cache, deduplication). However, it was too eager to "improve" things without considering backward compatibility:
Recommendation: Address issues #35, #36, #37, #38 before merging this staging branch into release. #36 (ort version fallback) is the highest priority since it can cause hard failures. |
Merges staging/release-2026-02-09 into release branch.
Includes:
All tests passing (77 tests).
Summary by CodeRabbit
New Features
Bug Fixes
Performance