Skip to content

feat: simplify and standardize examples #412

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 27, 2025
Merged

feat: simplify and standardize examples #412

merged 1 commit into from
Jun 27, 2025

Conversation

lukeocodes
Copy link
Contributor

@lukeocodes lukeocodes commented Jun 27, 2025

  • Standardize all examples to use 'nova-3' or 'aura-asteria-en' models
  • Update live transcription examples to stream from a consistent source
  • Add simple, clear READMEs and secure API key handling for all examples
  • Remove obsolete 'test/' directory to clean up the project structure

Summary by CodeRabbit

  • New Features

    • Added new example projects and documentation for live and prerecorded transcription, text analysis, and text-to-speech using the Deepgram JS SDK.
    • Introduced interactive browser demos for live and prerecorded audio transcription.
  • Bug Fixes

    • None.
  • Documentation

    • Simplified and updated README files across examples and test directories for clearer setup and usage instructions.
    • Added detailed READMEs for each new example to guide users.
  • Refactor

    • Streamlined and modernized example scripts for improved clarity, usability, and minimal setup.
    • Updated example code to use the latest models and simplified event handling.
  • Chores

    • Added .gitignore files to example directories to exclude dependencies, environment files, and generated outputs.
    • Added package.json files to example projects for dependency management.
  • Tests

    • Removed deprecated or redundant test files and simplified test documentation.

- Standardize all examples to use 'nova-3' or 'aura-asteria-en' models
- Update live transcription examples to stream from a consistent source
- Add simple, clear READMEs and secure API key handling for all examples
- Remove obsolete 'test/' directory to clean up the project structure
@lukeocodes lukeocodes requested a review from jpvajda June 27, 2025 16:57
Copy link
Contributor

coderabbitai bot commented Jun 27, 2025

Walkthrough

This update restructures and simplifies the example and test directories for the Deepgram JS SDK. It introduces new and revised README files, updates and refactors example scripts for clarity and modern usage, adds or updates .gitignore and package.json files for Node.js examples, removes obsolete files, and streamlines test documentation.

Changes

File(s) Summary
README.md, examples/README.md, tests/README.md Updated and condensed documentation; replaced or simplified instructions and overview content.
examples/browser-live/README.md, examples/browser-prerecorded/README.md,
examples/node-agent-live/README.md, examples/node-live-token/README.md,
examples/node-live/README.md, examples/node-prerecorded/README.md,
examples/node-read/README.md, examples/node-speak-live/README.md,
examples/node-speak/README.md Added new README files for each example with setup and usage instructions.
examples/browser-live/index.html, examples/browser-prerecorded/index.html Refactored browser examples: added UI, improved API key handling, updated to use latest models and features.
examples/node-agent-live/index.js, examples/node-live-token/index.js,
examples/node-live/index.js, examples/node-prerecorded/index.js,
examples/node-read/index.js, examples/node-speak-live/index.js,
examples/node-speak/index.js Refactored Node.js example scripts for clarity, modern usage, and simplified event handling.
examples/node-agent-live/package.json, examples/node-live-token/package.json,
examples/node-live/package.json, examples/node-prerecorded/package.json,
examples/node-read/package.json, examples/node-speak-live/package.json,
examples/node-speak/package.json Added new package.json files for Node.js examples with metadata and dependencies.
examples/node-agent-live/.gitignore, examples/node-live-token/.gitignore,
examples/node-live/.gitignore, examples/node-prerecorded/.gitignore,
examples/node-read/.gitignore, examples/node-speak-live/.gitignore,
examples/node-speak/.gitignore Added or updated .gitignore files to exclude dependencies, environment files, and generated outputs.
examples/disabled_deno-prerecorded/index.js, test/enhanced_websocket_errors.test.ts Removed obsolete Deno example and a detailed WebSocket error handling test suite.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ExampleScript
    participant DeepgramClient
    participant DeepgramAPI

    User->>ExampleScript: Provide API key / Start example
    ExampleScript->>DeepgramClient: Initialize with API key
    DeepgramClient->>DeepgramAPI: Authenticate and connect
    User->>ExampleScript: Trigger action (e.g., Start, Transcribe, Speak)
    ExampleScript->>DeepgramClient: Send audio/text or request transcription
    DeepgramClient->>DeepgramAPI: Stream data / request processing
    DeepgramAPI-->>DeepgramClient: Return transcript/audio
    DeepgramClient-->>ExampleScript: Emit event with result
    ExampleScript-->>User: Display transcript/audio or log output
Loading

Possibly related PRs

Suggested reviewers

  • naomi-lgbt
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Post Copyable Unit Tests in Comment
  • Commit Unit Tests in branch lo/improve-readme

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@jpvajda jpvajda merged commit 81689db into main Jun 27, 2025
3 of 6 checks passed
@jpvajda jpvajda deleted the lo/improve-readme branch June 27, 2025 16:59
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

🔭 Outside diff range comments (1)
examples/browser-live/index.html (1)

39-63: Remove conflicting audio source configuration.

The code sets up both BBC stream fetching and MediaRecorder for microphone input, but only the microphone should be used for interactive live transcription.

        connection.on(deepgram.LiveTranscriptionEvents.Open, () => {
          console.log("Connection opened.");
-
-          fetch("http://stream.live.vc.bbcmedia.co.uk/bbc_world_service")
-            .then((response) => response.body)
-            .then((body) => {
-              const reader = body.getReader();
-              function read() {
-                reader
-                  .read()
-                  .then(({ done, value }) => {
-                    if (done) {
-                      console.log("Stream complete");
-                      return;
-                    }
-                    connection.send(value);
-                    read();
-                  })
-                  .catch((error) => {
-                    console.error("Stream read error:", error);
-                  });
-              }
-              read();
-            })
-            .catch((error) => {
-              console.error("Fetch error:", error);
-            });
        });
♻️ Duplicate comments (6)
examples/node-speak-live/index.js (1)

2-2: Same ESLint configuration issue as in other examples.

This file has the same TypeScript ESLint rule definition issues identified in the static analysis.

examples/node-speak/README.md (1)

5-12: Same prerequisite caveat as the live-transcription README

The “Setup” section assumes pnpm. Repeat the clarification about Node version and alternative package managers for consistency across READMEs.

examples/node-agent-live/README.md (1)

5-12: Prerequisite clarification

Mirror the note suggested for the other READMEs so users without pnpm are not surprised.

