From 19f751c1abfb5bb101f6cf66268d92d83c1c7a84 Mon Sep 17 00:00:00 2001 From: David vonThenen <12752197+dvonthenen@users.noreply.github.com> Date: Tue, 10 Sep 2024 16:43:22 -0700 Subject: [PATCH] Initial Code for Starter App --- .gitattributes | 3 + .gitignore | 30 +++ CODE_OF_CONDUCT.md | 30 +-- CONTRIBUTING.md | 151 +++++--------- LICENSE | 2 +- README.md | 77 ++++---- SECURITY.md | 5 - deepgram.toml | 21 +- go.mod | 20 ++ go.sum | 24 +++ main.go | 318 ++++++++++++++++++++++++++++++ public/assets/dg_favicon.ico | Bin 0 -> 963 bytes public/assets/logo-6ad0fabf.png | Bin 0 -> 12346 bytes public/assets/preview-starter.png | Bin 0 -> 121990 bytes public/client.js | 187 ++++++++++++++++++ public/index.html | 70 +++++++ public/style.css | 203 +++++++++++++++++++ sample.env | 1 - static/.gitkeep | 0 19 files changed, 966 insertions(+), 176 deletions(-) create mode 100644 .gitattributes create mode 100644 .gitignore delete mode 100644 SECURITY.md create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 public/assets/dg_favicon.ico create mode 100644 public/assets/logo-6ad0fabf.png create mode 100644 public/assets/preview-starter.png create mode 100644 public/client.js create mode 100644 public/index.html create mode 100644 public/style.css delete mode 100644 sample.env delete mode 100644 static/.gitkeep diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..0a11cce --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +*.html linguist-detectable=false +*.css linguist-detectable=false +*.js linguist-detectable=false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..87b3921 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# Binaries for programs and plugins +.DS_Store +*.exe +*.exe~ +*.dll +*.o +*.a +*.so +*.dylib + +# Folders +_obj +_test +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# cgo stuff +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* +_testmain.go +.idea/ +*.iml diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 1dc8f5e..303ec62 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -17,23 +17,23 @@ diverse, inclusive, and healthy community. Examples of behavior that contributes to a positive environment for our community include: -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience -* Focusing on what is best not just for us as individuals, but for the +- Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: -* The use of sexualized language or imagery, and sexual attention or +- The use of sexualized language or imagery, and sexual attention or advances of any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email address, without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a +- Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities @@ -60,7 +60,7 @@ representative at an online or offline event. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at -Deepgram Developer Relations . +devrel@deepgram.com. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the @@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an +standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within @@ -116,7 +116,7 @@ the community. This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at -https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. +. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). @@ -124,5 +124,5 @@ enforcement ladder](https://github.com/mozilla/diversity). [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see the FAQ at -https://www.contributor-covenant.org/faq. Translations are available at -https://www.contributor-covenant.org/translations. +. Translations are available at +. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4230ea3..f46ceeb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,105 +1,50 @@ - # Contributing Guidelines -:+1::tada: We :heart: contributions from everyone! :tada::+1: - -It is a good idea to reach out with an issue first if you plan to add any new functionality. Otherwise, bug reports, bug fixes and feedback is always appreciated. Check out the [Contributing Guidelines][contributing] for more information and please follow the [GitHub Flow][githubflow]. - -![contributions welcome][contribadge] - -The following is a set of guidelines for contributing to this project, which are hosted on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. - -Please take the time to review the [Code of Conduct][coc], which all contributors are subject to on this project. - -[I don't want to read this whole thing, I just have a question!!!](#i-dont-want-to-read-this-whole-thing-i-just-have-a-question) - -[TOC] - -## Reporting Bugs - -This section guides you through submitting a bug report. Following these guidelines helps maintainers and the community understand your report :pencil:, reproduce the behavior :computer: :computer:, and find related reports :mag_right:. - -Before creating bug reports [please check for other issues,](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out the issue, and include any information it asks for to help us resolve issues faster. - -> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one. - -### Before Submitting A Bug Report - -* **Perform a cursory search** to see if the problem has already been reported. If it has **and the issue is still open**, add a comment to the existing issue instead of opening a new one. - -### How Do I Submit A (Good) Bug Report? - -Bugs are tracked as GitHub issues. Create an issue and provide the following information as required or necessary. - -Explain the problem and include additional details to help maintainers reproduce the problem: - -* **Use a clear and descriptive title** for the issue to identify the problem. -* **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining how you started. When listing steps, **don't just say what you did, but explain how you did it**. -* **Provide specific examples to demonstrate the steps**. Include links to files or copy/pasteable snippets, which you use in those examples. If you're providing snippets in the issue, use [Markdown code blocks][githubcodeblocks]. -* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior. -* **Explain which behavior you expected to see instead and why.** -* **Include screenshots and animated GIFs** where possible. Show how you follow the described steps and clearly demonstrate the problem. You can use [this tool][licecap] to record GIFs on macOS and Windows, and [this tool][silentcast] on Linux. -* **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more information using the guidelines below. -* **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens. -Include details about your configuration and environment: - -## Suggesting Enhancements - -This section guides you through submitting a suggestion, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion :pencil: and find related suggestions :mag_right:. - -Before creating enhancement suggestions, please check [this list](#before-submitting-an-enhancement-suggestion) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion). Fill out [the required template][featurerequest], the information it asks for helps us resolve issues faster. - -### Before Submitting An Enhancement Suggestion - -* **Perform a cursory search** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. - -### How Do I Submit A (Good) Enhancement Suggestion? - -Enhancement suggestions are tracked as GitHub issues. Create an issue and provide the following information. - -* **Use a clear and descriptive title** for the issue to identify the suggestion. -* **Provide a step-by-step description of the suggested enhancement** in as many details as possible. -* **Provide specific examples to demonstrate the steps**. Include copy/pasteable snippets which you use in those examples, as [Markdown code blocks][githubcodeblocks]. -* **Describe the current behavior** and **explain which behavior you expected to see instead** and why. -* **Explain why this enhancement would be useful** to most users. - -## Your First Code Contribution - -Unsure where to begin contributing? You can start by looking through these `beginner` and `help-wanted` issues on any of our projects. While not perfect, number of comments is a reasonable proxy for impact a given change will have. - -## Pull Requests - -Please follow these steps to have your contribution considered by the maintainers: - -1. Follow all instructions in [the template][pullrequest] -2. Adhear the [Code of Conduct][coc] -3. After you submit your pull request, verify that all [status checks][githubstatuschecks] are passing. - -While the prerequisites above must be satisfied prior to having your pull request reviewed, the reviewer(s) may ask you to complete additional design work, tests, or other changes before your pull request can be ultimately accepted. - -# I don't want to read this whole thing I just have a question!!! - -You can join our community for any questions you might have: - -* [Contact our Developer Relations Team][community] -* [Reach out on Twitter][twitter] - * This Twitter is monitored by our Marketing and Developer Relations team, but not 24/7—please be patient! - -Alternatively, you can raise an issue on the project. - -[contribadge]: https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat "Contributions Welcome" - -[coc]: CODE_OF_CONDUCT.md "Code of Conduct" -[contributing]: CONTRIBUTING.md "Contributing" -[license]: LICENSE "MIT License" -[pullrequest]: PULL_REQUEST_TEMPLATE/PULL_REQUEST_TEMPLATE.md "Pull Request template" - -[community]: https://github.com/orgs/deepgram/discussions "Deepgram Community" -[signup]: https://console.deepgram.com/signup "Deepgram Console" -[twitter]: https://twitter.com/DeepgramAI "Deepgram on Twitter" - -[githubcodeblocks]: https://help.github.com/articles/markdown-basics/#multiple-lines "GitHub Markdown Code Blocks" -[githubflow]: https://guides.github.com/introduction/flow/index.html "GitHub Flow" -[githubstatuschecks]: https://help.github.com/articles/about-status-checks/ "GitHub Status Checks" -[licecap]: https://www.cockos.com/licecap/ "LICEcap: animated screen captures" -[silentcast]: https://github.com/colinkeenan/silentcast "Silentcast: silent mkv screencasts and animated gifs" +Want to contribute to this project? We ❤️ it! + +Here are a few types of contributions that we would be interested in hearing about. + +* Bug fixes + * If you find a bug, please first report it using Github Issues. + * Issues that have already been identified as a bug will be labeled `bug`. + * If you'd like to submit a fix for a bug, send a Pull Request from your own fork and mention the Issue number. + * Include a test that isolates the bug and verifies that it was fixed. +* New Features + * If you'd like to accomplish something in the extension that it doesn't already do, describe the problem in a new Github Issue. + * Issues that have been identified as a feature request will be labeled `enhancement`. + * If you'd like to implement the new feature, please wait for feedback from the project maintainers before spending + too much time writing the code. In some cases, `enhancement`s may not align well with the project objectives at + the time. +* Tests, Documentation, Miscellaneous + * If you think the test coverage could be improved, the documentation could be clearer, you've got an alternative + implementation of something that may have more advantages, or any other change we would still be glad hear about + it. + * If its a trivial change, go ahead and send a Pull Request with the changes you have in mind + * If not, open a Github Issue to discuss the idea first. +* Snippets + * To add snippets: + * Add a directory in the `snippets` folder with the name of the language. + * Add one or more files in the language directory with snippets. + * Update the `package.json` to include the snippets you added. + +We also welcome anyone to work on any existing issues with the `good first issue` tag. + +## Requirements + +For a contribution to be accepted: + +* The test suite must be complete and pass +* Code must follow existing styling conventions +* Commit messages must be descriptive. Related issues should be mentioned by number. + +If the contribution doesn't meet these criteria, a maintainer will discuss it with you on the Issue. You can still +continue to add more commits to the branch you have sent the Pull Request from. + +## How To + +1. Fork this repository on GitHub. +1. Clone/fetch your fork to your local development machine. +1. Create a new branch (e.g. `issue-12`, `feat.add_foo`, etc) and check it out. +1. Make your changes and commit them. (Did the tests pass? No linting errors?) +1. Push your new branch to your fork. (e.g. `git push myname issue-12`) +1. Open a Pull Request from your new branch to the original fork's `main` branch. diff --git a/LICENSE b/LICENSE index f5bde48..fb8aa61 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Deepgram Templates +Copyright (c) 2024 Deepgram Devs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index a7b7174..192d47b 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,26 @@ -> Copy the entire contents of https://github.com/deepgram-starters/deepgram-starters-ui to the `./static/` folder. +# Text-to-Speech WebSocket Starter for Go -> The name of the project and repo, is less important than the correct configuration of the `deepgram.toml` file, if you wish for it to be included in future onboarding workflows. +This example app demonstrates how to use the Deepgram Text-to-Speech API over WebSockets with Go. -# [Usecase] [Language] Starter +The flow of this sample is: -> Write an intro for this project +1. A websocket is opened from the UI to the backend Go component +1. Text is sent over a websocket to the backend component +1. If a connection has not been established to Deepgram, create a websocket connection using the Python SDK and send the text to convert to audio +1. An audio byte response with synthesized text-to-speech is returned and forward back through the WebSocket created by the UI +1. Those audio bytes are then played by the media device contained within your browser -Nifty little into, maybe a screenshot. +A preview of the app -## Sign-up to Deepgram - -> Please leave this section unchanged, unless providing a UTM on the URL. +## What is Deepgram? -Before you start, it's essential to generate a Deepgram API key to use in this project. [Sign-up now for Deepgram](https://console.deepgram.com/signup). +[Deepgram](https://deepgram.com/) is a voice AI company providing speech-to-text and language understanding capabilities to make data readable and actionable by human or machines. -## Quickstart +## Sign-up to Deepgram -> Detail the manual steps to get started. +Before you start, it's essential to generate a Deepgram API key to use in this project. [Sign-up now for Deepgram and create an API key](https://console.deepgram.com/signup?jump=keys). -e.g. +## Quickstart ### Manual @@ -26,59 +28,54 @@ Follow these steps to get started with this starter application. #### Clone the repository -Go to GitHub and [clone the repository](https://github.com/deepgram-starters/prerecorded-node-starter). +Go to GitHub and [clone the repository](https://github.com/deepgram-starters/go-live-text-to-speech). #### Install dependencies Install the project dependencies. ```bash -npm install +go mod tidy ``` -#### Edit the config file +#### Set your Deepgram API key -> Config file can be any appropriate file for the framework/language. For e.g. -> Node is using a config.json file, while Python is only use .env files +If using bash, this can be done in your `~/.bash_profile` like so: -Copy the code from `sample.env` and create a new file called `.env`. Paste in the code and enter your API key you generated in the [Deepgram console](https://console.deepgram.com/). - -```json -DEEPGRAM_API_KEY=%api_key% +```bash +export DEEPGRAM_API_KEY="YOUR_DEEPGRAM_API_KEY" ``` -#### Run the application +#### Run the Go Application -> to support the UI, it must always run on port 8080 - -The `dev` script will run a web and API server concurrently. Once running, you can [access the application in your browser](http://localhost:8080/). +If you have set your `DEEPGRAM_API_KEY` environment variable, start the Backend go application using this command: ```bash -npm start +go run main.go ``` -## What is Deepgram? - -Deepgram is an AI speech platform which specializes in (NLU) Natural Language Understanding features and Transcription. It can help get the following from your audio. +If you haven't, this could also be done by a simple export before executing your Go application: -- [Speaker diarization](https://deepgram.com/product/speech-understanding/) -- [Language detection](https://deepgram.com/product/speech-understanding/) -- [Summarization](https://deepgram.com/product/speech-understanding/) -- [Topic detection](https://deepgram.com/product/speech-understanding/) -- [Language translation](https://deepgram.com/product/speech-understanding/) -- [Sentiment analysis](https://deepgram.com/product/speech-understanding/) -- [Entity detection](https://deepgram.com/product/speech-understanding/) -- [Transcription](https://deepgram.com/product/transcription/) -- [Redaction](https://deepgram.com/product/transcription/) +```bash +DEEPGRAM_API_KEY="YOUR_DEEPGRAM_API_KEY" go run main.go +``` -## Create a Free Deepgram Account +#### Open the UI in a Browser -Before you start, it's essential to generate a Deepgram API key to use in our starter applications. [Sign-up now for Deepgram](https://console.deepgram.com/signup). +To open the Frontend UI, just navigate to `http://localhost:3000` in Chrome. ## Issue Reporting If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The [Security Policy](./SECURITY.md) details the procedure for contacting Deepgram. +## Getting Help + +We love to hear from you so if you have questions, comments or find a bug in the project, let us know! You can either: + +- [Open an issue in this repository](https://github.com/deepgram-starters/live-node-starter/issues/new) +- [Join the Deepgram Github Discussions Community](https://github.com/orgs/deepgram/discussions) +- [Join the Deepgram Discord Community](https://discord.gg/xWRaCDBtW4) + ## Author [Deepgram](https://deepgram.com) diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index f898aee..0000000 --- a/SECURITY.md +++ /dev/null @@ -1,5 +0,0 @@ -# Security Policy - -Deepgram's security policy can be found on our main website. - -[Deepgram Security Policy](https://developers.deepgram.com/documentation/security/security-policy/) diff --git a/deepgram.toml b/deepgram.toml index eff3f2d..a1ad32b 100644 --- a/deepgram.toml +++ b/deepgram.toml @@ -1,17 +1,16 @@ [meta] - title = " Starter" # update with usecase and framework - description = "Basic demo for using Deepgram to in " # update with usecase and framework - author = "Deepgram DX Team (https://developers.deepgram.com)" # update for author details - useCase = "Prerecorded" # usecase - language = "Python" # base language - framework = "Flask" # framework if not native + title = "Text-to-speech Go Starter" + description = "This example app demonstrates how to use the Deepgram Text-to-Speech API with Go." + author = "Deepgram DX Team (https://developers.deepgram.com)" + useCase = "TTS" + language = "Go" -[build] # delete if no build/install steps applicable - command = "pip install -r requirements.txt" # automatically install dependencies, delete if not applicable +[build] + command = "go get" [config] - sample = "sample.env" # the example config file - output = ".env" # the file that we will generate using their API + sample = "sample.env" + output = ".env" [post-build] - message = "Run `flask run -p 8080` to get up and running." # message to give users once setup is complete \ No newline at end of file + message = "Run `go run .` to get up and running." diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..bf3c31b --- /dev/null +++ b/go.mod @@ -0,0 +1,20 @@ +module github.com/deepgram-starters/text-to-speech-starter-go + +go 1.19 + +require ( + github.com/deepgram/deepgram-go-sdk v1.6.0-dev.2 + github.com/gorilla/websocket v1.5.3 +) + +require ( + github.com/dvonthenen/websocket v1.5.1-dyv.2 // indirect + github.com/fatih/color v1.15.0 // indirect + github.com/go-logr/logr v1.3.0 // indirect + github.com/gorilla/schema v1.3.0 // indirect + github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + golang.org/x/sys v0.6.0 // indirect + k8s.io/klog/v2 v2.110.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..132a98e --- /dev/null +++ b/go.sum @@ -0,0 +1,24 @@ +github.com/deepgram/deepgram-go-sdk v1.6.0-dev.2 h1:ygZgPkdvU/fGLBOI3/eD2F+N48AmWBa3yvKef+oEf5g= +github.com/deepgram/deepgram-go-sdk v1.6.0-dev.2/go.mod h1:il+6HLmvxa47EG12LG6VwzaHcyI8Lo+yfBsOcDq3R8s= +github.com/dvonthenen/websocket v1.5.1-dyv.2 h1:OXlWJJkeHt8k4+MEI0Y8SQjY2ihHYD2z/tI7sZZfsnA= +github.com/dvonthenen/websocket v1.5.1-dyv.2/go.mod h1:q2GbopbpFJvBP4iqVvqwwahVmvu2HnCfdqCWDoQVKMM= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/gorilla/schema v1.3.0 h1:rbciOzXAx3IB8stEFnfTwO3sYa6EWlQk79XdyustPDA= +github.com/gorilla/schema v1.3.0/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f h1:7LYC+Yfkj3CTRcShK0KOL/w6iTiKyqqBA9a41Wnggw8= +github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= +k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= diff --git a/main.go b/main.go new file mode 100644 index 0000000..ea5b904 --- /dev/null +++ b/main.go @@ -0,0 +1,318 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "log" + "net/http" + "sync" + "time" + + "github.com/gorilla/websocket" + + msginterfaces "github.com/deepgram/deepgram-go-sdk/pkg/api/speak/v1/websocket/interfaces" + clientinterfaces "github.com/deepgram/deepgram-go-sdk/pkg/client/interfaces" + client "github.com/deepgram/deepgram-go-sdk/pkg/client/speak" +) + +type MyHandler struct { + binaryChan chan *[]byte + openChan chan *msginterfaces.OpenResponse + flushedChan chan *msginterfaces.FlushedResponse + closeChan chan *msginterfaces.CloseResponse + errorChan chan *msginterfaces.ErrorResponse + + wsUI *websocket.Conn +} + +func NewMyHandler(uiWebsocket *websocket.Conn) MyHandler { + handler := MyHandler{ + binaryChan: make(chan *[]byte), + openChan: make(chan *msginterfaces.OpenResponse), + flushedChan: make(chan *msginterfaces.FlushedResponse), + closeChan: make(chan *msginterfaces.CloseResponse), + errorChan: make(chan *msginterfaces.ErrorResponse), + wsUI: uiWebsocket, + } + + go func() { + handler.Run() + }() + + return handler +} + +// GetUnhandled returns the binary event channels +func (dch MyHandler) GetBinary() []*chan *[]byte { + return []*chan *[]byte{&dch.binaryChan} +} + +// GetOpen returns the open channels +func (dch MyHandler) GetOpen() []*chan *msginterfaces.OpenResponse { + return []*chan *msginterfaces.OpenResponse{&dch.openChan} +} + +// GetMetadata returns the metadata channels +func (dch MyHandler) GetMetadata() []*chan *msginterfaces.MetadataResponse { + return []*chan *msginterfaces.MetadataResponse{} +} + +// GetFlushed returns the flush channels +func (dch MyHandler) GetFlush() []*chan *msginterfaces.FlushedResponse { + return []*chan *msginterfaces.FlushedResponse{&dch.flushedChan} +} + +// GetClose returns the close channels +func (dch MyHandler) GetClose() []*chan *msginterfaces.CloseResponse { + return []*chan *msginterfaces.CloseResponse{&dch.closeChan} +} + +// GetWarning returns the warning channels +func (dch MyHandler) GetWarning() []*chan *msginterfaces.WarningResponse { + return []*chan *msginterfaces.WarningResponse{} +} + +// GetError returns the error channels +func (dch MyHandler) GetError() []*chan *msginterfaces.ErrorResponse { + return []*chan *msginterfaces.ErrorResponse{&dch.errorChan} +} + +// GetUnhandled returns the unhandled event channels +func (dch MyHandler) GetUnhandled() []*chan *[]byte { + return []*chan *[]byte{} +} + +// Open is the callback for when the connection opens +// golintci: funlen +func (dch MyHandler) Run() error { + wgReceivers := sync.WaitGroup{} + + // open channel + wgReceivers.Add(1) + go func() { + defer wgReceivers.Done() + + for or := range dch.openChan { + fmt.Printf("------------ [OPEN] Deepgram WebSocket connection opened\n") + + // Send metadata to the UI + openJSON, err := json.Marshal(or) + if err != nil { + log.Println("Failed to marshal open to JSON:", err) + continue + } + + fmt.Printf("Open JSON: %s\n", openJSON) + dch.wsUI.WriteMessage(websocket.TextMessage, openJSON) + } + }() + + // flushed channel + wgReceivers.Add(1) + go func() { + defer wgReceivers.Done() + + for fr := range dch.flushedChan { + fmt.Printf("------------ [FLUSHED] Final Binary\n") + + // Send metadata to the UI + flushedJSON, err := json.Marshal(fr) + if err != nil { + log.Println("Failed to marshal flushed to JSON:", err) + continue + } + + fmt.Printf("Flushed JSON: %s\n", flushedJSON) + dch.wsUI.WriteMessage(websocket.TextMessage, flushedJSON) + } + }() + + // binary channel + wgReceivers.Add(1) + go func() { + defer wgReceivers.Done() + + lastTime := time.Now().Add(-5 * time.Second) + + for br := range dch.binaryChan { + if time.Since(lastTime) > 3*time.Second { + fmt.Printf("------------ [Binary Data] Attach header.\n") + + // Add a wav audio container header to the file if you want to play the audio + // using the AudioContext or media player like VLC, Media Player, or Apple Music + // Without this header in the Chrome browser case, the audio will not play. + header := []byte{ + 0x52, 0x49, 0x46, 0x46, // "RIFF" + 0x00, 0x00, 0x00, 0x00, // Placeholder for file size + 0x57, 0x41, 0x56, 0x45, // "WAVE" + 0x66, 0x6d, 0x74, 0x20, // "fmt " + 0x10, 0x00, 0x00, 0x00, // Chunk size (16) + 0x01, 0x00, // Audio format (1 for PCM) + 0x01, 0x00, // Number of channels (1) + 0x80, 0xbb, 0x00, 0x00, // Sample rate (48000) + 0x00, 0xee, 0x02, 0x00, // Byte rate (48000 * 2) + 0x02, 0x00, // Block align (2) + 0x10, 0x00, // Bits per sample (16) + 0x64, 0x61, 0x74, 0x61, // "data" + 0x00, 0x00, 0x00, 0x00, // Placeholder for data size + } + + dch.wsUI.WriteMessage(websocket.BinaryMessage, header) + lastTime = time.Now() + } + + fmt.Printf("------------ [Binary Data] (len: %d)\n", len(*br)) + dch.wsUI.WriteMessage(websocket.BinaryMessage, *br) + } + }() + + // close channel + wgReceivers.Add(1) + go func() { + defer wgReceivers.Done() + + for cr := range dch.closeChan { + fmt.Printf("------------ [Close] Deepgram WebSocket connection closed\n") + + // Send metadata to the UI + closeJSON, err := json.Marshal(cr) + if err != nil { + log.Println("Failed to marshal close to JSON:", err) + continue + } + + fmt.Printf("Close JSON: %s\n", closeJSON) + dch.wsUI.WriteMessage(websocket.TextMessage, closeJSON) + } + }() + + // error channel + wgReceivers.Add(1) + go func() { + defer wgReceivers.Done() + + for er := range dch.errorChan { + fmt.Printf("------------ [Error] ErrCode: %s\n", er.ErrCode) + fmt.Printf("ErrMsg: %s\n", er.ErrMsg) + fmt.Printf("Description: %s\n", er.Description) + + // Send metadata to the UI + errorJSON, err := json.Marshal(er) + if err != nil { + log.Println("Failed to marshal error to JSON:", err) + continue + } + + fmt.Printf("Error JSON: %s\n", errorJSON) + dch.wsUI.WriteMessage(websocket.TextMessage, errorJSON) + } + }() + + // wait for all receivers to finish + wgReceivers.Wait() + + return nil +} + +var upgrader = websocket.Upgrader{ + CheckOrigin: func(r *http.Request) bool { + return true + }, +} + +var requestData struct { + Text string `json:"text"` +} + +func handleWebSocket(w http.ResponseWriter, r *http.Request) { + // get the model from the query string + model := r.URL.Query().Get("model") + + conn, err := upgrader.Upgrade(w, r, nil) + if err != nil { + log.Println("Failed to upgrade connection to WebSocket:", err) + return + } + defer conn.Close() + + if model == "" { + fmt.Println("No model specified, using default model") + model = "aura-asteria-en" + } + + // context + ctx := context.Background() + + // client options, if needed + cOptions := clientinterfaces.ClientOptions{} + + // Create a new Deepgram WebSocket client + sOptions := clientinterfaces.WSSpeakOptions{ + Model: model, + Encoding: "linear16", + SampleRate: 48000, + } + callback := NewMyHandler(conn) + + wsClient, err := client.NewWSUsingChan(ctx, "", &cOptions, &sOptions, callback) + if err != nil { + log.Fatalf("Failed to create WebSocket client: %v", err) + return + } + + // Wait for the connection to be established + isConnected := wsClient.Connect() + if !isConnected { + log.Fatalf("Failed to connect to Deepgram") + return + } + + for { + // Read message from the WebSocket connection + msgType, message, err := conn.ReadMessage() + if err != nil { + log.Println("Failed to read message from WebSocket:", err) + break + } + + if msgType == websocket.TextMessage { + err = json.Unmarshal(message, &requestData) + if err != nil { + log.Println("Failed to unmarshal JSON:", err) + continue + } + + if requestData.Text == "" { + log.Println("Text is required in the request") + continue + } + + log.Printf("Text: %s\n", requestData.Text) + + err = wsClient.SpeakWithText(requestData.Text) + if err != nil { + log.Println("Failed to send text to Deepgram:", err) + } + + err = wsClient.Flush() + if err != nil { + fmt.Printf("Error flushing: %v\n", err) + return + } + } + } +} + +func main() { + client.Init(client.InitLib{ + LogLevel: client.LogLevelDefault, // LogLevelDefault, LogLevelFull, LogLevelDebug, LogLevelTrace + }) + + fs := http.FileServer(http.Dir("./public")) + http.Handle("/", fs) + http.HandleFunc("/ws", handleWebSocket) + + fmt.Printf("Open the UI at http://localhost:3000\n") + log.Fatal(http.ListenAndServe(":3000", nil)) +} diff --git a/public/assets/dg_favicon.ico b/public/assets/dg_favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..bdda536c2df5b1e814076a35784a191d7d2ec790 GIT binary patch literal 963 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 literal 0 HcmV?d00001 diff --git a/public/assets/preview-starter.png b/public/assets/preview-starter.png new file mode 100644 index 0000000000000000000000000000000000000000..a98af5f6192a155fd1f46314065f226262954e97 GIT binary patch literal 121990 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 U`ByBKf&Y#lF*uz0i^H}51w!QkQvd(} literal 0 HcmV?d00001 diff --git a/public/client.js b/public/client.js new file mode 100644 index 0000000..6cd659d --- /dev/null +++ b/public/client.js @@ -0,0 +1,187 @@ +const PLAY_STATES = { + NO_AUDIO: "no_audio", + LOADING: "loading", + PLAYING: "playing", +}; + +let playState = PLAY_STATES.NO_AUDIO; +let audioPlayer; +const textArea = document.getElementById("text-input"); +const errorMessage = document.querySelector("#error-message"); + +let audioChunks = []; // Array to buffer incoming audio data chunks +let socket; + +// Function to update the play button based on the current state +function updatePlayButton() { + const playButton = document.getElementById("play-button"); + const icon = playButton.querySelector(".button-icon"); + + switch (playState) { + case PLAY_STATES.NO_AUDIO: + icon.className = "button-icon fa-solid fa-play"; + break; + case PLAY_STATES.LOADING: + icon.className = "button-icon fa-solid fa-circle-notch"; + break; + case PLAY_STATES.PLAYING: + icon.className = "button-icon fa-solid fa-stop"; + break; + default: + break; + } +} + +// Function to stop audio +function stopAudio() { + audioPlayer = document.getElementById("audio-player"); + if (audioPlayer) { + playState = PLAY_STATES.PLAYING; + updatePlayButton(); + audioPlayer.pause(); + audioPlayer.currentTime = 0; + audioPlayer = null; + } +} + +// Function to handle the click event on the play button +function playButtonClick() { + switch (playState) { + case PLAY_STATES.NO_AUDIO: + sendData(); + break; + case PLAY_STATES.PLAYING: + stopAudio(); + playState = PLAY_STATES.NO_AUDIO; + updatePlayButton(); + break; + default: + break; + } +} + +// Remove error message when the text area has a value +textArea.addEventListener("input", () => { + errorMessage.innerHTML = ""; +}); + +// Function to send data to backend via WebSocket +function sendData() { + const modelSelect = document.getElementById("models"); + const selectedModel = modelSelect.options[modelSelect.selectedIndex].value; + const textInput = document.getElementById("text-input").value; + if (!textInput) { + errorMessage.innerHTML = "ERROR: Please add text!"; + } else { + playState = PLAY_STATES.LOADING; + updatePlayButton(); + + // we want to simulate holding a connection open like you would for a websocket + // that's the reason why we only initialize once + if (!socket) { + // create a new WebSocket connection + socket = new WebSocket(`ws://localhost:3000/ws?model=${selectedModel}`); + + // disable the model select + modelSelect.disabled = true; + + socket.addEventListener("open", () => { + const data = { + text: textInput, + }; + socket.send(JSON.stringify(data)); + }); + + socket.addEventListener("message", (event) => { + // console.log("Incoming event:", event); + + if (typeof event.data === "string") { + console.log("Incoming text data:", event.data); + + let msg = JSON.parse(event.data); + + if (msg.type === "Open") { + console.log("WebSocket opened 2"); + } else if (msg.type === "Error") { + console.error("WebSocket error:", error); + playState = PLAY_STATES.NO_AUDIO; + updatePlayButton(); + } else if (msg.type === "Close") { + console.log("WebSocket closed"); + playState = PLAY_STATES.NO_AUDIO; + updatePlayButton(); + } else if (msg.type === "Flushed") { + console.log("Flushed received"); + + // All data received, now combine chunks and play audio + const blob = new Blob(audioChunks, { type: "audio/wav" }); + + if (window.MediaSource) { + console.log('MP4 audio is supported'); + const audioContext = new AudioContext(); + + const reader = new FileReader(); + reader.onload = function () { + const arrayBuffer = this.result; + + audioContext.decodeAudioData(arrayBuffer, (buffer) => { + const source = audioContext.createBufferSource(); + source.buffer = buffer; + source.connect(audioContext.destination); + source.start(); + + playState = PLAY_STATES.PLAYING; + updatePlayButton(); + + source.onended = () => { + // Clear the buffer + audioChunks = []; + playState = PLAY_STATES.NO_AUDIO; + updatePlayButton(); + }; + }); + }; + reader.readAsArrayBuffer(blob); + } else { + console.error('MP4 audio is NOT supported'); + } + + // Clear the buffer + audioChunks = []; + } + } + + if (event.data instanceof Blob) { + // Incoming audio blob data + const blob = event.data; + console.log("Incoming blob data:", blob); + + // Push each blob into the array + audioChunks.push(blob); + } + }); + + socket.addEventListener("close", () => { + console.log("Close received"); + playState = PLAY_STATES.NO_AUDIO; + updatePlayButton(); + }); + + socket.addEventListener("error", (error) => { + console.error("WebSocket error:", error); + playState = PLAY_STATES.NO_AUDIO; + updatePlayButton(); + }); + } else { + const data = { + text: textInput, + }; + socket.send(JSON.stringify(data)); + } + } +} + +// Event listener for the click event on the play button +document + .getElementById("play-button") + .addEventListener("click", playButtonClick); diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..8f64596 --- /dev/null +++ b/public/index.html @@ -0,0 +1,70 @@ + + + + + Deepgram Test + + + + + +
+
+
+ + + +

Text-to-Speech

+
+
+
+ + + +
+
+ +
+
+
+

Be sure to check out:

+
    +
  • + The + main branch + of this repo to see basic functionality. +
  • +
+
+
+
+
+ + + diff --git a/public/style.css b/public/style.css new file mode 100644 index 0000000..4c18378 --- /dev/null +++ b/public/style.css @@ -0,0 +1,203 @@ +/* Import fonts */ +@import url("https://fonts.googleapis.com/css2?family=Arimo:wght@400;600;700"); +@import url("https://fonts.googleapis.com/css2?family=Inter"); + +/* Global styles */ +html { + background: #101014; + color: #fff; + font-family: Inter, sans-serif; +} + +/* Main content */ +main { + margin-left: auto; + margin-right: auto; + display: flex; + flex-direction: column; + min-height: 100vh; + max-width: 1400px; + gap: 1rem; + padding: 1.5rem; +} + +@media (min-width: 640px) { + main { + padding: 2rem; + } +} + +/* Grid container */ +.grid-container { + display: grid; + gap: 1rem; +} + +@media (min-width: 768px) { + .grid-container { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +/* Text-to-speech section */ +.tts-section { + display: flex; + flex-direction: column; + gap: 1rem; +} + +/* Button container */ +.button-container { + display: flex; + justify-content: space-between; +} + +/* Button icon */ +.button-icon { + color: #00dda2; + font-size: 1.5rem; +} + +/* Spinner animation */ +.fa-circle-notch { + animation: spin 1s ease-in-out infinite; + -webkit-animation: spin 1s ease-in-out infinite; +} + +@keyframes spin { + to { + -webkit-transform: rotate(360deg); + } +} +@-webkit-keyframes spin { + to { + -webkit-transform: rotate(360deg); + } +} + +/* Button styling */ +button { + background: linear-gradient(#000, #000) padding-box, + linear-gradient(90deg, #201cff -91.5%, #13ef95 80.05%) border-box; + height: 48px; + width: 113px; + border: 1px solid transparent; + border-radius: 4px; + cursor: pointer; +} + +/* Error message */ +#error-message { + color: rgb(255, 74, 93); + font-weight: 800; +} + +/* Dropdown select */ +select { + height: 54px; + border-radius: 4px; + border-width: 1px; + border-color: rgba(44, 44, 51, 1); + background-color: rgba(16, 16, 20, 1); + padding: 1rem; + font-family: Fira Code, monospace; + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); + color: white; +} + +/* Label */ +label { + font-size: 14px; +} + +/* Textarea */ +textarea { + color: white; + display: flex; + min-height: 256px; + border-radius: 4px; + border-width: 1px; + border-color: rgba(44, 44, 51, 1); + background-color: rgba(16, 16, 20, 1); + padding: 1rem; + font-family: Fira Code, monospace; + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); + resize: none; +} + +/* Deepgram logo */ +.dg-logo { + padding-top: 0.75rem; + width: 10rem; +} + +/* Title */ +.title { + display: flex; + gap: 0.5rem; + align-items: flex-start; + margin-bottom: 4rem; +} + +@media (min-width: 640px) { + .title { + flex-direction: row; + } +} + +h1 { + color: transparent; + background-clip: text; + background-image: linear-gradient(90deg, #201cff -91.5%, #13ef95 120.05%); + font-size: 1.5rem; + margin: 0; + font-weight: 800; + font-family: Arimo; +} + +@media (min-width: 640px) { + h1 { + font-size: 3.5rem; + } +} + +h2 { + font: 700 2rem / 3.75rem Arimo; + letter-spacing: -0.02em; +} + +/* Information section */ +.information-section { + margin-left: 0; +} + +@media (min-width: 768px) { + .information-section { + margin-left: 120px; + color: rgb(237, 237, 242); + } +} + +/* List */ +ul { + font-family: "Arimo"; + display: flex; + padding-left: 0px; + gap: 16px; + flex-direction: column; +} + +li { + font-size: 20px; + line-height: 1.75rem; +} + +li::marker { + color: #13ef95; +} + +/* Links */ +a { + color: #13ef95; + text-decoration: none; +} diff --git a/sample.env b/sample.env deleted file mode 100644 index d68a2a2..0000000 --- a/sample.env +++ /dev/null @@ -1 +0,0 @@ -DEEPGRAM_API_KEY=%api_key% \ No newline at end of file diff --git a/static/.gitkeep b/static/.gitkeep deleted file mode 100644 index e69de29..0000000