examples/node-live-token/README.md (1)

5-12: Prerequisite clarification

Same comment as above: mention required Node version and alternatives to pnpm.

examples/node-read/index.js (1)

2-2: ESLint configuration issue - same as other files.

This file has the same ESLint rule definition issues as examples/node-prerecorded/index.js. This is a project-wide configuration issue, not a code problem.

examples/node-agent-live/index.js (1)

1-2: Fix ESLint rule configuration issues.

The static analysis indicates that TypeScript ESLint rules are not found. This is a duplicate issue from the previous file.

🧹 Nitpick comments (22)
examples/node-agent-live/.gitignore (1)

2-4: Consider broader ignore patterns for .env and audio artifacts

Nice addition—ignoring node_modules and env files keeps the examples tidy.
Two optional tweaks:

  1. Environment files often appear with suffixes (.env.local, .env.production, etc.).

-.env
+.env*

2. The WAV ignore can be broadened in case future scripts write differently-named files:  
```diff
-output-*.wav
+*.wav

These are non-blocking; feel free to keep the current patterns if they better match the example conventions.

examples/node-live/.gitignore (1)

1-2: Consider ignoring lock-files as well

The examples are using pnpm, but users might swap to npm or yarn while experimenting. Adding the common lock-files keeps the repo clean and avoids accidental commits.

 node_modules
 .env
+package-lock.json
+yarn.lock
+pnpm-lock.yaml
examples/node-speak/.gitignore (1)

1-3: Minor: also ignore potential text-to-speech artefacts

If users change the output format or filename, auxiliary artefacts (e.g. .wav) could get committed. A wildcard keeps the intent but stays future-proof.

 output.mp3
+output.*
examples/node-speak-live/.gitignore (1)

1-3: Align ignore rules with other examples

For consistency with node-speak, consider the wildcard pattern so both live and non-live examples behave the same when filenames change.

 output.mp3
+output.*
examples/node-speak-live/package.json (1)

1-12: Mark the example package as private to avoid accidental npm publish

Adding "private": true prevents an inadvertent publish and matches typical example-app practice.

   "name": "deepgram-node-speak-live-example",
   "version": "1.0.0",
+  "private": true,
examples/node-live/package.json (1)

1-12: Add private flag for safety

Same reasoning as the speak-live example—marking the package private guards against an unintended publish.

   "name": "deepgram-node-live-example",
   "version": "1.0.0",
+  "private": true,
examples/node-prerecorded/.gitignore (1)

1-2: Consider broadening environment-file patterns

Ignoring .env is good, but teams often use variants like .env.local, .env.dev, etc. Adding a wildcard prevents accidental commits of secrets.

 node_modules
-.env
+.env*
examples/node-prerecorded/README.md (1)

1-20: Add missing prerequisite & output details

  1. Mention that the SDK must be built from the repo root before running:
    pnpm run build # from project root
  2. Clarify which audio file the script transcribes or how to pass a custom path.
  3. Note that the .env file can reside in either the example folder or repo root—newcomers often trip over dotenv path issues.
examples/node-read/README.md (1)

1-20: README could briefly describe expected console output

A single sentence like “The script logs the sentiment / topics JSON to the console” helps users know what success looks like.

examples/node-speak-live/README.md (1)

1-20: Mention generated artefact & playback requirement

The example writes output.mp3; indicate where the file is saved and that users need an MP3 player to hear the result. Small addition but improves UX.

examples/node-live/README.md (1)

5-12: Clarify tooling prerequisites & add npm/yarn alternatives

Not every user will have pnpm pre-installed. Consider adding a short prerequisite note (“requires Node ≥18 and pnpm (or run npm install / yarn as an alternative)”) so newcomers aren’t blocked.

 ## Setup
@@
-2.  Install the dependencies:
+2.  Install the dependencies  
+   *(requires `pnpm`; if you don’t use pnpm, replace with `npm install` or `yarn`)*:
examples/node-live-token/package.json (1)

1-12: Include basic metadata & mark example as private

Minor polish: adding private: true prevents accidental publishing, and including a license (even “UNLICENSED”) aligns with npm recommendations.

 {
   "name": "deepgram-node-live-token-example",
   "version": "1.0.0",
   "description": "A simple example of using a temporary token to transcribe a live audio stream in Node.js.",
+  "license": "UNLICENSED",
+  "private": true,
   "main": "index.js",
examples/node-read/package.json (1)

1-8: Mark example packages as private and declare type":"module"

index.js (added in the same PR) uses import syntax. Node treats that as ESM only if "type": "module" is set.
Also marking the package private prevents accidental npm publish.

 {
   "name": "deepgram-node-read-example",
+  "private": true,
   "version": "1.0.0",
@@
   "main": "index.js",
+  "type": "module",
examples/node-agent-live/package.json (1)

1-8: Consider ESM flag and private field

If index.js uses import you need "type": "module". Also mark as private.

 {
   "name": "deepgram-node-agent-live-example",
+  "private": true,
   "version": "1.0.0",
@@
   "main": "index.js",
+  "type": "module",
examples/node-speak/package.json (1)

1-8: Set "type": "module" and "private": true for consistency

Align with the other examples and avoid accidental publish.

 {
   "name": "deepgram-node-speak-example",
+  "private": true,
   "version": "1.0.0",
@@
   "main": "index.js",
+  "type": "module",
examples/browser-live/README.md (1)

17-20: Passing the API key as a query-string is convenient but insecure

Anyone who inspects browser history or server logs can read the key. For public/production demos prefer retrieving the key from a secured backend or a short-lived token endpoint instead of a persistent secret in the URL.

examples/browser-prerecorded/README.md (1)

17-20: Same security caveat about API key in URL

Storing the secret in a URL is fine for quick local demos but unsafe for anything else. Consider adding a short note or link to token-based auth here as well, mirroring the comment in the live example.

examples/node-prerecorded/index.js (1)

99-112: Add null safety for nested property access.

The new transcribe function is well-structured, but directly accessing result.results.channels[0].alternatives[0].transcript could throw a runtime error if the response structure is unexpected or incomplete.

Consider adding null safety:

  if (error) {
    console.error(error);
  } else {
-   console.log(result.results.channels[0].alternatives[0].transcript);
+   const transcript = result?.results?.channels?.[0]?.alternatives?.[0]?.transcript;
+   if (transcript) {
+     console.log(transcript);
+   } else {
+     console.log("No transcript found in response");
+   }
  }
examples/browser-prerecorded/index.html (2)

33-37: Add null safety for nested property access.

Similar to the Node.js example, directly accessing nested properties could cause runtime errors if the response structure is unexpected.

  if (error) {
    console.error(error);
  } else {
-   console.log(result.results.channels[0].alternatives[0].transcript);
+   const transcript = result?.results?.channels?.[0]?.alternatives?.[0]?.transcript;
+   console.log(transcript || "No transcript found in response");
  }

15-21: API key handling is acceptable for examples but not production.

Using URL query strings for API keys is convenient for examples but poses security risks in production. Consider adding a note in the documentation about secure API key handling practices.

Consider adding a comment in the code to clarify this is for example purposes only:

  const transcribe = async () => {
    const urlParams = new URLSearchParams(window.location.search);
+   // Note: For production applications, use secure methods to handle API keys
    const apiKey = urlParams.get("key");
examples/node-speak/index.js (2)

10-10: Add validation for the API key.

The code assumes the API key is available from environment variables but doesn't validate its presence, which could lead to runtime errors.

const speak = async () => {
+  if (!process.env.DEEPGRAM_API_KEY) {
+    console.error("DEEPGRAM_API_KEY environment variable is required");
+    process.exit(1);
+  }
  const deepgram = createClient(process.env.DEEPGRAM_API_KEY);

24-29: Consider using async stream processing utilities.

The manual Promise wrapper for stream processing could be simplified using Node.js stream utilities or async iterators for better readability and error handling.

-    const buffer = await new Promise((resolve, reject) => {
-      const chunks = [];
-      stream.on("data", (chunk) => chunks.push(chunk));
-      stream.on("end", () => resolve(Buffer.concat(chunks)));
-      stream.on("error", reject);
-    });
+    const chunks = [];
+    for await (const chunk of stream) {
+      chunks.push(chunk);
+    }
+    const buffer = Buffer.concat(chunks);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5cb550b and 1d107b8.

📒 Files selected for processing (37)
  • README.md (1 hunks)
  • examples/README.md (1 hunks)
  • examples/browser-live/README.md (1 hunks)
  • examples/browser-live/index.html (2 hunks)
  • examples/browser-prerecorded/README.md (1 hunks)
  • examples/browser-prerecorded/index.html (1 hunks)
  • examples/disabled_deno-prerecorded/index.js (0 hunks)
  • examples/node-agent-live/.gitignore (1 hunks)
  • examples/node-agent-live/README.md (1 hunks)
  • examples/node-agent-live/index.js (1 hunks)
  • examples/node-agent-live/package.json (1 hunks)
  • examples/node-live-token/.gitignore (1 hunks)
  • examples/node-live-token/README.md (1 hunks)
  • examples/node-live-token/index.js (1 hunks)
  • examples/node-live-token/package.json (1 hunks)
  • examples/node-live/.gitignore (1 hunks)
  • examples/node-live/README.md (1 hunks)
  • examples/node-live/index.js (1 hunks)
  • examples/node-live/package.json (1 hunks)
  • examples/node-prerecorded/.gitignore (1 hunks)
  • examples/node-prerecorded/README.md (1 hunks)
  • examples/node-prerecorded/index.js (3 hunks)
  • examples/node-prerecorded/package.json (1 hunks)
  • examples/node-read/.gitignore (1 hunks)
  • examples/node-read/README.md (1 hunks)
  • examples/node-read/index.js (1 hunks)
  • examples/node-read/package.json (1 hunks)
  • examples/node-speak-live/.gitignore (1 hunks)
  • examples/node-speak-live/README.md (1 hunks)
  • examples/node-speak-live/index.js (1 hunks)
  • examples/node-speak-live/package.json (1 hunks)
  • examples/node-speak/.gitignore (1 hunks)
  • examples/node-speak/README.md (1 hunks)
  • examples/node-speak/index.js (1 hunks)
  • examples/node-speak/package.json (1 hunks)
  • test/enhanced_websocket_errors.test.ts (0 hunks)
  • tests/README.md (1 hunks)
💤 Files with no reviewable changes (2)
  • examples/disabled_deno-prerecorded/index.js
  • test/enhanced_websocket_errors.test.ts
🧰 Additional context used
🧠 Learnings (22)
📓 Common learnings
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .markdownlint.jsonc:3-5
Timestamp: 2024-10-08T01:22:26.486Z
Learning: In the deepgram-js-sdk project, disabling the MarkdownLint rules `"line-length"`, `"no-bare-urls"`, and `"no-duplicate-heading"` is acceptable for GitHub documentation files.
examples/node-live-token/README.md (2)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .markdownlint.jsonc:3-5
Timestamp: 2024-10-08T01:22:26.486Z
Learning: In the deepgram-js-sdk project, disabling the MarkdownLint rules `"line-length"`, `"no-bare-urls"`, and `"no-duplicate-heading"` is acceptable for GitHub documentation files.
examples/node-prerecorded/README.md (1)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
examples/node-live-token/package.json (1)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
examples/node-agent-live/README.md (1)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
examples/node-speak/.gitignore (1)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
examples/node-live/README.md (2)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .markdownlint.jsonc:3-5
Timestamp: 2024-10-08T01:22:26.486Z
Learning: In the deepgram-js-sdk project, disabling the MarkdownLint rules `"line-length"`, `"no-bare-urls"`, and `"no-duplicate-heading"` is acceptable for GitHub documentation files.
examples/node-read/README.md (2)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .markdownlint.jsonc:3-5
Timestamp: 2024-10-08T01:22:26.486Z
Learning: In the deepgram-js-sdk project, disabling the MarkdownLint rules `"line-length"`, `"no-bare-urls"`, and `"no-duplicate-heading"` is acceptable for GitHub documentation files.
examples/node-speak-live/README.md (1)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
examples/node-agent-live/.gitignore (1)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
examples/README.md (2)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .markdownlint.jsonc:3-5
Timestamp: 2024-10-08T01:22:26.486Z
Learning: In the deepgram-js-sdk project, disabling the MarkdownLint rules `"line-length"`, `"no-bare-urls"`, and `"no-duplicate-heading"` is acceptable for GitHub documentation files.
examples/node-read/package.json (2)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .markdownlint.jsonc:3-5
Timestamp: 2024-10-08T01:22:26.486Z
Learning: In the deepgram-js-sdk project, disabling the MarkdownLint rules `"line-length"`, `"no-bare-urls"`, and `"no-duplicate-heading"` is acceptable for GitHub documentation files.
examples/node-agent-live/package.json (1)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
examples/node-speak-live/package.json (1)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
examples/node-live/package.json (1)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
examples/node-speak/package.json (1)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
examples/node-prerecorded/package.json (1)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
examples/node-speak/README.md (1)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
examples/node-prerecorded/index.js (1)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
examples/node-read/index.js (1)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
examples/node-speak/index.js (1)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
tests/README.md (2)
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .markdownlint.jsonc:3-5
Timestamp: 2024-10-08T01:22:26.486Z
Learning: In the deepgram-js-sdk project, disabling the MarkdownLint rules `"line-length"`, `"no-bare-urls"`, and `"no-duplicate-heading"` is acceptable for GitHub documentation files.
Learnt from: naomi-lgbt
PR: deepgram/deepgram-js-sdk#333
File: .github/workflows/CI.yml:50-51
Timestamp: 2024-10-08T01:26:16.711Z
Learning: In the `deepgram-js-sdk` project, linting configuration files may have custom names that differ from the default ones.
🧬 Code Graph Analysis (4)
examples/node-prerecorded/index.js (1)
src/packages/ListenRestClient.ts (2)
  • transcribeUrl (35-72)
  • transcribeFile (82-115)
examples/node-read/index.js (6)
examples/node-live/index.js (2)
  • require (4-4)
  • deepgram (9-9)
examples/node-live-token/index.js (2)
  • require (4-4)
  • deepgram (9-9)
examples/node-agent-live/index.js (2)
  • require (4-4)
  • deepgram (9-9)
examples/node-prerecorded/index.js (9)
  • require (4-4)
  • require (5-5)
  • require (6-6)
  • deepgram (65-65)
  • deepgram (68-75)
  • deepgram (84-84)
  • deepgram (91-93)
  • deepgram (100-100)
  • deepgram (103-105)
examples/node-speak/index.js (5)
  • require (4-4)
  • require (5-5)
  • require (6-6)
  • deepgram (10-10)
  • text (11-11)
examples/node-speak-live/index.js (4)
  • require (4-4)
  • require (5-5)
  • require (6-6)
  • deepgram (10-10)
examples/node-speak/index.js (3)
examples/node-read/index.js (4)
  • require (4-4)
  • deepgram (8-8)
  • deepgram (11-16)
  • text (9-9)
examples/node-speak-live/index.js (5)
  • require (4-4)
  • require (5-5)
  • require (6-6)
  • speak (9-36)
  • deepgram (10-10)
src/DeepgramClient.ts (1)
  • speak (90-92)
examples/node-agent-live/index.js (5)
examples/node-live/index.js (4)
  • require (4-4)
  • fetch (5-5)
  • deepgram (9-9)
  • connection (10-12)
examples/node-read/index.js (3)
  • require (4-4)
  • deepgram (8-8)
  • deepgram (11-16)
examples/node-speak-live/index.js (5)
  • require (4-4)
  • require (5-5)
  • require (6-6)
  • deepgram (10-10)
  • connection (11-13)
src/DeepgramClient.ts (1)
  • agent (100-102)
src/index.ts (1)
  • createClient (46-46)
🪛 GitHub Check: Test / OS ubuntu-latest / Node 22
examples/node-live/index.js

[failure] 2-2:
Definition for rule '@typescript-eslint/no-require-imports' was not found


[failure] 2-2:
Definition for rule '@typescript-eslint/no-var-requires' was not found

examples/node-prerecorded/index.js

[failure] 2-2:
Definition for rule '@typescript-eslint/no-require-imports' was not found


[failure] 2-2:
Definition for rule '@typescript-eslint/no-var-requires' was not found

examples/node-read/index.js

[failure] 2-2:
Definition for rule '@typescript-eslint/no-require-imports' was not found


[failure] 2-2:
Definition for rule '@typescript-eslint/no-var-requires' was not found

examples/node-live-token/index.js

[failure] 2-2:
Definition for rule '@typescript-eslint/no-require-imports' was not found


[failure] 2-2:
Definition for rule '@typescript-eslint/no-var-requires' was not found

examples/node-agent-live/index.js

[failure] 2-2:
Definition for rule '@typescript-eslint/no-require-imports' was not found


[failure] 2-2:
Definition for rule '@typescript-eslint/no-var-requires' was not found

🪛 GitHub Actions: CI
examples/node-agent-live/index.js

[error] 2-2: ESLint: Definition for rule '@typescript-eslint/no-var-requires' was not found.

🔇 Additional comments (13)
tests/README.md (1)

1-46: LGTM! Clean and well-structured test documentation.

The simplified test documentation is clear, concise, and provides all the necessary commands for running different types of tests. The structure follows good documentation practices and aligns well with the PR's objective of simplification.

examples/node-read/.gitignore (1)

1-3: LGTM! Standard Node.js gitignore patterns.

The gitignore file correctly excludes common Node.js artifacts (node_modules) and sensitive environment files (.env), following best practices for Node.js projects.

examples/node-live-token/.gitignore (1)

1-3: LGTM! Consistent gitignore patterns across examples.

This gitignore file maintains consistency with other example directories by using the same standard Node.js patterns, supporting the PR's goal of standardization.

README.md (1)

1021-1021: Double-check for lingering npm run build references

This line now uses pnpm, but several other docs (e.g. CONTRIBUTING, DEVELOPMENT, individual example READMEs) may still instruct npm run build. A quick grep will confirm consistency.

examples/README.md (1)

1-16: LGTM! Clean and focused documentation structure.

The simplified README effectively delegates detailed instructions to individual example directories while providing the essential setup steps. The use of pnpm for the build command is appropriate for this project.

examples/node-prerecorded/package.json (1)

1-12: LGTM! Well-structured package configuration.

The package.json follows standard conventions with appropriate metadata and dependencies. The inclusion of dotenv supports secure environment variable management, which is a best practice for handling API keys.

examples/node-prerecorded/index.js (3)

1-7: LGTM! Clean imports and environment configuration.

The destructured imports and dotenv configuration improve code organization and follow security best practices for API key management.


86-88: LGTM! Improved path handling.

The use of destructured resolve and readFileSync functions is cleaner and more maintainable than the previous full module imports.


2-2: ESLint configuration issue - not a code problem.

The static analysis failure indicates missing ESLint rule definitions, which is likely a configuration issue rather than a code problem. This should be addressed in the project's ESLint configuration.

The missing ESLint rules suggest the project's linting configuration may need updates. Based on the retrieved learnings, this project may have custom linting configuration files.

#!/bin/bash
# Check for ESLint configuration files and verify rule definitions
echo "Searching for ESLint configuration files..."
fd -t f -e json -e js -e yaml -e yml | grep -E "(eslint|lint)" | head -10

echo -e "\nChecking for TypeScript ESLint plugin installation..."
if [ -f "package.json" ]; then
  cat package.json | jq '.dependencies, .devDependencies' | grep -E "(typescript-eslint|eslint)"
fi

echo -e "\nSearching for any custom ESLint config files..."
fd -t f -e jsonc | grep -i eslint | head -5
examples/browser-prerecorded/index.html (1)

7-11: LGTM! Improved user experience with interactive transcription.

The HTML structure and button-triggered transcription provide a better user experience compared to automatic transcription on page load.

examples/node-read/index.js (2)

4-5: LGTM! Clean imports and environment configuration.

The simplified imports and dotenv configuration follow best practices for environment variable management.


7-23: LGTM! Well-structured and simplified example.

The refactored analyze function is clean and follows good practices:

  • Simple test text for demonstration
  • Consistent use of "nova-3" model
  • Proper error handling with logging instead of throwing
  • Clean result output with appropriate depth
examples/node-live-token/index.js (1)

1-2: ```bash
#!/bin/bash

Locate ESLint configuration files

echo "ESLint config files:"
fd -t f -g ".eslintrc*"

Check each config for TypeScript ESLint plugin/parser usage

echo "Checking for '@typescript-eslint' in these files:"
fd -t f -g ".eslintrc*" -x grep -H "@typescript-eslint" {} ;


</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Comment on lines +17 to 23
fetch("http://stream.live.vc.bbcmedia.co.uk/bbc_world_service")
.then((r) => r.body)
.then((res) => {
res.on("readable", () => {
connection.send(res.read());
});
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for the stream connection.

The fetch operation and stream processing lack error handling, which could lead to unhandled promise rejections or runtime errors if the BBC stream is unavailable.

-    fetch("http://stream.live.vc.bbcmedia.co.uk/bbc_world_service")
-      .then((r) => r.body)
-      .then((res) => {
-        res.on("readable", () => {
-          connection.send(res.read());
-        });
-      });
+    fetch("http://stream.live.vc.bbcmedia.co.uk/bbc_world_service")
+      .then((r) => {
+        if (!r.ok) {
+          throw new Error(`HTTP error! status: ${r.status}`);
+        }
+        return r.body;
+      })
+      .then((res) => {
+        res.on("readable", () => {
+          connection.send(res.read());
+        });
+        res.on("error", (error) => {
+          console.error("Stream error:", error);
+        });
+      })
+      .catch((error) => {
+        console.error("Failed to connect to audio stream:", error);
+      });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fetch("http://stream.live.vc.bbcmedia.co.uk/bbc_world_service")
.then((r) => r.body)
.then((res) => {
res.on("readable", () => {
connection.send(res.read());
});
});
fetch("http://stream.live.vc.bbcmedia.co.uk/bbc_world_service")
.then((r) => {
if (!r.ok) {
throw new Error(`HTTP error! status: ${r.status}`);
}
return r.body;
})
.then((res) => {
res.on("readable", () => {
connection.send(res.read());
});
res.on("error", (error) => {
console.error("Stream error:", error);
});
})
.catch((error) => {
console.error("Failed to connect to audio stream:", error);
});
🤖 Prompt for AI Agents
In examples/node-live/index.js around lines 17 to 23, the fetch call and stream
processing lack error handling, risking unhandled promise rejections or runtime
errors if the BBC stream is unavailable. Add catch blocks to the fetch promise
chain to handle fetch errors, and add error event listeners on the stream object
to handle stream errors gracefully. Ensure any errors are logged or handled
appropriately to prevent the application from crashing.

@@ -1,87 +1,34 @@
/* eslint-env node */
/* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports, no-console */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 Verification correct

Fix ESLint configuration issues.

The static analysis indicates that TypeScript ESLint rules are not found, suggesting a configuration problem that could affect the development workflow.

Please verify the ESLint configuration includes the necessary TypeScript rules:


🏁 Script executed:

#!/bin/bash
# Description: Check ESLint configuration for TypeScript rules
echo "Checking ESLint configuration files..."

# Look for ESLint config files
fd -t f "\.(eslintrc|eslint\.config)\.(js|json|yml|yaml|mjs)$" .
fd -t f "\.eslintrc$" .

# Check package.json for ESLint config
cat package.json | jq '.eslintConfig // empty'

# Check if TypeScript ESLint packages are installed
cat package.json | jq '.devDependencies | keys[] | select(contains("typescript-eslint"))'

Length of output: 383


Fix ESLint configuration issues.

The static analysis indicates that TypeScript ESLint rules are not found, suggesting a configuration problem that could affect the development workflow.

Please verify the ESLint configuration includes the necessary TypeScript rules:

#!/bin/bash
# Description: Check ESLint configuration for TypeScript rules
echo "Checking ESLint configuration files..."

# Look for ESLint config files
fd -t f "\.(eslintrc|eslint\.config)\.(js|json|yml|yaml|mjs)$" .
fd -t f "\.eslintrc$" .

# Check package.json for ESLint config
cat package.json | jq '.eslintConfig // empty'

# Check if TypeScript ESLint packages are installed
cat package.json | jq '.devDependencies | keys[] | select(contains("typescript-eslint"))'
🧰 Tools
🪛 GitHub Check: Test / OS ubuntu-latest / Node 22

[failure] 2-2:
Definition for rule '@typescript-eslint/no-require-imports' was not found


[failure] 2-2:
Definition for rule '@typescript-eslint/no-var-requires' was not found

🤖 Prompt for AI Agents
In examples/node-live/index.js at line 2, the ESLint configuration is missing or
incorrectly set up for TypeScript ESLint rules, causing static analysis errors.
Verify that your ESLint config files (like .eslintrc.js, .eslintrc.json, or
eslint.config.js) include the TypeScript ESLint plugin and parser settings.
Also, ensure that the necessary TypeScript ESLint packages are installed as
devDependencies in package.json. Run the provided shell commands to locate
ESLint config files and confirm the presence of TypeScript ESLint packages, then
update the configuration and dependencies accordingly.

Comment on lines +25 to +31
connection.on(LiveTranscriptionEvents.Transcript, (data) => {
console.log(data.channel.alternatives[0].transcript);
});

connection.on(LiveTranscriptionEvents.Close, () => {
console.log("Connection closed.");
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Move event listeners outside the Open event handler.

Event listeners for Transcript and Close events are registered inside the Open event handler, which could lead to unexpected behavior or multiple registrations if the connection reopens.

   connection.on(LiveTranscriptionEvents.Open, () => {
     console.log("Connection opened.");

     fetch("http://stream.live.vc.bbcmedia.co.uk/bbc_world_service")
       .then((r) => r.body)
       .then((res) => {
         res.on("readable", () => {
           connection.send(res.read());
         });
       });
-
-    connection.on(LiveTranscriptionEvents.Transcript, (data) => {
-      console.log(data.channel.alternatives[0].transcript);
-    });
-
-    connection.on(LiveTranscriptionEvents.Close, () => {
-      console.log("Connection closed.");
-    });
   });
+
+  connection.on(LiveTranscriptionEvents.Transcript, (data) => {
+    console.log(data.channel.alternatives[0].transcript);
+  });
+
+  connection.on(LiveTranscriptionEvents.Close, () => {
+    console.log("Connection closed.");
+  });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
connection.on(LiveTranscriptionEvents.Transcript, (data) => {
console.log(data.channel.alternatives[0].transcript);
});
connection.on(LiveTranscriptionEvents.Close, () => {
console.log("Connection closed.");
});
connection.on(LiveTranscriptionEvents.Open, () => {
console.log("Connection opened.");
fetch("http://stream.live.vc.bbcmedia.co.uk/bbc_world_service")
.then((r) => r.body)
.then((res) => {
res.on("readable", () => {
connection.send(res.read());
});
});
});
connection.on(LiveTranscriptionEvents.Transcript, (data) => {
console.log(data.channel.alternatives[0].transcript);
});
connection.on(LiveTranscriptionEvents.Close, () => {
console.log("Connection closed.");
});
🤖 Prompt for AI Agents
In examples/node-live/index.js around lines 25 to 31, the event listeners for
LiveTranscriptionEvents.Transcript and LiveTranscriptionEvents.Close are
currently registered inside the Open event handler, which can cause multiple
registrations if the connection reopens. Move these event listener registrations
outside and before the Open event handler to ensure they are only registered
once and avoid unexpected behavior.

Comment on lines +9 to +38
const speak = async () => {
const deepgram = createClient(process.env.DEEPGRAM_API_KEY);

const dgConnection = deepgram.speak.live({
model: "aura-2-thalia-en",
encoding: "linear16",
sample_rate: 48000,
const connection = deepgram.speak.live({
model: "aura-asteria-en",
});

let audioBuffer = Buffer.from(wavHeader);

dgConnection.on(LiveTTSEvents.Open, () => {
console.log("Connection opened");

// Send text data for TTS synthesis
dgConnection.sendText(text);
const audioChunks = [];

// Send Flush message to the server after sending the text
dgConnection.flush();

dgConnection.on(LiveTTSEvents.Close, () => {
console.log("Connection closed");
});

dgConnection.on(LiveTTSEvents.Metadata, (data) => {
console.dir(data, { depth: null });
});

dgConnection.on(LiveTTSEvents.Audio, (data) => {
console.log("Deepgram audio data received");
// Concatenate the audio chunks into a single buffer
const buffer = Buffer.from(data);
audioBuffer = Buffer.concat([audioBuffer, buffer]);
});

dgConnection.on(LiveTTSEvents.Flushed, () => {
console.log("Deepgram Flushed");
// Write the buffered audio data to a file when the flush event is received
writeFile();
});
connection.on(LiveTTSEvents.Open, () => {
console.log("Connection opened.");
connection.sendText("Hello, world! This is a live text-to-speech test.");
connection.sendText("This is a second sentence.");
connection.finish();
});

dgConnection.on(LiveTTSEvents.Error, (err) => {
console.error(err);
});
connection.on(LiveTTSEvents.Audio, (audio) => {
console.log("Received audio chunk.");
audioChunks.push(audio);
});

const writeFile = () => {
if (audioBuffer.length > 0) {
fs.writeFile("output.wav", audioBuffer, (err) => {
if (err) {
console.error("Error writing audio file:", err);
} else {
console.log("Audio file saved as output.wav");
}
});
audioBuffer = Buffer.from(wavHeader); // Reset buffer after writing
}
};
connection.on(LiveTTSEvents.Close, () => {
console.log("Connection closed.");
const buffer = Buffer.concat(audioChunks);
const filePath = resolve(__dirname, "output.mp3");
writeFileSync(filePath, buffer);
console.log(`Audio file saved to ${filePath}`);
});
};

live();
speak();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for connection events.

The example lacks error handling for potential connection issues or TTS service errors, which could help users understand what went wrong.

Add an error event handler:

   connection.on(LiveTTSEvents.Close, () => {
     console.log("Connection closed.");
     const buffer = Buffer.concat(audioChunks);
     const filePath = resolve(__dirname, "output.mp3");
     writeFileSync(filePath, buffer);
     console.log(`Audio file saved to ${filePath}`);
   });
+
+  connection.on(LiveTTSEvents.Error, (error) => {
+    console.error("Connection error:", error);
+  });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const speak = async () => {
const deepgram = createClient(process.env.DEEPGRAM_API_KEY);
const dgConnection = deepgram.speak.live({
model: "aura-2-thalia-en",
encoding: "linear16",
sample_rate: 48000,
const connection = deepgram.speak.live({
model: "aura-asteria-en",
});
let audioBuffer = Buffer.from(wavHeader);
dgConnection.on(LiveTTSEvents.Open, () => {
console.log("Connection opened");
// Send text data for TTS synthesis
dgConnection.sendText(text);
const audioChunks = [];
// Send Flush message to the server after sending the text
dgConnection.flush();
dgConnection.on(LiveTTSEvents.Close, () => {
console.log("Connection closed");
});
dgConnection.on(LiveTTSEvents.Metadata, (data) => {
console.dir(data, { depth: null });
});
dgConnection.on(LiveTTSEvents.Audio, (data) => {
console.log("Deepgram audio data received");
// Concatenate the audio chunks into a single buffer
const buffer = Buffer.from(data);
audioBuffer = Buffer.concat([audioBuffer, buffer]);
});
dgConnection.on(LiveTTSEvents.Flushed, () => {
console.log("Deepgram Flushed");
// Write the buffered audio data to a file when the flush event is received
writeFile();
});
connection.on(LiveTTSEvents.Open, () => {
console.log("Connection opened.");
connection.sendText("Hello, world! This is a live text-to-speech test.");
connection.sendText("This is a second sentence.");
connection.finish();
});
dgConnection.on(LiveTTSEvents.Error, (err) => {
console.error(err);
});
connection.on(LiveTTSEvents.Audio, (audio) => {
console.log("Received audio chunk.");
audioChunks.push(audio);
});
const writeFile = () => {
if (audioBuffer.length > 0) {
fs.writeFile("output.wav", audioBuffer, (err) => {
if (err) {
console.error("Error writing audio file:", err);
} else {
console.log("Audio file saved as output.wav");
}
});
audioBuffer = Buffer.from(wavHeader); // Reset buffer after writing
}
};
connection.on(LiveTTSEvents.Close, () => {
console.log("Connection closed.");
const buffer = Buffer.concat(audioChunks);
const filePath = resolve(__dirname, "output.mp3");
writeFileSync(filePath, buffer);
console.log(`Audio file saved to ${filePath}`);
});
};
live();
speak();
const speak = async () => {
const deepgram = createClient(process.env.DEEPGRAM_API_KEY);
const connection = deepgram.speak.live({
model: "aura-asteria-en",
});
const audioChunks = [];
connection.on(LiveTTSEvents.Open, () => {
console.log("Connection opened.");
connection.sendText("Hello, world! This is a live text-to-speech test.");
connection.sendText("This is a second sentence.");
connection.finish();
});
connection.on(LiveTTSEvents.Audio, (audio) => {
console.log("Received audio chunk.");
audioChunks.push(audio);
});
connection.on(LiveTTSEvents.Close, () => {
console.log("Connection closed.");
const buffer = Buffer.concat(audioChunks);
const filePath = resolve(__dirname, "output.mp3");
writeFileSync(filePath, buffer);
console.log(`Audio file saved to ${filePath}`);
});
connection.on(LiveTTSEvents.Error, (error) => {
console.error("Connection error:", error);
});
};
speak();
🤖 Prompt for AI Agents
In examples/node-speak-live/index.js around lines 9 to 38, the code lacks error
handling for the live TTS connection events. Add an event listener for the error
event on the connection object to catch and log any errors that occur during the
connection or TTS process. This will help users understand and debug issues by
providing clear error messages.

Comment on lines +29 to +35
connection.on(LiveTTSEvents.Close, () => {
console.log("Connection closed.");
const buffer = Buffer.concat(audioChunks);
const filePath = resolve(__dirname, "output.mp3");
writeFileSync(filePath, buffer);
console.log(`Audio file saved to ${filePath}`);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use asynchronous file operations to avoid blocking.

The synchronous writeFileSync operation could block the event loop, especially for larger audio files. Consider using the asynchronous version with proper error handling.

+  const { writeFile } = require("fs").promises;

   connection.on(LiveTTSEvents.Close, () => {
     console.log("Connection closed.");
     const buffer = Buffer.concat(audioChunks);
     const filePath = resolve(__dirname, "output.mp3");
-    writeFileSync(filePath, buffer);
-    console.log(`Audio file saved to ${filePath}`);
+    writeFile(filePath, buffer)
+      .then(() => {
+        console.log(`Audio file saved to ${filePath}`);
+      })
+      .catch((error) => {
+        console.error("Failed to save audio file:", error);
+      });
   });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
connection.on(LiveTTSEvents.Close, () => {
console.log("Connection closed.");
const buffer = Buffer.concat(audioChunks);
const filePath = resolve(__dirname, "output.mp3");
writeFileSync(filePath, buffer);
console.log(`Audio file saved to ${filePath}`);
});
const { writeFile } = require("fs").promises;
connection.on(LiveTTSEvents.Close, () => {
console.log("Connection closed.");
const buffer = Buffer.concat(audioChunks);
const filePath = resolve(__dirname, "output.mp3");
writeFile(filePath, buffer)
.then(() => {
console.log(`Audio file saved to ${filePath}`);
})
.catch((error) => {
console.error("Failed to save audio file:", error);
});
});
🤖 Prompt for AI Agents
In examples/node-speak-live/index.js around lines 29 to 35, replace the
synchronous writeFileSync call with the asynchronous writeFile function from the
fs module. Use async/await or a callback to handle the file writing operation
and include error handling to catch and log any errors during the file save
process, ensuring the event loop is not blocked.

Comment on lines +26 to 32
fetch("http://stream.live.vc.bbcmedia.co.uk/bbc_world_service")
.then((r) => r.body)
.then((res) => {
res.on("readable", () => {
console.log("Sending audio chunk");
connection.send(res.read());
});
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for the audio stream fetch.

The fetch operation lacks proper error handling, which could cause unhandled promise rejections.

    fetch("http://stream.live.vc.bbcmedia.co.uk/bbc_world_service")
      .then((r) => r.body)
      .then((res) => {
        res.on("readable", () => {
          connection.send(res.read());
        });
-      });
+      })
+      .catch((error) => {
+        console.error("Error fetching audio stream:", error);
+      });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fetch("http://stream.live.vc.bbcmedia.co.uk/bbc_world_service")
.then((r) => r.body)
.then((res) => {
res.on("readable", () => {
console.log("Sending audio chunk");
connection.send(res.read());
});
});
fetch("http://stream.live.vc.bbcmedia.co.uk/bbc_world_service")
.then((r) => r.body)
.then((res) => {
res.on("readable", () => {
connection.send(res.read());
});
})
.catch((error) => {
console.error("Error fetching audio stream:", error);
});
🤖 Prompt for AI Agents
In examples/node-agent-live/index.js between lines 26 and 32, the fetch call for
the audio stream does not handle errors, risking unhandled promise rejections.
Add a .catch() block after the fetch promise chain to catch and handle any
errors that occur during the fetch or stream processing. This should log the
error or handle it appropriately to prevent the application from crashing.

Comment on lines +34 to +40
connection.on(AgentEvents.ConversationText, (data) => {
console.log(data.role, data.content);
});

connection.on(AgentEvents.Unhandled, (data) => {
console.dir(data, { depth: null });
connection.on(AgentEvents.Close, () => {
console.log("Connection closed.");
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Move event handlers outside the Open event to prevent multiple registrations.

Similar to the token example, event handlers are nested inside the Open event handler, which could lead to multiple registrations.

  connection.on(AgentEvents.Open, () => {
    console.log("Connection opened.");

    connection.configure({
      agent: {
        listen: {
          model: "nova-3",
        },
        speak: {
          model: "aura-asteria-en",
        },
      },
    });

    fetch("http://stream.live.vc.bbcmedia.co.uk/bbc_world_service")
      .then((r) => r.body)
      .then((res) => {
        res.on("readable", () => {
          connection.send(res.read());
        });
      });
-
-    connection.on(AgentEvents.ConversationText, (data) => {
-      console.log(data.role, data.content);
-    });
-
-    connection.on(AgentEvents.Close, () => {
-      console.log("Connection closed.");
-    });
  });
+
+  connection.on(AgentEvents.ConversationText, (data) => {
+    console.log(data.role, data.content);
+  });
+
+  connection.on(AgentEvents.Close, () => {
+    console.log("Connection closed.");
+  });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
connection.on(AgentEvents.ConversationText, (data) => {
console.log(data.role, data.content);
});
connection.on(AgentEvents.Unhandled, (data) => {
console.dir(data, { depth: null });
connection.on(AgentEvents.Close, () => {
console.log("Connection closed.");
});
connection.on(AgentEvents.Open, () => {
console.log("Connection opened.");
connection.configure({
agent: {
listen: {
model: "nova-3",
},
speak: {
model: "aura-asteria-en",
},
},
});
fetch("http://stream.live.vc.bbcmedia.co.uk/bbc_world_service")
.then((r) => r.body)
.then((res) => {
res.on("readable", () => {
connection.send(res.read());
});
});
});
connection.on(AgentEvents.ConversationText, (data) => {
console.log(data.role, data.content);
});
connection.on(AgentEvents.Close, () => {
console.log("Connection closed.");
});
🤖 Prompt for AI Agents
In examples/node-agent-live/index.js around lines 34 to 40, the event handlers
for ConversationText and Close are currently inside the Open event handler,
causing multiple registrations on repeated opens. Move these event handler
registrations outside and before the Open event handler to ensure they are
registered only once and prevent duplicate event handling.

vad_events: true,
// Time in milliseconds of silence to wait for before finalizing speech
endpointing: 300,
const deepgram = deepgram.createClient(apiKey);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix incorrect global object reference.

The code uses deepgram.createClient() but the global object from the UMD bundle is likely Deepgram (capitalized).

-        const deepgram = deepgram.createClient(apiKey);
+        const deepgram = Deepgram.createClient(apiKey);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const deepgram = deepgram.createClient(apiKey);
const deepgram = Deepgram.createClient(apiKey);
🤖 Prompt for AI Agents
In examples/browser-live/index.html at line 31, the code incorrectly references
the global object as 'deepgram' with a lowercase 'd'. Change this to 'Deepgram'
with an uppercase 'D' to correctly use the global object from the UMD bundle
when calling createClient.

Comment on lines +73 to +80
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = (event) => {
if (event.data.size > 0) {
connection.send(event.data);
}
};
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for getUserMedia.

The MediaRecorder setup lacks error handling for cases where microphone access is denied or unavailable.

-        const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
-        mediaRecorder = new MediaRecorder(stream);
-        mediaRecorder.ondataavailable = (event) => {
-          if (event.data.size > 0) {
-            connection.send(event.data);
-          }
-        };
+        try {
+          const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
+          mediaRecorder = new MediaRecorder(stream);
+          mediaRecorder.ondataavailable = (event) => {
+            if (event.data.size > 0) {
+              connection.send(event.data);
+            }
+          };
+        } catch (error) {
+          console.error("Error accessing microphone:", error);
+          alert("Microphone access is required for live transcription.");
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = (event) => {
if (event.data.size > 0) {
connection.send(event.data);
}
};
};
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = (event) => {
if (event.data.size > 0) {
connection.send(event.data);
}
};
} catch (error) {
console.error("Error accessing microphone:", error);
alert("Microphone access is required for live transcription.");
}
};
🤖 Prompt for AI Agents
In examples/browser-live/index.html around lines 73 to 80, the code calls
getUserMedia without handling errors, which can cause issues if microphone
access is denied or unavailable. Wrap the getUserMedia call in a try-catch block
or use promise catch to handle errors gracefully. In the error handler, provide
user feedback or log the error to inform about the failure to access the
microphone.

Comment on lines +82 to +90
startButton.onclick = () => {
if (!connection) {
setup().then(() => {
mediaRecorder.start(1000);
});
} else {
mediaRecorder.start(1000);
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Prevent multiple setup calls and connection leaks.

The start button can call setup multiple times, potentially creating multiple connections and event handlers without proper cleanup.

      startButton.onclick = () => {
-        if (!connection) {
-          setup().then(() => {
-            mediaRecorder.start(1000);
-          });
-        } else {
-          mediaRecorder.start(1000);
-        }
+        if (!connection) {
+          setup().then(() => {
+            if (mediaRecorder) {
+              mediaRecorder.start(1000);
+            }
+          }).catch((error) => {
+            console.error("Setup failed:", error);
+          });
+        } else if (mediaRecorder && mediaRecorder.state === "inactive") {
+          mediaRecorder.start(1000);
+        }
       };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
startButton.onclick = () => {
if (!connection) {
setup().then(() => {
mediaRecorder.start(1000);
});
} else {
mediaRecorder.start(1000);
}
};
startButton.onclick = () => {
if (!connection) {
setup().then(() => {
if (mediaRecorder) {
mediaRecorder.start(1000);
}
}).catch((error) => {
console.error("Setup failed:", error);
});
} else if (mediaRecorder && mediaRecorder.state === "inactive") {
mediaRecorder.start(1000);
}
};
🤖 Prompt for AI Agents
In examples/browser-live/index.html around lines 82 to 90, the startButton
onclick handler calls setup multiple times if connection is not established,
which can create multiple connections and event handlers leading to leaks.
Modify the code to ensure setup is only called once by checking if a setup is
already in progress or completed before calling it again. Also, add proper
cleanup logic to close or reset existing connections and event handlers before
creating new ones to prevent leaks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants