diff --git a/Cargo.toml b/Cargo.toml index 3edd898..0ebcf98 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,6 @@ byteorder = "1" bytes = "1" cpal = "0.15" crossbeam = "0.8" -deepgram = {path = "deepgram-rust-sdk"} eframe = {version = "0.27", default-features = false, features = ["default_fonts", "glow", "persistence"]} egui = "0.27" egui_extras = {version = "0.27", features = ["image"]} diff --git a/deepgram-rust-sdk/.github/ISSUE_TEMPLATE/bug_report.md b/deepgram-rust-sdk/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index a68b46a..0000000 --- a/deepgram-rust-sdk/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -name: Bug report -about: Something is occurring that I think is wrong -title: '' -labels: "bug" -assignees: '' - ---- - -## What is the current behavior? - - - -## Steps to reproduce - - - -## Expected behavior - - - -## Please tell us about your environment - -- **`deepgram` Package Version:** -- **Operating System/Version:** -- **Rust Version:** - -## Other information - - diff --git a/deepgram-rust-sdk/.github/ISSUE_TEMPLATE/config.yml b/deepgram-rust-sdk/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 422e244..0000000 --- a/deepgram-rust-sdk/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,4 +0,0 @@ -blank_issues_enabled: false -contact_links: - - name: DeepgramAI on Twitter - url: https://twitter.com/DeepgramAI diff --git a/deepgram-rust-sdk/.github/ISSUE_TEMPLATE/feature_request.md b/deepgram-rust-sdk/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index f99ae59..0000000 --- a/deepgram-rust-sdk/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: Feature Request -about: I think X would be a cool addition or change. -title: '' -labels: "enhancement" -assignees: '' - ---- - -## Proposed changes - - - -## Context - - - -## Possible Implementation - - - -## Other information - - diff --git a/deepgram-rust-sdk/.github/PULL_REQUEST_TEMPLATE.md b/deepgram-rust-sdk/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index d4b6aed..0000000 --- a/deepgram-rust-sdk/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,37 +0,0 @@ - - -## Proposed changes - - - -## Types of changes - - - - -- [ ] Bugfix (non-breaking change which fixes an issue) -- [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) -- [ ] Documentation update or tests (if none of the other choices apply) - -## Checklist - - - - -- [ ] I have read the [CONTRIBUTING.md](../CONTRIBUTING.md) doc -- [ ] I have added tests and/or examples that prove my fix is effective or that my feature works -- [ ] I have added necessary documentation (if appropriate) - -## Further comments - - diff --git a/deepgram-rust-sdk/.github/workflows/ci.yaml b/deepgram-rust-sdk/.github/workflows/ci.yaml deleted file mode 100644 index 42dab37..0000000 --- a/deepgram-rust-sdk/.github/workflows/ci.yaml +++ /dev/null @@ -1,93 +0,0 @@ -on: [push, pull_request] - -name: CI -env: - CARGO_TERM_COLOR: always - RUSTFLAGS: -D warnings - RUSTDOCFLAGS: -D warnings - -jobs: - Build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Install libasound2-dev - run: | - sudo apt-get update - sudo apt-get install libasound2-dev - - name: Cargo Build - run: cargo build --all-targets --all-features - Clippy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Install libasound2-dev - run: | - sudo apt-get update - sudo apt-get install libasound2-dev - - name: Cargo Clippy - run: cargo clippy --all-targets --all-features - Test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Install libasound2-dev - run: | - sudo apt-get update - sudo apt-get install libasound2-dev - - name: Cargo Test - run: cargo test --all --all-features - Format: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Cargo Fmt - run: cargo fmt --check --all - Documentation: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Cargo Doc - run: cargo doc --workspace --all-features - Audit: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Install cargo-audit - run: cargo install --locked cargo-audit - - name: Remove Dev Dependencies - run: | - cargo install --locked cargo-hack - cargo hack --remove-dev-deps - cargo generate-lockfile - - name: Cargo Audit - run: cargo audit - Minimal-Versions: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Install libasound2-dev - run: | - sudo apt-get update - sudo apt-get install libasound2-dev - - name: Install Rust Nightly - run: rustup toolchain install nightly - - name: Cargo Build - run: rustup run nightly cargo build --all-targets --all-features -Z minimal-versions - - name: Cargo Test - run: rustup run nightly cargo test --all --all-features -Z minimal-versions - - name: Remove Dev Dependencies - run: | - cargo install --locked cargo-hack - cargo hack --remove-dev-deps - rustup run nightly cargo generate-lockfile -Z minimal-versions - - name: Cargo Build Without Dev Dependencies - run: rustup run nightly cargo build --all-features -Z minimal-versions - SemVer: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Install cargo-semver-checks - run: cargo install --locked cargo-semver-checks - - name: Cargo SemVer Checks - run: cargo semver-checks check-release --verbose diff --git a/deepgram-rust-sdk/.gitignore b/deepgram-rust-sdk/.gitignore deleted file mode 100644 index 4fffb2f..0000000 --- a/deepgram-rust-sdk/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -/Cargo.lock diff --git a/deepgram-rust-sdk/CHANGELOG.md b/deepgram-rust-sdk/CHANGELOG.md deleted file mode 100644 index 6b686bc..0000000 --- a/deepgram-rust-sdk/CHANGELOG.md +++ /dev/null @@ -1,32 +0,0 @@ -# Changelog -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [Unreleased] - -## [0.4.0] - 2023-11-01 - -### Added -- `detect_language` option. - -### Changed -- Remove generic from `Deepgram` struct. -- Upgrade dependencies: `tungstenite`, `tokio-tungstenite`, `reqwest`. - -## [0.3.0] - -### Added -- Derive `Serialize` for all response types. - -### Fixed -- Use the users builder options when building a streaming URL. -- Make sure that `Future` returned from `StreamRequestBuilder::start()` is `Send`. - -### Changed -- Use Rustls instead of OpenSSL. - -[Unreleased]: https://github.com/deepgram-devs/deepgram-rust-sdk/compare/0.4.0...HEAD -[0.4.0]: https://github.com/deepgram-devs/deepgram-rust-sdk/compare/0.3.0...0.4.0 -[0.3.0]: https://github.com/deepgram-devs/deepgram-rust-sdk/compare/0.2.1...0.3.0 diff --git a/deepgram-rust-sdk/CODE_OF_CONDUCT.md b/deepgram-rust-sdk/CODE_OF_CONDUCT.md deleted file mode 100644 index 72005d0..0000000 --- a/deepgram-rust-sdk/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,3 +0,0 @@ -# Community Code of Conduct - -The Deepgram Community Code of Conduct can be found at \ No newline at end of file diff --git a/deepgram-rust-sdk/CONTRIBUTING.md b/deepgram-rust-sdk/CONTRIBUTING.md deleted file mode 100644 index f804f09..0000000 --- a/deepgram-rust-sdk/CONTRIBUTING.md +++ /dev/null @@ -1,49 +0,0 @@ -**NOTICE**: *For the majority of situations, please use the dev branch as the base for your pull request. -We only update the main branch when we release a new version of the package. -[More info](https://github.com/deepgram-devs/deepgram-rust-sdk/wiki/Branches).* - -# Contributing Guidelines - -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 it's 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. - -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. 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. -2. Clone/fetch your fork to your local development machine. -3. Create a new branch and check it out. -4. Make your changes and commit them. (Did the tests pass? No linting errors?) -5. Push your new branch to your fork. -6. Open a Pull Request from your new branch to the [`deepgram-devs/deepgram-rust-sdk`](https://github.com/deepgram-devs/deepgram-rust-sdk)'s `dev` branch. diff --git a/deepgram-rust-sdk/Cargo.toml b/deepgram-rust-sdk/Cargo.toml deleted file mode 100644 index 4d36654..0000000 --- a/deepgram-rust-sdk/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "deepgram" -version = "0.4.0" -authors = ["Deepgram "] -edition = "2021" -description = "Official Rust SDK for Deepgram's automated speech recognition APIs." -license = "MIT" -repository = "https://github.com/deepgram-devs/deepgram-rust-sdk" -keywords = ["deepgram", "asr", "transcription", "ai", "speech-to-text"] -categories = ["api-bindings", "multimedia::audio"] - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -# TODO Investigate which of these dependencies can go behind features. -bytes = "1" -futures = "0.3" -http = "1" -pin-project = "1" -reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls", "stream"] } -serde = { version = "1", features = ["derive"] } -serde_json = "1" -thiserror = "1" -tokio = { version = "1", features = ["full"] } -tokio-tungstenite = { version = "0.21", features = ["rustls-tls-webpki-roots"] } -tokio-util = { version = "0.7.1", features = ["codec", "io"] } -tungstenite = "0.21" -url = "2" -uuid = { version = "1", features = ["serde"] } -# Dependencies below are specified only to satisfy minimal-versions. -proc-macro2 = "1.0.60" - -[dev-dependencies] -pkg-config = "0.3.27" -cpal = "0.14" -crossbeam = "0.8" diff --git a/deepgram-rust-sdk/LICENSE b/deepgram-rust-sdk/LICENSE deleted file mode 100644 index 6aa6f9d..0000000 --- a/deepgram-rust-sdk/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 Deepgram - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/deepgram-rust-sdk/README.md b/deepgram-rust-sdk/README.md deleted file mode 100644 index beb5f4b..0000000 --- a/deepgram-rust-sdk/README.md +++ /dev/null @@ -1,58 +0,0 @@ -# Deepgram Rust SDK - -[![CI](https://github.com/deepgram-devs/deepgram-rust-sdk/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/deepgram-devs/deepgram-rust-sdk/actions/workflows/ci.yaml) -[![crates.io](https://img.shields.io/crates/v/deepgram)](https://crates.io/crates/deepgram) -[![downloads](https://img.shields.io/crates/d/deepgram)](https://crates.io/crates/deepgram) -[![docs](https://img.shields.io/docsrs/deepgram)](https://docs.rs/deepgram) -[![license](https://img.shields.io/crates/l/deepgram)](./LICENSE) - -Experimental Rust SDK for [Deepgram](https://www.deepgram.com/). Power your apps with world-class speech and Language AI models. - -> This SDK only supports hosted usage of api.deepgram.com. - -## Getting an API Key - -🔑 To access the Deepgram API you will need a [free Deepgram API Key](https://console.deepgram.com/signup?jump=keys). -## Documentation - -You can learn more about the Deepgram API at [developers.deepgram.com](https://developers.deepgram.com/docs). - -## Current Status - -This SDK is still very much work-in-progress. The interface is subject to rapid change. -## Install - -From within your Cargo project directory, run the following command: - -```sh -cargo add deepgram -``` - -You will also probably need to install [`tokio`](https://crates.io/crates/tokio): - -```sh -cargo add tokio --features full -``` - -## Documentation and Examples - -Documentation and examples can be found on our [Docs.rs page](https://docs.rs/deepgram/latest/deepgram/). - -## Development and Contributing - -Interested in contributing? We ❤️ pull requests! - -To make sure our community is safe for all, be sure to review and agree to our -[Code of Conduct](./CODE_OF_CONDUCT.md). Then see the -[Contributing Guidelines](./CONTRIBUTING.md) for more information. - -## 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-devs/deepgram-rust-sdk/issues/new) -- [Join the Deepgram Github Discussions Community](https://github.com/orgs/deepgram/discussions) -- [Join the Deepgram Discord Community](https://discord.gg/xWRaCDBtW4) - -[license]: LICENSE.txt \ No newline at end of file diff --git a/deepgram-rust-sdk/examples/billing.rs b/deepgram-rust-sdk/examples/billing.rs deleted file mode 100644 index 73cc0c8..0000000 --- a/deepgram-rust-sdk/examples/billing.rs +++ /dev/null @@ -1,27 +0,0 @@ -use deepgram::{Deepgram, DeepgramError}; -use std::env; - -#[tokio::main] -async fn main() -> Result<(), DeepgramError> { - let deepgram_api_key = - env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - - let project_id = - env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - - let balance_id = - env::var("DEEPGRAM_BALANCE_ID").expect("DEEPGRAM_BALANCE_ID environmental variable"); - - let dg_client = Deepgram::new(&deepgram_api_key); - - let all_balances = dg_client.billing().list_balance(&project_id).await?; - println!("{:#?}", all_balances); - - let specific_balance = dg_client - .billing() - .get_balance(&project_id, &balance_id) - .await?; - println!("{:#?}", specific_balance); - - Ok(()) -} diff --git a/deepgram-rust-sdk/examples/callback.rs b/deepgram-rust-sdk/examples/callback.rs deleted file mode 100644 index 5533c31..0000000 --- a/deepgram-rust-sdk/examples/callback.rs +++ /dev/null @@ -1,38 +0,0 @@ -use std::env; - -use deepgram::{ - transcription::prerecorded::{ - audio_source::AudioSource, - options::{Language, Options}, - }, - Deepgram, DeepgramError, -}; - -static AUDIO_URL: &str = "https://static.deepgram.com/examples/Bueller-Life-moves-pretty-fast.wav"; - -#[tokio::main] -async fn main() -> Result<(), DeepgramError> { - let deepgram_api_key = - env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - - let dg_client = Deepgram::new(&deepgram_api_key); - - let source = AudioSource::from_url(AUDIO_URL); - - let options = Options::builder() - .punctuate(true) - .language(Language::en_US) - .build(); - - let callback_url = - env::var("DEEPGRAM_CALLBACK_URL").expect("DEEPGRAM_CALLBACK_URL environmental variable"); - - let response = dg_client - .transcription() - .prerecorded_callback(source, &options, &callback_url) - .await?; - - println!("{}", response.request_id); - - Ok(()) -} diff --git a/deepgram-rust-sdk/examples/invitations.rs b/deepgram-rust-sdk/examples/invitations.rs deleted file mode 100644 index 8bbf088..0000000 --- a/deepgram-rust-sdk/examples/invitations.rs +++ /dev/null @@ -1,19 +0,0 @@ -use std::env; - -use deepgram::{Deepgram, DeepgramError}; - -#[tokio::main] -async fn main() -> Result<(), DeepgramError> { - let deepgram_api_key = - env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - - let project_id = - env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - - let dg_client = Deepgram::new(&deepgram_api_key); - - let message = dg_client.invitations().leave_project(&project_id).await?; - println!("{:#?}", message); - - Ok(()) -} diff --git a/deepgram-rust-sdk/examples/keys.rs b/deepgram-rust-sdk/examples/keys.rs deleted file mode 100644 index 463a44f..0000000 --- a/deepgram-rust-sdk/examples/keys.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::env; - -use deepgram::{keys::options::Options, Deepgram, DeepgramError}; - -#[tokio::main] -async fn main() -> Result<(), DeepgramError> { - let deepgram_api_key = - env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - - let project_id = - env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - - let key_id = env::var("DEEPGRAM_KEY_ID").expect("DEEPGRAM_KEY_ID environmental variable"); - - let dg_client = Deepgram::new(&deepgram_api_key); - - let keys = dg_client.keys().list(&project_id).await?; - println!("{:#?}", keys); - - let key = dg_client.keys().get(&project_id, &key_id).await?; - println!("{:#?}", key); - - let options = Options::builder("New Key", ["member"]).build(); - let new_key = dg_client.keys().create(&project_id, &options).await?; - println!("{:#?}", new_key); - - let message = dg_client.keys().delete(&project_id, &key_id).await?; - println!("{}", message.message); - - Ok(()) -} diff --git a/deepgram-rust-sdk/examples/make_prerecorded_request_builder.rs b/deepgram-rust-sdk/examples/make_prerecorded_request_builder.rs deleted file mode 100644 index 53ceb26..0000000 --- a/deepgram-rust-sdk/examples/make_prerecorded_request_builder.rs +++ /dev/null @@ -1,45 +0,0 @@ -use std::env; - -use deepgram::{ - transcription::prerecorded::{ - audio_source::AudioSource, - options::{Language, Options}, - response::Response, - }, - Deepgram, -}; - -static AUDIO_URL: &str = "https://static.deepgram.com/examples/Bueller-Life-moves-pretty-fast.wav"; - -#[tokio::main] -async fn main() -> reqwest::Result<()> { - let deepgram_api_key = - env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - - let dg_client = Deepgram::new(&deepgram_api_key); - - let source = AudioSource::from_url(AUDIO_URL); - - let options = Options::builder() - .punctuate(true) - .language(Language::en_US) - .build(); - - let request_builder = dg_client - .transcription() - .make_prerecorded_request_builder(source, &options); - - // Customize the RequestBuilder here - let customized_request_builder = request_builder - .query(&[("custom_query_key", "custom_query_value")]) - .header("custom_header_key", "custom_header_value"); - - // It is necessary to annotate the type of response here - // That way it knows what type to deserialize the JSON into - let response: Response = customized_request_builder.send().await?.json().await?; - - let transcript = &response.results.channels[0].alternatives[0].transcript; - println!("{}", transcript); - - Ok(()) -} diff --git a/deepgram-rust-sdk/examples/members.rs b/deepgram-rust-sdk/examples/members.rs deleted file mode 100644 index 27de3fd..0000000 --- a/deepgram-rust-sdk/examples/members.rs +++ /dev/null @@ -1,28 +0,0 @@ -use std::env; - -use deepgram::{Deepgram, DeepgramError}; - -#[tokio::main] -async fn main() -> Result<(), DeepgramError> { - let deepgram_api_key = - env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - - let project_id = - env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - - let member_id = - env::var("DEEPGRAM_MEMBER_ID").expect("DEEPGRAM_MEMBER_ID environmental variable"); - - let dg_client = Deepgram::new(&deepgram_api_key); - - let members = dg_client.members().list_members(&project_id).await?; - println!("{:#?}", members); - - let message = dg_client - .members() - .remove_member(&project_id, &member_id) - .await?; - println!("{}", message.message); - - Ok(()) -} diff --git a/deepgram-rust-sdk/examples/microphone_stream.rs b/deepgram-rust-sdk/examples/microphone_stream.rs deleted file mode 100644 index 9165226..0000000 --- a/deepgram-rust-sdk/examples/microphone_stream.rs +++ /dev/null @@ -1,112 +0,0 @@ -use std::env; -use std::thread; - -use bytes::{BufMut, Bytes, BytesMut}; -use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; -use cpal::Sample; -use crossbeam::channel::RecvError; -use futures::channel::mpsc::{self, Receiver as FuturesReceiver}; -use futures::stream::StreamExt; -use futures::SinkExt; - -use deepgram::{Deepgram, DeepgramError}; - -fn microphone_as_stream() -> FuturesReceiver> { - let (sync_tx, sync_rx) = crossbeam::channel::unbounded(); - let (mut async_tx, async_rx) = mpsc::channel(1); - - thread::spawn(move || { - let host = cpal::default_host(); - let device = host.default_input_device().unwrap(); - - // let config = device.supported_input_configs().unwrap(); - // for config in config { - // dbg!(&config); - // } - - let config = device.default_input_config().unwrap(); - - // dbg!(&config); - - let stream = match config.sample_format() { - cpal::SampleFormat::F32 => device - .build_input_stream( - &config.into(), - move |data: &[f32], _: &_| { - let mut bytes = BytesMut::with_capacity(data.len() * 2); - for sample in data { - bytes.put_i16_le(sample.to_i16()); - } - sync_tx.send(bytes.freeze()).unwrap(); - }, - |_| panic!(), - ) - .unwrap(), - cpal::SampleFormat::I16 => device - .build_input_stream( - &config.into(), - move |data: &[i16], _: &_| { - let mut bytes = BytesMut::with_capacity(data.len() * 2); - for sample in data { - bytes.put_i16_le(*sample); - } - sync_tx.send(bytes.freeze()).unwrap(); - }, - |_| panic!(), - ) - .unwrap(), - cpal::SampleFormat::U16 => device - .build_input_stream( - &config.into(), - move |data: &[u16], _: &_| { - let mut bytes = BytesMut::with_capacity(data.len() * 2); - for sample in data { - bytes.put_i16_le(sample.to_i16()); - } - sync_tx.send(bytes.freeze()).unwrap(); - }, - |_| panic!(), - ) - .unwrap(), - }; - - stream.play().unwrap(); - - loop { - thread::park(); - } - }); - - tokio::spawn(async move { - loop { - let data = sync_rx.recv(); - async_tx.send(data).await.unwrap(); - } - }); - - async_rx -} - -#[tokio::main] -async fn main() -> Result<(), DeepgramError> { - let dg = Deepgram::new(env::var("DEEPGRAM_API_KEY").unwrap()); - - let mut results = dg - .transcription() - .stream_request() - .stream(microphone_as_stream()) - // TODO Enum. - .encoding("linear16".to_string()) - // TODO Specific to my machine, not general enough example. - .sample_rate(44100) - // TODO Specific to my machine, not general enough example. - .channels(2) - .start() - .await?; - - while let Some(result) = results.next().await { - println!("got: {:?}", result); - } - - Ok(()) -} diff --git a/deepgram-rust-sdk/examples/prerecorded_from_file/Bueller-Life-moves-pretty-fast.mp3 b/deepgram-rust-sdk/examples/prerecorded_from_file/Bueller-Life-moves-pretty-fast.mp3 deleted file mode 100644 index 0de454c..0000000 Binary files a/deepgram-rust-sdk/examples/prerecorded_from_file/Bueller-Life-moves-pretty-fast.mp3 and /dev/null differ diff --git a/deepgram-rust-sdk/examples/prerecorded_from_file/main.rs b/deepgram-rust-sdk/examples/prerecorded_from_file/main.rs deleted file mode 100644 index c80872c..0000000 --- a/deepgram-rust-sdk/examples/prerecorded_from_file/main.rs +++ /dev/null @@ -1,39 +0,0 @@ -use std::env; - -use deepgram::{ - transcription::prerecorded::{ - audio_source::AudioSource, - options::{Language, Options}, - }, - Deepgram, DeepgramError, -}; -use tokio::fs::File; - -static PATH_TO_FILE: &str = "examples/prerecorded_from_file/Bueller-Life-moves-pretty-fast.mp3"; - -#[tokio::main] -async fn main() -> Result<(), DeepgramError> { - let deepgram_api_key = - env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - - let dg_client = Deepgram::new(&deepgram_api_key); - - let file = File::open(PATH_TO_FILE).await.unwrap(); - - let source = AudioSource::from_buffer_with_mime_type(file, "audio/mpeg3"); - - let options = Options::builder() - .punctuate(true) - .language(Language::en_US) - .build(); - - let response = dg_client - .transcription() - .prerecorded(source, &options) - .await?; - - let transcript = &response.results.channels[0].alternatives[0].transcript; - println!("{}", transcript); - - Ok(()) -} diff --git a/deepgram-rust-sdk/examples/prerecorded_from_url.rs b/deepgram-rust-sdk/examples/prerecorded_from_url.rs deleted file mode 100644 index d7de33e..0000000 --- a/deepgram-rust-sdk/examples/prerecorded_from_url.rs +++ /dev/null @@ -1,36 +0,0 @@ -use std::env; - -use deepgram::{ - transcription::prerecorded::{ - audio_source::AudioSource, - options::{Language, Options}, - }, - Deepgram, DeepgramError, -}; - -static AUDIO_URL: &str = "https://static.deepgram.com/examples/Bueller-Life-moves-pretty-fast.wav"; - -#[tokio::main] -async fn main() -> Result<(), DeepgramError> { - let deepgram_api_key = - env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - - let dg_client = Deepgram::new(&deepgram_api_key); - - let source = AudioSource::from_url(AUDIO_URL); - - let options = Options::builder() - .punctuate(true) - .language(Language::en_US) - .build(); - - let response = dg_client - .transcription() - .prerecorded(source, &options) - .await?; - - let transcript = &response.results.channels[0].alternatives[0].transcript; - println!("{}", transcript); - - Ok(()) -} diff --git a/deepgram-rust-sdk/examples/projects.rs b/deepgram-rust-sdk/examples/projects.rs deleted file mode 100644 index bd0c784..0000000 --- a/deepgram-rust-sdk/examples/projects.rs +++ /dev/null @@ -1,32 +0,0 @@ -use std::env; - -use deepgram::{projects::options::Options, Deepgram, DeepgramError}; - -#[tokio::main] -async fn main() -> Result<(), DeepgramError> { - let deepgram_api_key = - env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - - let project_id = - env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - - let dg_client = Deepgram::new(&deepgram_api_key); - - let projects = dg_client.projects().list().await?; - println!("{:#?}", projects); - - let project = dg_client.projects().get(&project_id).await?; - println!("{:#?}", project); - - let options = Options::builder() - .name("The Transcribinator") - .company("Doofenshmirtz Evil Incorporated") - .build(); - let message = dg_client.projects().update(&project_id, &options).await?; - println!("{}", message.message); - - let message = dg_client.projects().delete(&project_id).await?; - println!("{}", message.message); - - Ok(()) -} diff --git a/deepgram-rust-sdk/examples/scopes.rs b/deepgram-rust-sdk/examples/scopes.rs deleted file mode 100644 index 3d376b4..0000000 --- a/deepgram-rust-sdk/examples/scopes.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::env; - -use deepgram::{Deepgram, DeepgramError}; - -#[tokio::main] -async fn main() -> Result<(), DeepgramError> { - let deepgram_api_key = - env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - - let project_id = - env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - - let member_id = - env::var("DEEPGRAM_MEMBER_ID").expect("DEEPGRAM_MEMBER_ID environmental variable"); - - let dg_client = Deepgram::new(&deepgram_api_key); - - let scopes = dg_client - .scopes() - .get_scope(&project_id, &member_id) - .await?; - println!("{:#?}", scopes); - - let message = dg_client - .scopes() - .update_scope(&project_id, &member_id, "member") - .await?; - println!("{}", message.message); - - Ok(()) -} diff --git a/deepgram-rust-sdk/examples/simple_stream.rs b/deepgram-rust-sdk/examples/simple_stream.rs deleted file mode 100644 index 424dc7a..0000000 --- a/deepgram-rust-sdk/examples/simple_stream.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::env; -use std::time::Duration; - -use futures::stream::StreamExt; - -use deepgram::{Deepgram, DeepgramError}; - -#[tokio::main] -async fn main() -> Result<(), DeepgramError> { - let dg = Deepgram::new(env::var("DEEPGRAM_API_KEY").unwrap()); - - let mut results = dg - .transcription() - .stream_request() - .file( - env::var("FILENAME").unwrap(), - 3174, - Duration::from_millis(16), - ) - .await? - .start() - .await?; - - while let Some(result) = results.next().await { - println!("got: {:?}", result); - } - - Ok(()) -} diff --git a/deepgram-rust-sdk/examples/usage.rs b/deepgram-rust-sdk/examples/usage.rs deleted file mode 100644 index 8f20891..0000000 --- a/deepgram-rust-sdk/examples/usage.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::env; - -use deepgram::{ - usage::{get_fields_options, get_usage_options, list_requests_options}, - Deepgram, DeepgramError, -}; - -#[tokio::main] -async fn main() -> Result<(), DeepgramError> { - let deepgram_api_key = - env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - - let project_id = - env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - - let request_id = - env::var("DEEPGRAM_REQUEST_ID").expect("DEEPGRAM_REQUEST_ID environmental variable"); - - let dg_client = Deepgram::new(&deepgram_api_key); - - let options = list_requests_options::Options::builder().build(); - let requests = dg_client - .usage() - .list_requests(&project_id, &options) - .await?; - println!("{:#?}", requests); - - let request = dg_client - .usage() - .get_request(&project_id, &request_id) - .await?; - println!("{:#?}", request); - - let options = get_usage_options::Options::builder().build(); - let summary = dg_client.usage().get_usage(&project_id, &options).await?; - println!("{:#?}", summary); - - let options = get_fields_options::Options::builder().build(); - let summary = dg_client.usage().get_fields(&project_id, &options).await?; - println!("{:#?}", summary); - - Ok(()) -} diff --git a/deepgram-rust-sdk/rustfmt.toml b/deepgram-rust-sdk/rustfmt.toml deleted file mode 100644 index 8b13789..0000000 --- a/deepgram-rust-sdk/rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/deepgram-rust-sdk/src/billing.rs b/deepgram-rust-sdk/src/billing.rs deleted file mode 100644 index a3d775d..0000000 --- a/deepgram-rust-sdk/src/billing.rs +++ /dev/null @@ -1,135 +0,0 @@ -//! Get the outstanding balances for a Deepgram Project. -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#billing - -use crate::{send_and_translate_response, Deepgram}; - -pub mod response; - -use response::{Balance, Balances}; - -/// Get the outstanding balances for a Deepgram Project. -/// -/// Constructed using [`Deepgram::billing`]. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#billing -#[derive(Debug, Clone)] -pub struct Billing<'a>(&'a Deepgram); - -impl Deepgram { - /// Construct a new [`Billing`] from a [`Deepgram`]. - pub fn billing(&self) -> Billing<'_> { - self.into() - } -} - -impl<'a> From<&'a Deepgram> for Billing<'a> { - /// Construct a new [`Billing`] from a [`Deepgram`]. - fn from(deepgram: &'a Deepgram) -> Self { - Self(deepgram) - } -} - -impl Billing<'_> { - /// Get the outstanding balances for the specified project. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#billing-all - /// - /// # Examples - /// - /// ```no_run - /// # use deepgram::{Deepgram, DeepgramError}; - /// # use std::env; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// let balances = dg_client - /// .billing() - /// .list_balance(&project_id) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn list_balance(&self, project_id: &str) -> crate::Result { - let url = format!( - "https://api.deepgram.com/v1/projects/{}/balances", - project_id, - ); - - send_and_translate_response(self.0.client.get(url)).await - } - - /// Get the details of a specific balance. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#billing-get - /// - /// # Examples - /// - /// ```no_run - /// # use deepgram::{Deepgram, DeepgramError}; - /// # use std::env; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// # let balance_id = - /// # env::var("DEEPGRAM_BALANCE_ID").expect("DEEPGRAM_BALANCE_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// let balance = dg_client - /// .billing() - /// .get_balance(&project_id, &balance_id) - /// .await?; - /// - /// assert_eq!(balance_id, balance.balance_id.to_string()); - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn get_balance(&self, project_id: &str, balance_id: &str) -> crate::Result { - let url = format!( - "https://api.deepgram.com/v1/projects/{}/balances/{}", - project_id, balance_id, - ); - - send_and_translate_response(self.0.client.get(url)).await - } -} - -#[cfg(test)] -mod tests { - use super::{response::BillingUnits, *}; - - #[test] - fn test() { - assert_eq!( - serde_json::from_str::( - "{\"balance_id\":\"a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8\",\"amount\":1,\"units\":\"usd\",\"purchase_order_id\":\"a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8\"}", - ).unwrap().units, - BillingUnits::Usd - ); - } -} diff --git a/deepgram-rust-sdk/src/billing/response.rs b/deepgram-rust-sdk/src/billing/response.rs deleted file mode 100644 index 3068c6e..0000000 --- a/deepgram-rust-sdk/src/billing/response.rs +++ /dev/null @@ -1,55 +0,0 @@ -//! Deepgram billing API response types. - -use serde::{Deserialize, Serialize}; -use uuid::Uuid; - -/// The balances for a Deepgram Project. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#billing -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Balances { - #[allow(missing_docs)] - pub balances: Vec, -} - -/// Information about a specific balance. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#billing -#[allow(missing_docs)] // Struct fields are documented in the API reference -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Balance { - #[allow(missing_docs)] - pub balance_id: Uuid, - - #[allow(missing_docs)] - pub amount: f64, - - #[allow(missing_docs)] - pub units: BillingUnits, - - #[allow(missing_docs)] - pub purchase_order_id: Uuid, -} - -/// Units for the [`Balance::amount`] field. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#billing -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Serialize, Deserialize)] -#[non_exhaustive] -pub enum BillingUnits { - #[allow(missing_docs)] - #[serde(rename = "usd")] - Usd, - - #[allow(missing_docs)] - #[serde(rename = "hour")] - Hour, -} diff --git a/deepgram-rust-sdk/src/invitations.rs b/deepgram-rust-sdk/src/invitations.rs deleted file mode 100644 index fae53b6..0000000 --- a/deepgram-rust-sdk/src/invitations.rs +++ /dev/null @@ -1,74 +0,0 @@ -//! Manage the invitations to a Deepgram Project. -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#invitations - -use crate::{send_and_translate_response, Deepgram}; - -pub mod response; - -use response::Message; - -/// Manage the invitations to a Deepgram Project. -/// -/// Constructed using [`Deepgram::invitations`]. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#invitations -#[derive(Debug, Clone)] -pub struct Invitations<'a>(&'a Deepgram); - -impl Deepgram { - /// Construct a new [`Invitations`] from a [`Deepgram`]. - pub fn invitations(&self) -> Invitations<'_> { - self.into() - } -} - -impl<'a> From<&'a Deepgram> for Invitations<'a> { - /// Construct a new [`Invitations`] from a [`Deepgram`]. - fn from(deepgram: &'a Deepgram) -> Self { - Self(deepgram) - } -} - -impl Invitations<'_> { - /// Remove the authenticated account from the specified project. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#invitations - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{Deepgram, DeepgramError}; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// dg_client - /// .invitations() - /// .leave_project(&project_id) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn leave_project(&self, project_id: &str) -> crate::Result { - let url = format!("https://api.deepgram.com/v1/projects/{}/leave", project_id,); - - send_and_translate_response(self.0.client.delete(url)).await - } -} diff --git a/deepgram-rust-sdk/src/invitations/response.rs b/deepgram-rust-sdk/src/invitations/response.rs deleted file mode 100644 index 657f8ab..0000000 --- a/deepgram-rust-sdk/src/invitations/response.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! Deepgram invitations API response types. - -use serde::{Deserialize, Serialize}; - -/// Success message. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#invitations -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Message { - #[allow(missing_docs)] - pub message: String, -} diff --git a/deepgram-rust-sdk/src/keys.rs b/deepgram-rust-sdk/src/keys.rs deleted file mode 100644 index 3b76b1c..0000000 --- a/deepgram-rust-sdk/src/keys.rs +++ /dev/null @@ -1,205 +0,0 @@ -//! Manage the keys for a Deepgram Project. -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#keys - -use crate::{send_and_translate_response, Deepgram}; - -pub mod options; -pub mod response; - -use options::{Options, SerializableOptions}; -use response::{MemberAndApiKey, MembersAndApiKeys, Message, NewApiKey}; - -/// Manage the keys for a Deepgram Project. -/// -/// Constructed using [`Deepgram::keys`]. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#keys -#[derive(Debug, Clone)] -pub struct Keys<'a>(&'a Deepgram); - -impl Deepgram { - /// Construct a new [`Keys`] from a [`Deepgram`]. - pub fn keys(&self) -> Keys<'_> { - self.into() - } -} - -impl<'a> From<&'a Deepgram> for Keys<'a> { - /// Construct a new [`Keys`] from a [`Deepgram`]. - fn from(deepgram: &'a Deepgram) -> Self { - Self(deepgram) - } -} - -impl Keys<'_> { - /// Get keys for the specified project. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#keys-get-keys - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{keys::options::Options, Deepgram, DeepgramError}; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// let keys = dg_client - /// .keys() - /// .list(&project_id) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn list(&self, project_id: &str) -> crate::Result { - let url = format!("https://api.deepgram.com/v1/projects/{}/keys", project_id); - - send_and_translate_response(self.0.client.get(url)).await - } - - /// Get details of the specified key. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#keys-get-key - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{keys::options::Options, Deepgram, DeepgramError}; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// # let key_id = env::var("DEEPGRAM_KEY_ID").expect("DEEPGRAM_KEY_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// let key = dg_client - /// .keys() - /// .get(&project_id, &key_id) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn get(&self, project_id: &str, key_id: &str) -> crate::Result { - let url = format!( - "https://api.deepgram.com/v1/projects/{}/keys/{}", - project_id, key_id, - ); - - send_and_translate_response(self.0.client.get(url)).await - } - - /// Create a new key in the specified project. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#keys-create - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{keys::options::Options, Deepgram, DeepgramError}; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// # let key_id = env::var("DEEPGRAM_KEY_ID").expect("DEEPGRAM_KEY_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// let options = Options::builder("New Key", ["member"]).build(); - /// let new_key = dg_client - /// .keys() - /// .create(&project_id, &options) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn create(&self, project_id: &str, options: &Options) -> crate::Result { - let url = format!("https://api.deepgram.com/v1/projects/{}/keys", project_id); - let request = self - .0 - .client - .post(url) - .json(&SerializableOptions::from(options)); - - send_and_translate_response(request).await - } - - /// Delete the specified key in the specified project. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#keys-delete - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{keys::options::Options, Deepgram, DeepgramError}; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// # let key_id = env::var("DEEPGRAM_KEY_ID").expect("DEEPGRAM_KEY_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// dg_client - /// .keys() - /// .delete(&project_id, &key_id) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn delete(&self, project_id: &str, key_id: &str) -> crate::Result { - let url = format!( - "https://api.deepgram.com/v1/projects/{}/keys/{}", - project_id, key_id, - ); - - send_and_translate_response(self.0.client.delete(url)).await - } -} diff --git a/deepgram-rust-sdk/src/keys/options.rs b/deepgram-rust-sdk/src/keys/options.rs deleted file mode 100644 index 9ded59e..0000000 --- a/deepgram-rust-sdk/src/keys/options.rs +++ /dev/null @@ -1,259 +0,0 @@ -//! Set options for [`Keys::create`](super::Keys::create). -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#keys-create - -use serde::Serialize; - -/// Used as a parameter for [`Keys::create`](super::Keys::create). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#keys-create -#[derive(Debug, PartialEq, Clone)] -pub struct Options { - comment: String, - tags: Vec, - scopes: Vec, - expiration: Option, -} - -#[derive(Debug, PartialEq, Clone)] -enum Expiration { - ExpirationDate(String), - TimeToLiveInSeconds(usize), -} - -/// Builds an [`Options`] object using [the Builder pattern][builder]. -/// -/// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html -#[derive(Debug, PartialEq, Clone)] -pub struct OptionsBuilder(Options); - -#[derive(Serialize)] -pub(super) struct SerializableOptions<'a> { - comment: &'a String, - - #[serde(skip_serializing_if = "Vec::is_empty")] - tags: &'a Vec, - - scopes: &'a Vec, - - #[serde(skip_serializing_if = "Option::is_none")] - expiration_date: Option<&'a String>, - - #[serde(skip_serializing_if = "Option::is_none")] - time_to_live_in_seconds: Option, -} - -impl Options { - /// Construct a new [`OptionsBuilder`]. - pub fn builder<'a>( - comment: impl Into, - scopes: impl IntoIterator, - ) -> OptionsBuilder { - OptionsBuilder::new(comment, scopes) - } -} - -impl OptionsBuilder { - /// Construct a new [`OptionsBuilder`]. - pub fn new<'a>(comment: impl Into, scopes: impl IntoIterator) -> Self { - Self(Options { - comment: comment.into(), - tags: Vec::new(), - scopes: scopes.into_iter().map(String::from).collect(), - expiration: None, - }) - } - - /// Set the comment. - /// - /// This will overwrite any previously set comment, - /// including the one set in [`OptionsBuilder::new`] for [`Options::builder`]. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::keys::options::Options; - /// # - /// let options1 = Options::builder("Old comment", ["member"]) - /// .comment("New comment") - /// .build(); - /// - /// let options2 = Options::builder("New comment", ["member"]).build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn comment(mut self, comment: impl Into) -> Self { - self.0.comment = comment.into(); - self - } - - /// Set the tags. - /// - /// Calling this when already set will append to the existing tags, not overwrite them. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::keys::options::Options; - /// # - /// let options = Options::builder("New Key", ["member"]) - /// .tag(["Tag 1", "Tag 2"]) - /// .build(); - /// ``` - /// - /// ``` - /// # use deepgram::keys::options::Options; - /// # - /// let options1 = Options::builder("New Key", ["member"]) - /// .tag(["Tag 1"]) - /// .tag(["Tag 2"]) - /// .build(); - /// - /// let options2 = Options::builder("New Key", ["member"]) - /// .tag(["Tag 1", "Tag 2"]) - /// .build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn tag<'a>(mut self, tags: impl IntoIterator) -> Self { - self.0.tags.extend(tags.into_iter().map(String::from)); - self - } - - /// Set additional scopes. - /// - /// Calling this when already set will append to the existing scopes, not overwrite them. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::keys::options::Options; - /// # - /// let options = Options::builder("New Key", ["member"]) - /// .scopes(["admin"]) - /// .build(); - /// ``` - /// - /// ``` - /// # use deepgram::keys::options::Options; - /// # - /// let options1 = Options::builder("New Key", ["member"]) - /// .scopes(["admin"]) - /// .build(); - /// - /// let options2 = Options::builder("New Key", ["member", "admin"]).build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn scopes<'a>(mut self, scopes: impl IntoIterator) -> Self { - self.0.scopes.extend(scopes.into_iter().map(String::from)); - self - } - - /// Set the expiration date. - /// - /// This will unset the time to live in seconds. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::keys::options::Options; - /// # - /// let options = Options::builder("New Key", ["member"]) - /// .expiration_date("2038-01-19") - /// .build(); - /// ``` - /// - /// ``` - /// # use deepgram::keys::options::Options; - /// # - /// let options1 = Options::builder("New Key", ["member"]) - /// .time_to_live_in_seconds(7776000) - /// .expiration_date("2038-01-19") - /// .build(); - /// - /// let options2 = Options::builder("New Key", ["member"]) - /// .expiration_date("2038-01-19") - /// .build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn expiration_date(mut self, expiration_date: impl Into) -> Self { - self.0.expiration = Some(Expiration::ExpirationDate(expiration_date.into())); - self - } - - /// Set the time to live in seconds. - /// - /// This will unset the expiration date. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::keys::options::Options; - /// # - /// let options = Options::builder("New Key", ["member"]) - /// .time_to_live_in_seconds(7776000) - /// .build(); - /// ``` - /// - /// ``` - /// # use deepgram::keys::options::Options; - /// # - /// let options1 = Options::builder("New Key", ["member"]) - /// .expiration_date("2038-01-19") - /// .time_to_live_in_seconds(7776000) - /// .build(); - /// - /// let options2 = Options::builder("New Key", ["member"]) - /// .time_to_live_in_seconds(7776000) - /// .build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn time_to_live_in_seconds(mut self, time_to_live_in_seconds: usize) -> Self { - self.0.expiration = Some(Expiration::TimeToLiveInSeconds(time_to_live_in_seconds)); - self - } - - /// Finish building the [`Options`] object. - pub fn build(self) -> Options { - self.0 - } -} - -impl<'a> From<&'a Options> for SerializableOptions<'a> { - fn from(options: &'a Options) -> Self { - // Destructuring it makes sure that we don't forget to use any of it - let Options { - comment, - tags, - scopes, - expiration, - } = options; - - let mut serializable_options = Self { - comment, - tags, - scopes, - expiration_date: None, - time_to_live_in_seconds: None, - }; - - match expiration { - Some(Expiration::ExpirationDate(expiration_date)) => { - serializable_options.expiration_date = Some(expiration_date); - } - Some(Expiration::TimeToLiveInSeconds(time_to_live_in_seconds)) => { - serializable_options.time_to_live_in_seconds = Some(*time_to_live_in_seconds); - } - None => {} - }; - - serializable_options - } -} diff --git a/deepgram-rust-sdk/src/keys/response.rs b/deepgram-rust-sdk/src/keys/response.rs deleted file mode 100644 index 7b3a885..0000000 --- a/deepgram-rust-sdk/src/keys/response.rs +++ /dev/null @@ -1,111 +0,0 @@ -//! Deepgram keys API response types. - -use serde::{Deserialize, Serialize}; -use uuid::Uuid; - -pub use crate::response::Message; - -/// Returned by [`Keys::list`](super::Keys::list). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#keys-get-keys -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MembersAndApiKeys { - #[allow(missing_docs)] - pub api_keys: Vec, -} - -/// Returned by [`Keys::get`](super::Keys::get). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#keys-get-key -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MemberAndApiKey { - #[allow(missing_docs)] - pub member: Member, - - #[allow(missing_docs)] - pub api_key: ApiKey, -} - -/// Details of a single member. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#keys-get-key -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Member { - #[allow(missing_docs)] - pub member_id: Uuid, - - #[allow(missing_docs)] - pub first_name: Option, - - #[allow(missing_docs)] - pub last_name: Option, - - #[allow(missing_docs)] - pub email: String, -} - -/// Details of a single API key. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#keys-get-key -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct ApiKey { - #[allow(missing_docs)] - pub api_key_id: Uuid, - - #[allow(missing_docs)] - pub comment: String, - - #[allow(missing_docs)] - pub scopes: Vec, - - #[allow(missing_docs)] - pub tags: Option>, - - #[allow(missing_docs)] - pub created: String, - - #[allow(missing_docs)] - pub expiration_date: Option, -} - -/// Returned by [`Keys::create`](super::Keys::create). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#keys-create -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct NewApiKey { - #[allow(missing_docs)] - pub api_key_id: Uuid, - - #[allow(missing_docs)] - pub key: String, - - #[allow(missing_docs)] - pub comment: String, - - #[allow(missing_docs)] - pub scopes: Vec, - - #[allow(missing_docs)] - pub tags: Option>, - - #[allow(missing_docs)] - pub created: String, - - #[allow(missing_docs)] - pub expiration_date: Option, -} diff --git a/deepgram-rust-sdk/src/lib.rs b/deepgram-rust-sdk/src/lib.rs deleted file mode 100644 index a10ad53..0000000 --- a/deepgram-rust-sdk/src/lib.rs +++ /dev/null @@ -1,136 +0,0 @@ -#![forbid(unsafe_code)] -#![warn(missing_debug_implementations, clippy::cargo)] -#![allow(clippy::multiple_crate_versions, clippy::derive_partial_eq_without_eq)] - -//! Official Rust SDK for Deepgram's automated speech recognition APIs. -//! -//! Get started transcribing with a [`Transcription`](transcription::Transcription) object. - -use std::io; - -use reqwest::{ - header::{HeaderMap, HeaderValue}, - RequestBuilder, -}; -use serde::de::DeserializeOwned; -use thiserror::Error; - -pub mod billing; -pub mod invitations; -pub mod keys; -pub mod members; -pub mod projects; -pub mod scopes; -pub mod transcription; -pub mod usage; - -mod response; - -/// A client for the Deepgram API. -/// -/// Make transcriptions requests using [`Deepgram::transcription`]. -#[derive(Debug, Clone)] -pub struct Deepgram { - api_key: String, - client: reqwest::Client, -} - -/// Errors that may arise from the [`deepgram`](crate) crate. -// TODO sub-errors for the different types? -#[derive(Debug, Error)] -pub enum DeepgramError { - /// No source was provided to the request builder. - #[error("No source was provided to the request builder.")] - NoSource, - - /// The Deepgram API returned an error. - #[error("The Deepgram API returned an error.")] - DeepgramApiError { - /// Error message from the Deepgram API. - body: String, - - /// Underlying [`reqwest::Error`] from the HTTP request. - err: reqwest::Error, - }, - - /// Something went wrong when generating the http request. - #[error("Something went wrong when generating the http request: {0}")] - HttpError(#[from] http::Error), - - /// Something went wrong when making the HTTP request. - #[error("Something went wrong when making the HTTP request: {0}")] - ReqwestError(#[from] reqwest::Error), - - /// Something went wrong during I/O. - #[error("Something went wrong during I/O: {0}")] - IoError(#[from] io::Error), - - /// Something went wrong with WS. - #[error("Something went wrong with WS: {0}")] - WsError(#[from] tungstenite::Error), - - /// Something went wrong during serialization/deserialization. - #[error("Something went wrong during serialization/deserialization: {0}")] - SerdeError(#[from] serde_json::Error), -} - -type Result = std::result::Result; - -impl Deepgram { - /// Construct a new Deepgram client. - /// - /// Create your first API key on the [Deepgram Console][console]. - /// - /// [console]: https://console.deepgram.com/ - /// - /// # Panics - /// - /// Panics under the same conditions as [`reqwest::Client::new`]. - pub fn new>(api_key: K) -> Self { - static USER_AGENT: &str = concat!( - env!("CARGO_PKG_NAME"), - "/", - env!("CARGO_PKG_VERSION"), - " rust", - ); - - let authorization_header = { - let mut header = HeaderMap::new(); - header.insert( - "Authorization", - HeaderValue::from_str(&format!("Token {}", api_key.as_ref())) - .expect("Invalid API key"), - ); - header - }; - let api_key = api_key.as_ref().to_owned(); - - Deepgram { - api_key, - client: reqwest::Client::builder() - .user_agent(USER_AGENT) - .default_headers(authorization_header) - .build() - // Even though `reqwest::Client::new` is not used here, it will always panic under the same conditions - .expect("See reqwest::Client::new docs for cause of panic"), - } - } -} - -/// Sends the request and checks the response for an error. -/// -/// If there is an error, it translates it into a [`DeepgramError::DeepgramApiError`]. -/// Otherwise, it deserializes the JSON accordingly. -async fn send_and_translate_response( - request_builder: RequestBuilder, -) -> crate::Result { - let response = request_builder.send().await?; - - match response.error_for_status_ref() { - Ok(_) => Ok(response.json().await?), - Err(err) => Err(DeepgramError::DeepgramApiError { - body: response.text().await?, - err, - }), - } -} diff --git a/deepgram-rust-sdk/src/members.rs b/deepgram-rust-sdk/src/members.rs deleted file mode 100644 index 8651da5..0000000 --- a/deepgram-rust-sdk/src/members.rs +++ /dev/null @@ -1,122 +0,0 @@ -//! Manage the members of a Deepgram Project. -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#members - -use crate::{send_and_translate_response, Deepgram}; - -pub mod response; - -/// Manage the members of a Deepgram Project. -/// -/// Constructed using [`Deepgram::members`]. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#members -#[derive(Debug, Clone)] -pub struct Members<'a>(&'a Deepgram); - -impl Deepgram { - /// Construct a new [`Members`] from a [`Deepgram`]. - pub fn members(&self) -> Members<'_> { - self.into() - } -} - -impl<'a> From<&'a Deepgram> for Members<'a> { - /// Construct a new [`Members`] from a [`Deepgram`]. - fn from(deepgram: &'a Deepgram) -> Self { - Self(deepgram) - } -} - -impl Members<'_> { - /// Get all members of the specified project. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#members-get-members - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{Deepgram, DeepgramError}; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// let members = dg_client - /// .members() - /// .list_members(&project_id) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn list_members(&self, project_id: &str) -> crate::Result { - let url = format!( - "https://api.deepgram.com/v1/projects/{}/members", - project_id, - ); - - send_and_translate_response(self.0.client.get(url)).await - } - - /// Remove the specified member from the specified project. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#members-delete - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{Deepgram, DeepgramError}; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// # let member_id = - /// # env::var("DEEPGRAM_MEMBER_ID").expect("DEEPGRAM_MEMBER_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// dg_client - /// .members() - /// .remove_member(&project_id, &member_id) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn remove_member( - &self, - project_id: &str, - member_id: &str, - ) -> crate::Result { - let url = format!( - "https://api.deepgram.com/v1/projects/{}/members/{}", - project_id, member_id, - ); - - send_and_translate_response(self.0.client.delete(url)).await - } -} diff --git a/deepgram-rust-sdk/src/members/response.rs b/deepgram-rust-sdk/src/members/response.rs deleted file mode 100644 index 578bc6d..0000000 --- a/deepgram-rust-sdk/src/members/response.rs +++ /dev/null @@ -1,42 +0,0 @@ -//! Deepgram members API response types. - -use serde::{Deserialize, Serialize}; -use uuid::Uuid; - -pub use crate::response::Message; - -/// Returned by [`Members::list_members`](super::Members::list_members). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#members-get-members -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Members { - #[allow(missing_docs)] - pub members: Vec, -} - -/// Returned by [`Members::list_members`](super::Members::list_members). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#members-get-members -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Member { - #[allow(missing_docs)] - pub member_id: Uuid, - - #[allow(missing_docs)] - pub first_name: Option, - - #[allow(missing_docs)] - pub last_name: Option, - - #[allow(missing_docs)] - pub scopes: Vec, - - #[allow(missing_docs)] - pub email: String, -} diff --git a/deepgram-rust-sdk/src/projects.rs b/deepgram-rust-sdk/src/projects.rs deleted file mode 100644 index 64a170e..0000000 --- a/deepgram-rust-sdk/src/projects.rs +++ /dev/null @@ -1,198 +0,0 @@ -//! Manage Deepgram Projects. -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#projects - -use crate::{send_and_translate_response, Deepgram}; - -pub mod options; -pub mod response; - -use options::{Options, SerializableOptions}; -use response::{Message, Project}; - -/// Manage Deepgram Projects. -/// -/// Constructed using [`Deepgram::projects`]. -/// -/// You can create new Deepgram Projects on the [Deepgram Console][console]. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [console]: https://console.deepgram.com/ -/// [api]: https://developers.deepgram.com/api-reference/#projects -#[derive(Debug, Clone)] -pub struct Projects<'a>(&'a Deepgram); - -impl Deepgram { - /// Construct a new [`Projects`] from a [`Deepgram`]. - pub fn projects(&self) -> Projects<'_> { - self.into() - } -} - -impl<'a> From<&'a Deepgram> for Projects<'a> { - /// Construct a new [`Projects`] from a [`Deepgram`]. - fn from(deepgram: &'a Deepgram) -> Self { - Self(deepgram) - } -} - -impl Projects<'_> { - /// Get all projects. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#projects-get-projects - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{projects::options::Options, Deepgram, DeepgramError}; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// let projects = dg_client - /// .projects() - /// .list() - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn list(&self) -> crate::Result { - let request = self.0.client.get("https://api.deepgram.com/v1/projects"); - - send_and_translate_response(request).await - } - - /// Get a specific project. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#projects-get-project - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{projects::options::Options, Deepgram, DeepgramError}; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// let project = dg_client - /// .projects() - /// .get(&project_id) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn get(&self, project_id: &str) -> crate::Result { - let url = format!("https://api.deepgram.com/v1/projects/{}", project_id); - - send_and_translate_response(self.0.client.get(url)).await - } - - /// Update the specified project. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#projects-update - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{projects::options::Options, Deepgram, DeepgramError}; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// let options = Options::builder() - /// .name("The Transcribinator") - /// .company("Doofenshmirtz Evil Incorporated") - /// .build(); - /// - /// dg_client - /// .projects() - /// .update(&project_id, &options) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn update(&self, project_id: &str, options: &Options) -> crate::Result { - let url = format!("https://api.deepgram.com/v1/projects/{}", project_id); - let request = self - .0 - .client - .patch(url) - .json(&SerializableOptions::from(options)); - - send_and_translate_response(request).await - } - - /// Delete the specified project. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#projects-get-delete - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{projects::options::Options, Deepgram, DeepgramError}; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// dg_client - /// .projects() - /// .delete(&project_id) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn delete(&self, project_id: &str) -> crate::Result { - let url = format!("https://api.deepgram.com/v1/projects/{}", project_id); - let request = self.0.client.delete(url); - - send_and_translate_response(request).await - } -} diff --git a/deepgram-rust-sdk/src/projects/options.rs b/deepgram-rust-sdk/src/projects/options.rs deleted file mode 100644 index 133d69a..0000000 --- a/deepgram-rust-sdk/src/projects/options.rs +++ /dev/null @@ -1,102 +0,0 @@ -//! Set options for [`Projects::update`](super::Projects::update). -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#projects-update - -use serde::Serialize; - -/// Used as a parameter for [`Projects::update`](super::Projects::update). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#projects-update -#[derive(Debug, PartialEq, Eq, Clone, Hash)] -pub struct Options { - name: Option, - company: Option, -} - -/// Builds an [`Options`] object using [the Builder pattern][builder]. -/// -/// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html -#[derive(Debug, PartialEq, Clone)] -pub struct OptionsBuilder(Options); - -#[derive(Serialize)] -pub(super) struct SerializableOptions<'a> { - #[serde(skip_serializing_if = "Option::is_none")] - pub(super) name: &'a Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub(super) company: &'a Option, -} - -impl Options { - /// Construct a new [`OptionsBuilder`]. - pub fn builder() -> OptionsBuilder { - OptionsBuilder::new() - } -} - -impl OptionsBuilder { - /// Construct a new [`OptionsBuilder`]. - pub fn new() -> Self { - Self(Options { - name: None, - company: None, - }) - } - - /// Set the project name. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::projects::options::Options; - /// # - /// let options = Options::builder() - /// .name("The Transcribinator") - /// .build(); - /// ``` - pub fn name(mut self, name: impl Into) -> Self { - self.0.name = Some(name.into()); - self - } - - /// Set the project company. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::projects::options::Options; - /// # - /// let options = Options::builder() - /// .company("Doofenshmirtz Evil Incorporated") - /// .build(); - /// ``` - pub fn company(mut self, company: impl Into) -> Self { - self.0.company = Some(company.into()); - self - } - - /// Finish building the [`Options`] object. - pub fn build(self) -> Options { - self.0 - } -} - -impl Default for OptionsBuilder { - fn default() -> Self { - Self::new() - } -} - -impl<'a> From<&'a Options> for SerializableOptions<'a> { - fn from(options: &'a Options) -> Self { - // Destructuring it makes sure that we don't forget to use any of it - let Options { name, company } = options; - - Self { name, company } - } -} diff --git a/deepgram-rust-sdk/src/projects/response.rs b/deepgram-rust-sdk/src/projects/response.rs deleted file mode 100644 index 18c9e21..0000000 --- a/deepgram-rust-sdk/src/projects/response.rs +++ /dev/null @@ -1,36 +0,0 @@ -//! Deepgram projects API response types. - -use serde::{Deserialize, Serialize}; -use uuid::Uuid; - -pub use crate::response::Message; - -/// Returned by [`Projects::list`](super::Projects::list). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#projects-get-projects -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Projects { - #[allow(missing_docs)] - pub projects: Vec, -} - -/// Returned by [`Projects::get`](super::Projects::get). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#projects-get-project -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Project { - #[allow(missing_docs)] - pub project_id: Uuid, - - #[allow(missing_docs)] - pub name: String, - - #[allow(missing_docs)] - pub company: Option, -} diff --git a/deepgram-rust-sdk/src/response.rs b/deepgram-rust-sdk/src/response.rs deleted file mode 100644 index 6f58b50..0000000 --- a/deepgram-rust-sdk/src/response.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! Response types that are shared by multiple parts of the API. - -use serde::{Deserialize, Serialize}; - -/// A success message. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/ -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Message { - #[allow(missing_docs)] - pub message: String, -} diff --git a/deepgram-rust-sdk/src/scopes.rs b/deepgram-rust-sdk/src/scopes.rs deleted file mode 100644 index aa75c99..0000000 --- a/deepgram-rust-sdk/src/scopes.rs +++ /dev/null @@ -1,140 +0,0 @@ -//! Manage the permissions of a Deepgram Project. -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#scopes - -use serde::Serialize; - -use crate::{send_and_translate_response, Deepgram}; - -pub mod response; - -use response::Message; - -/// Manage the permissions of a Deepgram Project. -/// -/// Constructed using [`Deepgram::scopes`]. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#scopes -#[derive(Debug, Clone)] -pub struct Scopes<'a>(&'a Deepgram); - -impl Deepgram { - /// Construct a new [`Scopes`] from a [`Deepgram`]. - pub fn scopes(&self) -> Scopes<'_> { - self.into() - } -} - -impl<'a> From<&'a Deepgram> for Scopes<'a> { - /// Construct a new [`Scopes`] from a [`Deepgram`]. - fn from(deepgram: &'a Deepgram) -> Self { - Self(deepgram) - } -} - -impl Scopes<'_> { - /// Get the specified project scopes assigned to the specified member. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#scopes-get - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{Deepgram, DeepgramError}; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// # let member_id = - /// # env::var("DEEPGRAM_MEMBER_ID").expect("DEEPGRAM_MEMBER_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// let scopes = dg_client - /// .scopes() - /// .get_scope(&project_id, &member_id) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn get_scope( - &self, - project_id: &str, - member_id: &str, - ) -> crate::Result { - let url = format!( - "https://api.deepgram.com/v1/projects/{}/members/{}/scopes ", - project_id, member_id - ); - - send_and_translate_response(self.0.client.get(url)).await - } - - /// Update the specified project scopes assigned to the specified member. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#scopes-update - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{Deepgram, DeepgramError}; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// # let member_id = - /// # env::var("DEEPGRAM_MEMBER_ID").expect("DEEPGRAM_MEMBER_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// dg_client - /// .scopes() - /// .update_scope(&project_id, &member_id, "member") - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn update_scope( - &self, - project_id: &str, - member_id: &str, - scope: &str, - ) -> crate::Result { - #[derive(Serialize)] - struct Scope<'a> { - scope: &'a str, - } - - let url = format!( - "https://api.deepgram.com/v1/projects/{}/members/{}/scopes", - project_id, member_id - ); - let request = self.0.client.put(url).json(&Scope { scope }); - - send_and_translate_response(request).await - } -} diff --git a/deepgram-rust-sdk/src/scopes/response.rs b/deepgram-rust-sdk/src/scopes/response.rs deleted file mode 100644 index 993874a..0000000 --- a/deepgram-rust-sdk/src/scopes/response.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! Deepgram TODO API response types. - -use serde::{Deserialize, Serialize}; - -pub use crate::response::Message; - -/// Scopes associated with the member. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#scopes-get -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Scopes { - #[allow(missing_docs)] - pub scopes: Vec, -} diff --git a/deepgram-rust-sdk/src/transcription.rs b/deepgram-rust-sdk/src/transcription.rs deleted file mode 100644 index 6a576e7..0000000 --- a/deepgram-rust-sdk/src/transcription.rs +++ /dev/null @@ -1,34 +0,0 @@ -//! Transcribe audio using Deepgram's automated speech recognition. -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#transcription - -use crate::Deepgram; - -pub mod live; -pub mod prerecorded; - -/// Transcribe audio using Deepgram's automated speech recognition. -/// -/// Constructed using [`Deepgram::transcription`]. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#transcription -#[derive(Debug, Clone)] -pub struct Transcription<'a>(&'a Deepgram); - -impl Deepgram { - /// Construct a new [`Transcription`] from a [`Deepgram`]. - pub fn transcription(&self) -> Transcription<'_> { - self.into() - } -} - -impl<'a> From<&'a Deepgram> for Transcription<'a> { - /// Construct a new [`Transcription`] from a [`Deepgram`]. - fn from(deepgram: &'a Deepgram) -> Self { - Self(deepgram) - } -} diff --git a/deepgram-rust-sdk/src/transcription/live.rs b/deepgram-rust-sdk/src/transcription/live.rs deleted file mode 100644 index eed1ea1..0000000 --- a/deepgram-rust-sdk/src/transcription/live.rs +++ /dev/null @@ -1,305 +0,0 @@ -// TODO: Remove this lint -// Currently not documented because interface of this module is still changing -#![allow(missing_docs)] - -//! Types used for live audio transcription. -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#transcription-streaming - -use std::path::Path; -use std::pin::Pin; -use std::task::{Context, Poll}; -use std::time::Duration; - -use bytes::{Bytes, BytesMut}; -use futures::channel::mpsc::{self, Receiver}; -use futures::stream::StreamExt; -use futures::{SinkExt, Stream}; -use http::Request; -use pin_project::pin_project; -use serde::{Deserialize, Serialize}; -use tokio::fs::File; -use tokio_tungstenite::tungstenite::protocol::Message; -use tokio_util::io::ReaderStream; -use tungstenite::handshake::client; -use url::Url; - -use crate::{Deepgram, DeepgramError, Result}; - -use super::Transcription; - -#[derive(Debug)] -pub struct StreamRequestBuilder<'a, S, E> -where - S: Stream>, -{ - config: &'a Deepgram, - source: Option, - encoding: Option, - sample_rate: Option, - channels: Option, -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct Word { - pub word: String, - pub start: f64, - pub end: f64, - pub confidence: f64, - pub speaker: u8, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct Alternatives { - pub transcript: String, - pub words: Vec, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct Channel { - pub alternatives: Vec, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(untagged)] -pub enum StreamResponse { - TranscriptResponse { - duration: f64, - is_final: bool, - channel: Channel, - }, - TerminalResponse { - request_id: String, - created: String, - duration: f64, - channels: u32, - }, -} - -#[pin_project] -struct FileChunker { - chunk_size: usize, - buf: BytesMut, - #[pin] - file: ReaderStream, -} - -impl Transcription<'_> { - pub fn stream_request>>( - &self, - ) -> StreamRequestBuilder { - StreamRequestBuilder { - config: self.0, - source: None, - encoding: None, - sample_rate: None, - channels: None, - } - } -} - -impl FileChunker { - fn new(file: File, chunk_size: usize) -> Self { - FileChunker { - chunk_size, - buf: BytesMut::with_capacity(2 * chunk_size), - file: ReaderStream::new(file), - } - } -} - -impl Stream for FileChunker { - type Item = Result; - - fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - let mut this = self.project(); - - while this.buf.len() < *this.chunk_size { - match Pin::new(&mut this.file).poll_next(cx) { - Poll::Pending => return Poll::Pending, - Poll::Ready(next) => match next.transpose() { - Err(e) => return Poll::Ready(Some(Err(DeepgramError::from(e)))), - Ok(None) => { - if this.buf.is_empty() { - return Poll::Ready(None); - } else { - return Poll::Ready(Some(Ok(this - .buf - .split_to(this.buf.len()) - .freeze()))); - } - } - Ok(Some(next)) => { - this.buf.extend_from_slice(&next); - } - }, - } - } - - Poll::Ready(Some(Ok(this.buf.split_to(*this.chunk_size).freeze()))) - } -} - -impl<'a, S, E> StreamRequestBuilder<'a, S, E> -where - S: Stream>, -{ - pub fn stream(mut self, stream: S) -> Self { - self.source = Some(stream); - - self - } - - pub fn encoding(mut self, encoding: String) -> Self { - self.encoding = Some(encoding); - - self - } - - pub fn sample_rate(mut self, sample_rate: u32) -> Self { - self.sample_rate = Some(sample_rate); - - self - } - - pub fn channels(mut self, channels: u16) -> Self { - self.channels = Some(channels); - - self - } -} - -impl<'a> StreamRequestBuilder<'a, Receiver>, DeepgramError> { - pub async fn file( - mut self, - filename: impl AsRef, - frame_size: usize, - frame_delay: Duration, - ) -> Result>, DeepgramError>> { - let file = File::open(filename).await?; - let mut chunker = FileChunker::new(file, frame_size); - let (mut tx, rx) = mpsc::channel(1); - let task = async move { - while let Some(frame) = chunker.next().await { - tokio::time::sleep(frame_delay).await; - // This unwrap() is safe because application logic dictates that the Receiver won't - // be dropped before the Sender. - tx.send(frame).await.unwrap(); - } - }; - tokio::spawn(task); - - self.source = Some(rx); - Ok(self) - } -} - -impl StreamRequestBuilder<'_, S, E> -where - S: Stream> + Send + Unpin + 'static, - E: Send + std::fmt::Debug, -{ - pub async fn start(self) -> Result>> { - let StreamRequestBuilder { - config, - source, - encoding, - sample_rate, - channels, - } = self; - let mut source = source - .ok_or(DeepgramError::NoSource)? - .map(|res| res.map(|bytes| Message::binary(Vec::from(bytes.as_ref())))); - - // This unwrap is safe because we're parsing a static. - let mut base = Url::parse("wss://api.deepgram.com/v1/listen").unwrap(); - { - let mut pairs = base.query_pairs_mut(); - if let Some(encoding) = encoding { - pairs.append_pair("encoding", &encoding); - } - if let Some(sample_rate) = sample_rate { - pairs.append_pair("sample_rate", &sample_rate.to_string()); - } - if let Some(channels) = channels { - pairs.append_pair("channels", &channels.to_string()); - } - pairs.append_pair("model", "nova-2-general"); - pairs.append_pair("language", "en"); - // pairs.append_pair("version", "beta"); - pairs.append_pair("diarize", "true"); - pairs.append_pair("interim_results", "true"); - pairs.append_pair("filler_words", "true"); - pairs.append_pair("utterance_end_ms", "1000"); - pairs.append_pair("endpointing", "500"); - pairs.append_pair("keywords", "ChatGPT:1.0"); - pairs.append_pair("keywords", "GPT:1.0"); - - // - } - - dbg!(&base); - - let request = Request::builder() - .method("GET") - .uri(base.to_string()) - .header("authorization", format!("token {}", config.api_key)) - .header("sec-websocket-key", client::generate_key()) - .header("host", "api.deepgram.com") - .header("connection", "upgrade") - .header("upgrade", "websocket") - .header("sec-websocket-version", "13") - .body(())?; - let (ws_stream, _) = tokio_tungstenite::connect_async(request).await?; - let (mut write, mut read) = ws_stream.split(); - let (mut tx, rx) = mpsc::channel::>(1); - - let send_task = async move { - loop { - match source.next().await { - None => break, - Some(Ok(frame)) => { - // This unwrap is not safe. - write.send(frame).await.unwrap(); - } - Some(e) => { - let _ = dbg!(e); - break; - } - } - } - - // This unwrap is not safe. - write.send(Message::binary([])).await.unwrap(); - }; - - let recv_task = async move { - loop { - match read.next().await { - None => break, - Some(Ok(msg)) => { - if let Message::Text(txt) = msg { - let resp = serde_json::from_str(&txt).map_err(DeepgramError::from); - tx.send(resp) - .await - // This unwrap is probably not safe. - .unwrap(); - } - } - Some(e) => { - let _ = dbg!(e); - break; - } - } - } - }; - - tokio::spawn(async move { - tokio::join!(send_task, recv_task); - }); - - Ok(rx) - } -} diff --git a/deepgram-rust-sdk/src/transcription/prerecorded.rs b/deepgram-rust-sdk/src/transcription/prerecorded.rs deleted file mode 100644 index 2371361..0000000 --- a/deepgram-rust-sdk/src/transcription/prerecorded.rs +++ /dev/null @@ -1,270 +0,0 @@ -//! Types used for pre-recorded audio transcription. -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#transcription-prerecorded - -use reqwest::RequestBuilder; - -use super::Transcription; -use crate::send_and_translate_response; - -pub mod audio_source; -pub mod options; -pub mod response; - -use audio_source::AudioSource; -use options::{Options, SerializableOptions}; -use response::{CallbackResponse, Response}; - -static DEEPGRAM_API_URL_LISTEN: &str = "https://api.deepgram.com/v1/listen"; - -impl Transcription<'_> { - /// Sends a request to Deepgram to transcribe pre-recorded audio. - /// If you wish to use the Callback feature, you should use [`Transcription::prerecorded_callback`] instead. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#transcription-prerecorded - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{ - /// # transcription::prerecorded::{ - /// # audio_source::AudioSource, - /// # options::{Language, Options}, - /// # }, - /// # Deepgram, DeepgramError, - /// # }; - /// # - /// # static AUDIO_URL: &str = "https://static.deepgram.com/examples/Bueller-Life-moves-pretty-fast.wav"; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// let source = AudioSource::from_url(AUDIO_URL); - /// - /// let options = Options::builder() - /// .punctuate(true) - /// .language(Language::en_US) - /// .build(); - /// - /// let response = dg_client - /// .transcription() - /// .prerecorded(source, &options) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn prerecorded( - &self, - source: AudioSource, - options: &Options, - ) -> crate::Result { - let request_builder = self.make_prerecorded_request_builder(source, options); - - send_and_translate_response(request_builder).await - } - - /// Sends a request to Deepgram to transcribe pre-recorded audio using the Callback feature. - /// Otherwise behaves similarly to [`Transcription::prerecorded`]. - /// - /// See the [Deepgram Callback feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/callback/ - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{ - /// # transcription::prerecorded::{ - /// # audio_source::AudioSource, - /// # options::{Language, Options}, - /// # }, - /// # Deepgram, DeepgramError, - /// # }; - /// # - /// # static AUDIO_URL: &str = "https://static.deepgram.com/examples/Bueller-Life-moves-pretty-fast.wav"; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// let source = AudioSource::from_url(AUDIO_URL); - /// - /// let options = Options::builder() - /// .punctuate(true) - /// .language(Language::en_US) - /// .build(); - /// - /// # let callback_url = - /// # env::var("DEEPGRAM_CALLBACK_URL").expect("DEEPGRAM_CALLBACK_URL environmental variable"); - /// # - /// let response = dg_client - /// .transcription() - /// .prerecorded_callback(source, &options, &callback_url) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn prerecorded_callback( - &self, - source: AudioSource, - options: &Options, - callback: &str, - ) -> crate::Result { - let request_builder = - self.make_prerecorded_callback_request_builder(source, options, callback); - - send_and_translate_response(request_builder).await - } - - /// Makes a [`reqwest::RequestBuilder`] without actually sending the request. - /// This allows you to modify the request before it is sent. - /// - /// Avoid using this where possible. - /// By customizing the request, there is less of a guarantee that it will conform to the Deepgram API. - /// Prefer using [`Transcription::prerecorded`]. - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{ - /// # transcription::prerecorded::{ - /// # audio_source::AudioSource, - /// # options::{Language, Options}, - /// # response::Response, - /// # }, - /// # Deepgram, DeepgramError, - /// # }; - /// # - /// # static AUDIO_URL: &str = "https://static.deepgram.com/examples/Bueller-Life-moves-pretty-fast.wav"; - /// # - /// # #[tokio::main] - /// # async fn main() -> reqwest::Result<()> { - /// # - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let dg_client = Deepgram::new(&deepgram_api_key); - /// # - /// # let source = AudioSource::from_url(AUDIO_URL); - /// # - /// # let options = Options::builder() - /// # .punctuate(true) - /// # .language(Language::en_US) - /// # .build(); - /// # - /// let request_builder = dg_client - /// .transcription() - /// .make_prerecorded_request_builder(source, &options); - /// - /// // Customize the RequestBuilder here - /// let customized_request_builder = request_builder - /// .query(&[("custom_query_key", "custom_query_value")]) - /// .header("custom_header_key", "custom_header_value"); - /// - /// // It is necessary to annotate the type of response here - /// // That way it knows what type to deserialize the JSON into - /// let response: Response = customized_request_builder.send().await?.json().await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub fn make_prerecorded_request_builder( - &self, - source: AudioSource, - options: &Options, - ) -> RequestBuilder { - let request_builder = self - .0 - .client - .post(DEEPGRAM_API_URL_LISTEN) - .query(&SerializableOptions(options)); - - source.fill_body(request_builder) - } - - /// Similar to [`Transcription::make_prerecorded_request_builder`], - /// but for the purposes of a [callback request][callback]. - /// - /// You should avoid using this where possible too, preferring [`Transcription::prerecorded_callback`]. - /// - /// [callback]: https://developers.deepgram.com/documentation/features/callback/ - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{ - /// # transcription::prerecorded::{ - /// # audio_source::AudioSource, - /// # options::{Language, Options}, - /// # response::CallbackResponse, - /// # }, - /// # Deepgram, DeepgramError, - /// # }; - /// # - /// # static AUDIO_URL: &str = "https://static.deepgram.com/examples/Bueller-Life-moves-pretty-fast.wav"; - /// # - /// # #[tokio::main] - /// # async fn main() -> reqwest::Result<()> { - /// # - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let dg_client = Deepgram::new(&deepgram_api_key); - /// # - /// # let source = AudioSource::from_url(AUDIO_URL); - /// # - /// # let options = Options::builder() - /// # .punctuate(true) - /// # .language(Language::en_US) - /// # .build(); - /// # - /// # let callback_url = - /// # env::var("DEEPGRAM_CALLBACK_URL").expect("DEEPGRAM_CALLBACK_URL environmental variable"); - /// # - /// let request_builder = dg_client - /// .transcription() - /// .make_prerecorded_callback_request_builder(source, &options, &callback_url); - /// - /// // Customize the RequestBuilder here - /// let customized_request_builder = request_builder - /// .query(&[("custom_query_key", "custom_query_value")]) - /// .header("custom_header_key", "custom_header_value"); - /// - /// // It is necessary to annotate the type of response here - /// // That way it knows what type to deserialize the JSON into - /// let response: CallbackResponse = customized_request_builder.send().await?.json().await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub fn make_prerecorded_callback_request_builder( - &self, - source: AudioSource, - options: &Options, - callback: &str, - ) -> RequestBuilder { - self.make_prerecorded_request_builder(source, options) - .query(&[("callback", callback)]) - } -} diff --git a/deepgram-rust-sdk/src/transcription/prerecorded/audio_source.rs b/deepgram-rust-sdk/src/transcription/prerecorded/audio_source.rs deleted file mode 100644 index f42c375..0000000 --- a/deepgram-rust-sdk/src/transcription/prerecorded/audio_source.rs +++ /dev/null @@ -1,79 +0,0 @@ -//! Sources of audio that can be transcribed. -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#transcription-prerecorded - -use reqwest::{header::CONTENT_TYPE, RequestBuilder}; -use serde::Serialize; - -/// Used as a parameter for [`Transcription::prerecorded`](crate::transcription::Transcription::prerecorded) and similar functions. -#[derive(Debug)] -pub struct AudioSource(InternalAudioSource); - -#[derive(Debug)] -enum InternalAudioSource { - Url(String), - Buffer { - buffer: reqwest::Body, - mime_type: Option, - }, -} - -impl AudioSource { - /// Constructs an [`AudioSource`] that will instruct Deepgram to download the audio from the specified URL. - pub fn from_url(url: impl Into) -> Self { - Self(InternalAudioSource::Url(url.into())) - } - - /// Constructs an [`AudioSource`] that will upload the raw binary audio data to Deepgram as part of the request. - /// - /// The buffer can be any type that implements [`Into`], such as a [`tokio::fs::File`]. - /// See [trait implementations for `reqwest::Body`](reqwest::Body#trait-implementations) - /// for a list of types that already implement it. - /// - /// Use [`AudioSource::from_buffer_with_mime_type`] if you want to specify a [MIME type][mime]. - /// - /// [mime]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#audio_and_video_types - pub fn from_buffer(buffer: impl Into) -> Self { - Self(InternalAudioSource::Buffer { - buffer: buffer.into(), - mime_type: None, - }) - } - - /// Same as [`AudioSource::from_buffer`], but allows you to specify a [MIME type][mime]. - /// - /// [mime]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#audio_and_video_types - pub fn from_buffer_with_mime_type( - buffer: impl Into, - mime_type: impl Into, - ) -> Self { - Self(InternalAudioSource::Buffer { - buffer: buffer.into(), - mime_type: Some(mime_type.into()), - }) - } - - pub(super) fn fill_body(self, request_builder: RequestBuilder) -> RequestBuilder { - match self.0 { - InternalAudioSource::Url(url) => { - #[derive(Serialize)] - struct UrlSource { - url: String, - } - - request_builder.json(&UrlSource { url }) - } - InternalAudioSource::Buffer { buffer, mime_type } => { - let request_builder = request_builder.body(buffer); - - if let Some(mime_type) = mime_type { - request_builder.header(CONTENT_TYPE, mime_type) - } else { - request_builder - } - } - } - } -} diff --git a/deepgram-rust-sdk/src/transcription/prerecorded/options.rs b/deepgram-rust-sdk/src/transcription/prerecorded/options.rs deleted file mode 100644 index 6a795db..0000000 --- a/deepgram-rust-sdk/src/transcription/prerecorded/options.rs +++ /dev/null @@ -1,1766 +0,0 @@ -//! Set various Deepgram features to control how the audio is transcribed. -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/documentation/features/ - -use serde::{ser::SerializeSeq, Serialize}; - -/// Used as a parameter for [`Transcription::prerecorded`](crate::transcription::Transcription::prerecorded) and similar functions. -#[derive(Debug, PartialEq, Clone)] -pub struct Options { - tier: Option, - model: Option, - version: Option, - language: Option, - punctuate: Option, - profanity_filter: Option, - redact: Vec, - diarize: Option, - ner: Option, - multichannel: Option, - alternatives: Option, - numerals: Option, - search: Vec, - replace: Vec, - keywords: Vec, - keyword_boost_legacy: bool, - utterances: Option, - tags: Vec, - detect_language: Option, -} - -/// Used as a parameter for [`OptionsBuilder::tier`]. -/// -/// See the [Deepgram Tier feature docs][docs] for more info. -/// -/// [docs]: https://developers.deepgram.com/documentation/features/tier/ -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] -#[non_exhaustive] -pub enum Tier { - #[allow(missing_docs)] - Enhanced, - - #[allow(missing_docs)] - Base, -} - -/// Used as a parameter for [`OptionsBuilder::model`] and [`OptionsBuilder::multichannel_with_models`]. -/// -/// See the [Deepgram Model feature docs][docs] for more info. -/// -/// [docs]: https://developers.deepgram.com/documentation/features/model/ -#[derive(Debug, PartialEq, Eq, Clone, Hash)] -#[non_exhaustive] -pub enum Model { - #[allow(missing_docs)] - General, - - #[allow(missing_docs)] - Meeting, - - #[allow(missing_docs)] - Phonecall, - - #[allow(missing_docs)] - Voicemail, - - #[allow(missing_docs)] - Finance, - - #[allow(missing_docs)] - Conversationalai, - - #[allow(missing_docs)] - Video, - - #[allow(missing_docs)] - CustomId(String), -} - -/// Used as a parameter for [`OptionsBuilder::language`]. -/// -/// See the [Deepgram Language feature docs][docs] for more info. -/// -/// [docs]: https://developers.deepgram.com/documentation/features/language/ -#[allow(non_camel_case_types)] // Variants should look like their BCP-47 tag -#[derive(Debug, PartialEq, Eq, Clone, Hash)] -#[non_exhaustive] -pub enum Language { - #[allow(missing_docs)] - zh, - - #[allow(missing_docs)] - zh_CN, - - #[allow(missing_docs)] - zh_TW, - - #[allow(missing_docs)] - nl, - - #[allow(missing_docs)] - en, - - #[allow(missing_docs)] - en_AU, - - #[allow(missing_docs)] - en_GB, - - #[allow(missing_docs)] - en_IN, - - #[allow(missing_docs)] - en_NZ, - - #[allow(missing_docs)] - en_US, - - #[allow(missing_docs)] - fr, - - #[allow(missing_docs)] - fr_CA, - - #[allow(missing_docs)] - de, - - #[allow(missing_docs)] - hi, - - #[allow(missing_docs)] - hi_Latn, - - #[allow(missing_docs)] - id, - - #[allow(missing_docs)] - it, - - #[allow(missing_docs)] - ja, - - #[allow(missing_docs)] - ko, - - #[allow(missing_docs)] - pt, - - #[allow(missing_docs)] - pt_BR, - - #[allow(missing_docs)] - ru, - - #[allow(missing_docs)] - es, - - #[allow(missing_docs)] - es_419, - - #[allow(missing_docs)] - sv, - - #[allow(missing_docs)] - tr, - - #[allow(missing_docs)] - uk, - - /// Avoid using the `Other` variant where possible. - /// It exists so that you can use new languages that Deepgram supports without being forced to update your version of the SDK. - /// See the [Deepgram Language feature docs][docs] for the most up-to-date list of supported languages. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/language/ - Other(String), -} - -/// Used as a parameter for [`OptionsBuilder::redact`]. -/// -/// See the [Deepgram Redaction feature docs][docs] for more info. -/// -/// [docs]: https://developers.deepgram.com/documentation/features/redact/ -#[derive(Debug, PartialEq, Eq, Clone, Hash)] -#[non_exhaustive] -pub enum Redact { - #[allow(missing_docs)] - Pci, - - #[allow(missing_docs)] - Numbers, - - #[allow(missing_docs)] - Ssn, - - /// Avoid using the `Other` variant where possible. - /// It exists so that you can use new redactable items that Deepgram supports without being forced to update your version of the SDK. - /// See the [Deepgram Redact feature docs][docs] for the most up-to-date list of redactable items. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/redact/ - Other(String), -} - -/// Used as a parameter for [`OptionsBuilder::replace`]. -/// -/// See the [Deepgram Find and Replace feature docs][docs] for more info. -/// -/// [docs]: https://developers.deepgram.com/documentation/features/replace/ -#[derive(Debug, PartialEq, Eq, Clone, Hash)] -pub struct Replace { - /// The term or phrase to find. - pub find: String, - - /// The term or phrase to replace [`find`](Replace::find) with. - /// If set to [`None`], [`find`](Replace::find) will be removed from the transcript without being replaced by anything. - pub replace: Option, -} - -/// Used as a parameter for [`OptionsBuilder::keywords_with_intensifiers`]. -/// -/// See the [Deepgram Keywords feature docs][docs] for more info. -/// -/// [docs]: https://developers.deepgram.com/documentation/features/keywords/ -#[derive(Debug, PartialEq, Clone)] -pub struct Keyword { - /// The keyword to boost. - pub keyword: String, - - /// Optionally specify how much to boost it. - pub intensifier: Option, -} - -#[derive(Debug, PartialEq, Clone, Copy)] -enum Utterances { - Disabled, - Enabled { utt_split: Option }, -} - -#[derive(Debug, PartialEq, Eq, Clone, Hash)] -enum Multichannel { - Disabled, - Enabled { models: Option> }, -} - -/// Builds an [`Options`] object using [the Builder pattern][builder]. -/// -/// Use it to set of Deepgram's features, excluding the Callback feature. -/// The Callback feature can be set when making the request by calling [`Transcription::prerecorded_callback`](crate::transcription::Transcription::prerecorded_callback). -/// -/// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html -#[derive(Debug, PartialEq, Clone)] -pub struct OptionsBuilder(Options); - -#[derive(Debug, PartialEq, Clone)] -pub(super) struct SerializableOptions<'a>(pub(super) &'a Options); - -impl Options { - /// Construct a new [`OptionsBuilder`]. - pub fn builder() -> OptionsBuilder { - OptionsBuilder::new() - } -} - -impl OptionsBuilder { - /// Construct a new [`OptionsBuilder`]. - pub fn new() -> Self { - Self(Options { - tier: None, - model: None, - version: None, - language: None, - punctuate: None, - profanity_filter: None, - redact: Vec::new(), - diarize: None, - ner: None, - multichannel: None, - alternatives: None, - numerals: None, - search: Vec::new(), - replace: Vec::new(), - keywords: Vec::new(), - keyword_boost_legacy: false, - utterances: None, - tags: Vec::new(), - detect_language: None, - }) - } - - /// Set the Tier feature. - /// - /// Not all tiers are supported for all models and languages. - /// For a list of models/languages and their supported models, - /// see the [Deepgram Language feature][language] docs. - /// - /// See the [Deepgram Tier feature docs][docs] for more info. - /// - /// [language]: https://developers.deepgram.com/documentation/features/language/ - /// [docs]: https://developers.deepgram.com/documentation/features/tier/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::{Options, Tier}; - /// # - /// let options = Options::builder() - /// .tier(Tier::Enhanced) - /// .build(); - /// ``` - pub fn tier(mut self, tier: Tier) -> Self { - self.0.tier = Some(tier); - self - } - - /// Set the Model feature. - /// - /// Not all models are supported for all languages. For a list of languages and their supported models, see - /// the [Deepgram Language feature][language] docs. - /// - /// If you previously set some models using [`OptionsBuilder::multichannel_with_models`], - /// calling this will overwrite the models you set there, but won't disable the Multichannel feature. - /// - /// See the [Deepgram Model feature docs][docs] for more info. - /// - /// [language]: https://developers.deepgram.com/documentation/features/language/ - /// [docs]: https://developers.deepgram.com/documentation/features/model/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::{Model, Options}; - /// # - /// let options = Options::builder() - /// .model(Model::General) - /// .build(); - /// ``` - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::{Model, Options}; - /// # - /// let options1 = Options::builder() - /// .multichannel_with_models([Model::Meeting, Model::Phonecall]) - /// .model(Model::General) - /// .build(); - /// - /// let options2 = Options::builder() - /// .multichannel(true) - /// .model(Model::General) - /// .build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn model(mut self, model: Model) -> Self { - self.0.model = Some(model); - - if let Some(Multichannel::Enabled { models }) = &mut self.0.multichannel { - *models = None; - } - - self - } - - /// Set the Version feature. - /// - /// See the [Deepgram Version feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/version/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options = Options::builder() - /// .version("12345678-1234-1234-1234-1234567890ab") - /// .build(); - /// ``` - pub fn version(mut self, version: &str) -> Self { - self.0.version = Some(version.into()); - self - } - - /// Set the Language feature. - /// - /// See the [Deepgram Language feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/language/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::{Language, Options}; - /// # - /// let options = Options::builder() - /// .language(Language::en_US) - /// .build(); - /// ``` - pub fn language(mut self, language: Language) -> Self { - self.0.language = Some(language); - self - } - - /// Set the Punctuation feature. - /// - /// See the [Deepgram Punctuation feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/punctuate/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options = Options::builder() - /// .punctuate(true) - /// .build(); - /// ``` - pub fn punctuate(mut self, punctuate: bool) -> Self { - self.0.punctuate = Some(punctuate); - self - } - - /// Set the Profanity Filter feature. - /// - /// Not necessarily available for all languages. - /// - /// See the [Deepgram Profanity Filter feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/profanity-filter/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options = Options::builder() - /// .profanity_filter(true) - /// .build(); - /// ``` - pub fn profanity_filter(mut self, profanity_filter: bool) -> Self { - self.0.profanity_filter = Some(profanity_filter); - self - } - - /// Set the Redaction feature. - /// - /// Not necessarily available for all languages. - /// - /// Calling this when already set will append to the existing redact items, not overwrite them. - /// - /// See the [Deepgram Redaction feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/redact/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::{Options, Redact}; - /// # - /// let options = Options::builder() - /// .redact([Redact::Pci, Redact::Ssn]) - /// .build(); - /// ``` - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::{Options, Redact}; - /// # - /// let options1 = Options::builder() - /// .redact([Redact::Pci]) - /// .redact([Redact::Ssn]) - /// .build(); - /// - /// let options2 = Options::builder() - /// .redact([Redact::Pci, Redact::Ssn]) - /// .build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn redact(mut self, redact: impl IntoIterator) -> Self { - self.0.redact.extend(redact); - self - } - - /// Set the Diarization feature. - /// - /// See the [Deepgram Diarization feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/diarize/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options = Options::builder() - /// .diarize(true) - /// .build(); - /// ``` - pub fn diarize(mut self, diarize: bool) -> Self { - self.0.diarize = Some(diarize); - self - } - - /// Set the Named-Entity Recognition feature. - /// - /// Not necessarily available for all languages. - /// - /// See the [Deepgram Named-Entity Recognition feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/named-entity-recognition/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options = Options::builder() - /// .ner(true) - /// .build(); - /// ``` - pub fn ner(mut self, ner: bool) -> Self { - self.0.ner = Some(ner); - self - } - - /// Set the Multichannel feature. - /// - /// To specify which model should process each channel, use [`OptionsBuilder::multichannel_with_models`] instead. - /// If [`OptionsBuilder::multichannel_with_models`] is currently set, calling [`OptionsBuilder::multichannel`] - /// will reset the model to the last call to [`OptionsBuilder::model`]. - /// - /// See the [Deepgram Multichannel feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/multichannel/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options = Options::builder() - /// .multichannel(true) - /// .build(); - /// ``` - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::{Model, Options}; - /// # - /// let options1 = Options::builder() - /// .model(Model::General) - /// .multichannel_with_models([Model::Meeting, Model::Phonecall]) - /// .multichannel(true) - /// .build(); - /// - /// let options2 = Options::builder() - /// .model(Model::General) - /// .multichannel(true) - /// .build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn multichannel(mut self, multichannel: bool) -> Self { - self.0.multichannel = Some(if multichannel { - Multichannel::Enabled { models: None } - } else { - Multichannel::Disabled - }); - - self - } - - /// Set the Multichannel feature to true, specifying which model should process each channel. - /// - /// If you previously set a model using [`OptionsBuilder::model`], - /// calling this will overshadow the model you set there, but won't erase it. - /// It can be recovered by calling [`OptionsBuilder::multichannel`]. - /// - /// Calling this when multichannel models are already set will append to the existing models, not overwrite them. - /// - /// See the [Deepgram Multichannel feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/multichannel/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::{Model, Options}; - /// # - /// let options = Options::builder() - /// .multichannel_with_models([Model::Meeting, Model::Phonecall]) - /// .build(); - /// ``` - /// - /// ``` - /// # use std::env; - /// # - /// # use deepgram::{ - /// # transcription::prerecorded::{ - /// # audio_source::AudioSource, - /// # options::{Model, Options}, - /// # }, - /// # Deepgram, - /// # }; - /// # - /// # - /// # static AUDIO_URL: &str = "https://static.deepgram.com/examples/Bueller-Life-moves-pretty-fast.wav"; - /// # - /// # fn main() -> Result<(), reqwest::Error> { - /// # let deepgram_api_key = env::var("DEEPGRAM_API_KEY").unwrap_or_default(); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// let dg_transcription = dg_client.transcription(); - /// - /// let options1 = Options::builder() - /// .model(Model::General) - /// .multichannel_with_models([Model::Meeting, Model::Phonecall]) - /// .build(); - /// - /// let options2 = Options::builder() - /// .multichannel_with_models([Model::Meeting, Model::Phonecall]) - /// .build(); - /// - /// let request1 = dg_transcription - /// .make_prerecorded_request_builder(AudioSource::from_url(AUDIO_URL), &options1) - /// .build()?; - /// - /// let request2 = dg_transcription - /// .make_prerecorded_request_builder(AudioSource::from_url(AUDIO_URL), &options2) - /// .build()?; - /// - /// // Both make the same request to Deepgram with the same features - /// assert_eq!(request1.url(), request2.url()); - /// - /// // However, they technically aren't "equal" - /// // This is because `options1` still remembers the model you set previously - /// assert_ne!(options1, options2); - /// # - /// # Ok(()) - /// # } - /// ``` - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::{Model, Options}; - /// # - /// let options1 = Options::builder() - /// .model(Model::General) - /// .multichannel_with_models([Model::Meeting, Model::Phonecall]) - /// .multichannel(true) - /// .build(); - /// - /// let options2 = Options::builder() - /// .model(Model::General) - /// .multichannel(true) - /// .build(); - /// - /// assert_eq!(options1, options2); - /// ``` - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::{Model, Options}; - /// # - /// let options1 = Options::builder() - /// .multichannel_with_models([Model::Meeting]) - /// .multichannel_with_models([Model::Phonecall]) - /// .build(); - /// - /// let options2 = Options::builder() - /// .multichannel_with_models([Model::Meeting, Model::Phonecall]) - /// .build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn multichannel_with_models(mut self, models: impl IntoIterator) -> Self { - if let Some(Multichannel::Enabled { - models: Some(old_models), - }) = &mut self.0.multichannel - { - // Multichannel with models already enabled - // Don't overwrite existing models - old_models.extend(models); - } else { - // Multichannel with models already enabled - self.0.multichannel = Some(Multichannel::Enabled { - models: Some(models.into_iter().collect()), - }); - } - - self - } - - /// Set the Alternatives feature. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#alternatives-pr - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options = Options::builder() - /// .alternatives(3) - /// .build(); - /// ``` - pub fn alternatives(mut self, alternatives: usize) -> Self { - self.0.alternatives = Some(alternatives); - self - } - - /// Set the Numerals feature. - /// - /// Not necessarily available for all languages. - /// - /// See the [Deepgram Numerals feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/numerals/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options = Options::builder() - /// .numerals(true) - /// .build(); - /// ``` - pub fn numerals(mut self, numerals: bool) -> Self { - self.0.numerals = Some(numerals); - self - } - - /// Set the Search feature. - /// - /// Calling this when already set will append to the existing items, not overwrite them. - /// - /// See the [Deepgram Search feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/search/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options = Options::builder() - /// .search(["hello", "world"]) - /// .build(); - /// ``` - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options1 = Options::builder() - /// .search(["hello"]) - /// .search(["world"]) - /// .build(); - /// - /// let options2 = Options::builder() - /// .search(["hello", "world"]) - /// .build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn search<'a>(mut self, search: impl IntoIterator) -> Self { - self.0.search.extend(search.into_iter().map(String::from)); - self - } - - /// Set the Find and Replace feature. - /// - /// Calling this when already set will append to the existing replacements, not overwrite them. - /// - /// See the [Deepgram Find and Replace feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/replace/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::{Options, Replace}; - /// # - /// let options = Options::builder() - /// .replace([ - /// Replace { - /// find: String::from("Aaron"), - /// replace: Some(String::from("Erin")), - /// }, - /// Replace { - /// find: String::from("Voldemort"), - /// replace: None, - /// }, - /// ]) - /// .build(); - /// ``` - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::{Options, Replace}; - /// # - /// let options1 = Options::builder() - /// .replace([Replace { - /// find: String::from("Aaron"), - /// replace: Some(String::from("Erin")), - /// }]) - /// .replace([Replace { - /// find: String::from("Voldemort"), - /// replace: None, - /// }]) - /// .build(); - /// - /// let options2 = Options::builder() - /// .replace([ - /// Replace { - /// find: String::from("Aaron"), - /// replace: Some(String::from("Erin")), - /// }, - /// Replace { - /// find: String::from("Voldemort"), - /// replace: None, - /// }, - /// ]) - /// .build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn replace(mut self, replace: impl IntoIterator) -> Self { - self.0.replace.extend(replace); - self - } - - /// Set the Keywords feature. - /// - /// To specify intensifiers, use [`OptionsBuilder::keywords_with_intensifiers`] instead. - /// - /// Calling this when already set will append to the existing keywords, not overwrite them. - /// This includes keywords set by [`OptionsBuilder::keywords_with_intensifiers`]. - /// - /// See the [Deepgram Keywords feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/keywords/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options = Options::builder() - /// .keywords(["hello", "world"]) - /// .build(); - /// ``` - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options1 = Options::builder() - /// .keywords(["hello"]) - /// .keywords(["world"]) - /// .build(); - /// - /// let options2 = Options::builder() - /// .keywords(["hello", "world"]) - /// .build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn keywords<'a>(mut self, keywords: impl IntoIterator) -> Self { - let iter = keywords.into_iter().map(|keyword| Keyword { - keyword: keyword.into(), - intensifier: None, - }); - - self.0.keywords.extend(iter); - self - } - - /// Set the Keywords feature, specifying intensifiers. - /// - /// If you do not need to specify intensifiers, you can use [`OptionsBuilder::keywords`] instead. - /// - /// Calling this when already set will append to the existing keywords, not overwrite them. - /// - /// See the [Deepgram Keywords feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/keywords/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::{Keyword, Options}; - /// # - /// let options = Options::builder() - /// .keywords_with_intensifiers([ - /// Keyword { - /// keyword: String::from("hello"), - /// intensifier: Some(-1.5), - /// }, - /// Keyword { - /// keyword: String::from("world"), - /// intensifier: None, - /// }, - /// ]) - /// .build(); - /// ``` - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::{Keyword, Options}; - /// # - /// let options1 = Options::builder() - /// .keywords_with_intensifiers([ - /// Keyword { - /// keyword: String::from("hello"), - /// intensifier: Some(-1.5), - /// }, - /// ]) - /// .keywords_with_intensifiers([ - /// Keyword { - /// keyword: String::from("world"), - /// intensifier: None, - /// }, - /// ]) - /// .build(); - /// - /// let options2 = Options::builder() - /// .keywords_with_intensifiers([ - /// Keyword { - /// keyword: String::from("hello"), - /// intensifier: Some(-1.5), - /// }, - /// Keyword { - /// keyword: String::from("world"), - /// intensifier: None, - /// }, - /// ]) - /// .build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn keywords_with_intensifiers( - mut self, - keywords: impl IntoIterator, - ) -> Self { - self.0.keywords.extend(keywords); - self - } - - /// Use legacy keyword boosting. - /// - /// See the [Deepgram Keywords feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/keywords/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options = Options::builder() - /// .keywords(["hello", "world"]) - /// .keyword_boost_legacy() - /// .build(); - /// ``` - pub fn keyword_boost_legacy(mut self) -> Self { - self.0.keyword_boost_legacy = true; - self - } - - /// Set the Utterances feature. - /// - /// To set the Utterance Split feature, use [`OptionsBuilder::utterances_with_utt_split`] instead. - /// - /// See the [Deepgram Utterances feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/utterances/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options = Options::builder() - /// .utterances(true) - /// .build(); - /// ``` - pub fn utterances(mut self, utterances: bool) -> Self { - self.0.utterances = Some(if utterances { - Utterances::Enabled { utt_split: None } - } else { - Utterances::Disabled - }); - - self - } - - /// Set the Utterances feature and the Utterance Split feature. - /// - /// If you do not want to set the Utterance Split feature, use [`OptionsBuilder::utterances`] instead. - /// - /// See the [Deepgram Utterances feature docs][utterances-docs] - /// and the [Deepgram Utterance Split feature docs][utt_split-docs] for more info. - /// - /// [utterances-docs]: https://developers.deepgram.com/documentation/features/utterances/ - /// [utt_split-docs]: https://developers.deepgram.com/documentation/features/utterance-split/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options = Options::builder() - /// .utterances_with_utt_split(0.9) - /// .build(); - /// ``` - pub fn utterances_with_utt_split(mut self, utt_split: f64) -> Self { - self.0.utterances = Some(Utterances::Enabled { - utt_split: Some(utt_split), - }); - self - } - - /// Set the Tag feature. - /// - /// Calling this when already set will append to the existing tags, not overwrite them. - /// - /// See the [Deepgram Tag feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/documentation/features/tag/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options = Options::builder() - /// .tag(["Tag 1", "Tag 2"]) - /// .build(); - /// ``` - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options1 = Options::builder() - /// .tag(["Tag 1"]) - /// .tag(["Tag 2"]) - /// .build(); - /// - /// let options2 = Options::builder() - /// .tag(["Tag 1", "Tag 2"]) - /// .build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn tag<'a>(mut self, tag: impl IntoIterator) -> Self { - self.0.tags.extend(tag.into_iter().map(String::from)); - self - } - - /// Set the Language Detection feature. - /// - /// See the [Deepgram Language Detection feature docs][docs] for more info. - /// - /// [docs]: https://developers.deepgram.com/docs/language-detection/ - /// - /// # Examples - /// - /// ``` - /// # use deepgram::transcription::prerecorded::options::Options; - /// # - /// let options = Options::builder() - /// .detect_language(true) - /// .build(); - /// ``` - pub fn detect_language(mut self, detect_language: bool) -> Self { - self.0.detect_language = Some(detect_language); - - self - } - /// Finish building the [`Options`] object. - pub fn build(self) -> Options { - self.0 - } -} - -impl Default for OptionsBuilder { - fn default() -> Self { - Self::new() - } -} - -impl Serialize for SerializableOptions<'_> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut seq = serializer.serialize_seq(None)?; - - // Destructuring it makes sure that we don't forget to use any of it - let Options { - tier, - model, - version, - language, - punctuate, - profanity_filter, - redact, - diarize, - ner, - multichannel, - alternatives, - numerals, - search, - replace, - keywords, - keyword_boost_legacy, - utterances, - tags, - detect_language, - } = self.0; - - if let Some(tier) = tier { - seq.serialize_element(&("tier", tier.as_ref()))?; - } - - match multichannel { - // Multichannels with models is enabled - // Ignore self.model field - Some(Multichannel::Enabled { - models: Some(models), - }) => { - seq.serialize_element(&("model", models_to_string(models)))?; - } - - // Multichannel with models is not enabled - // Use self.model field - Some(Multichannel::Enabled { models: None } | Multichannel::Disabled) | None => { - if let Some(model) = model { - seq.serialize_element(&("model", model.as_ref()))?; - } - } - }; - - if let Some(version) = version { - seq.serialize_element(&("version", version))?; - } - - if let Some(language) = language { - seq.serialize_element(&("language", language.as_ref()))?; - } - - if let Some(punctuate) = punctuate { - seq.serialize_element(&("punctuate", punctuate))?; - } - - if let Some(profanity_filter) = profanity_filter { - seq.serialize_element(&("profanity_filter", profanity_filter))?; - } - - for element in redact { - seq.serialize_element(&("redact", element.as_ref()))?; - } - - if let Some(diarize) = diarize { - seq.serialize_element(&("diarize", diarize))?; - } - - if let Some(ner) = ner { - seq.serialize_element(&("ner", ner))?; - } - - match multichannel { - Some(Multichannel::Disabled) => seq.serialize_element(&("multichannel", false))?, - Some(Multichannel::Enabled { models: _ }) => { - // Multichannel models are serialized above if they exist - // This is done instead of serializing the self.model field - seq.serialize_element(&("multichannel", true))?; - } - None => (), - }; - - if let Some(alternatives) = alternatives { - seq.serialize_element(&("alternatives", alternatives))?; - } - - if let Some(numerals) = numerals { - seq.serialize_element(&("numerals", numerals))?; - } - - for element in search { - seq.serialize_element(&("search", element))?; - } - - for element in replace { - if let Some(replace) = &element.replace { - seq.serialize_element(&("replace", format!("{}:{}", element.find, replace)))?; - } else { - seq.serialize_element(&("replace", &element.find))?; - } - } - - for element in keywords { - if let Some(intensifier) = element.intensifier { - seq.serialize_element(&( - "keywords", - format!("{}:{}", element.keyword, intensifier), - ))?; - } else { - seq.serialize_element(&("keywords", &element.keyword))?; - } - } - - if *keyword_boost_legacy { - seq.serialize_element(&("keyword_boost", "legacy"))?; - } - - match utterances { - Some(Utterances::Disabled) => seq.serialize_element(&("utterances", false))?, - Some(Utterances::Enabled { utt_split }) => { - seq.serialize_element(&("utterances", true))?; - - if let Some(utt_split) = utt_split { - seq.serialize_element(&("utt_split", utt_split))?; - } - } - None => (), - }; - - for element in tags { - seq.serialize_element(&("tag", element))?; - } - - if let Some(detect_language) = detect_language { - seq.serialize_element(&("detect_language", detect_language))?; - } - - seq.end() - } -} - -impl AsRef for Tier { - fn as_ref(&self) -> &str { - use Tier::*; - - match self { - Enhanced => "enhanced", - Base => "base", - } - } -} - -impl AsRef for Model { - fn as_ref(&self) -> &str { - use Model::*; - - match self { - General => "general", - Meeting => "meeting", - Phonecall => "phonecall", - Voicemail => "voicemail", - Finance => "finance", - Conversationalai => "conversationalai", - Video => "video", - CustomId(id) => id, - } - } -} - -impl AsRef for Language { - fn as_ref(&self) -> &str { - use Language::*; - - match self { - zh => "zh", - zh_CN => "zh-CN", - zh_TW => "zh-TW", - nl => "nl", - en => "en", - en_AU => "en-AU", - en_GB => "en-GB", - en_IN => "en-IN", - en_NZ => "en-NZ", - en_US => "en-US", - fr => "fr", - fr_CA => "fr-CA", - de => "de", - hi => "hi", - hi_Latn => "hi-Latn", - id => "id", - it => "it", - ja => "ja", - ko => "ko", - pt => "pt", - pt_BR => "pt-BR", - ru => "ru", - es => "es", - es_419 => "es-419", - sv => "sv", - tr => "tr", - uk => "uk", - Other(bcp_47_tag) => bcp_47_tag, - } - } -} - -impl AsRef for Redact { - fn as_ref(&self) -> &str { - use Redact::*; - - match self { - Pci => "pci", - Numbers => "numbers", - Ssn => "ssn", - Other(id) => id, - } - } -} - -fn models_to_string(models: &[Model]) -> String { - models - .iter() - .map(AsRef::::as_ref) - .collect::>() - .join(":") -} - -#[cfg(test)] -mod models_to_string_tests { - use super::{Model::*, *}; - - #[test] - fn empty() { - assert_eq!(models_to_string(&[]), ""); - } - - #[test] - fn one() { - assert_eq!(models_to_string(&[General]), "general"); - } - - #[test] - fn many() { - assert_eq!( - models_to_string(&[Phonecall, Meeting, Voicemail]), - "phonecall:meeting:voicemail" - ); - } - - #[test] - fn custom() { - assert_eq!( - models_to_string(&[ - Finance, - CustomId(String::from("extra_crispy")), - Conversationalai - ]), - "finance:extra_crispy:conversationalai" - ); - } -} - -#[cfg(test)] -mod serialize_options_tests { - use std::cmp; - use std::env; - - use super::{super::audio_source::AudioSource, *}; - use crate::Deepgram; - - fn check_serialization(options: &Options, expected: &str) { - let deepgram_api_key = env::var("DEEPGRAM_API_KEY").unwrap_or_default(); - - let dg_client = Deepgram::new(deepgram_api_key); - - let request = dg_client - .transcription() - .make_prerecorded_request_builder(AudioSource::from_url(""), options) - .build() - .unwrap(); - - let actual = request.url().query().unwrap_or(""); - - assert_eq!(actual, expected); - } - - fn generate_alphabet_test(key: &str, length: usize) -> (Vec<&str>, String) { - let letters = [ - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", - "R", "S", "T", "U", "V", "W", "X", "Y", "Z", - ]; - - let limited_letters = Vec::from(&letters[..cmp::min(length, letters.len())]); - - let expected = limited_letters - .iter() - .map(|letter| format!("{}={}", key, letter)) - .collect::>() - .join("&"); - - (limited_letters, expected) - } - - #[test] - fn all_options() { - let options = Options::builder() - .tier(Tier::Enhanced) - .model(Model::General) - .version("1.2.3") - .language(Language::en_US) - .punctuate(true) - .profanity_filter(true) - .redact([Redact::Pci, Redact::Ssn]) - .diarize(true) - .ner(true) - .multichannel_with_models([ - Model::Finance, - Model::CustomId(String::from("extra_crispy")), - Model::Conversationalai, - ]) - .alternatives(4) - .numerals(true) - .search(["Rust", "Deepgram"]) - .replace([Replace { - find: String::from("Aaron"), - replace: Some(String::from("Erin")), - }]) - .keywords(["Ferris"]) - .keywords_with_intensifiers([Keyword { - keyword: String::from("Cargo"), - intensifier: Some(-1.5), - }]) - .utterances_with_utt_split(0.9) - .tag(["Tag 1"]) - .build(); - - check_serialization(&options, "tier=enhanced&model=finance%3Aextra_crispy%3Aconversationalai&version=1.2.3&language=en-US&punctuate=true&profanity_filter=true&redact=pci&redact=ssn&diarize=true&ner=true&multichannel=true&alternatives=4&numerals=true&search=Rust&search=Deepgram&replace=Aaron%3AErin&keywords=Ferris&keywords=Cargo%3A-1.5&utterances=true&utt_split=0.9&tag=Tag+1"); - } - - #[test] - fn tier() { - check_serialization( - &Options::builder().tier(Tier::Enhanced).build(), - "tier=enhanced", - ); - - check_serialization(&Options::builder().tier(Tier::Base).build(), "tier=base"); - } - - #[test] - fn model() { - check_serialization( - &Options::builder().model(Model::General).build(), - "model=general", - ); - - check_serialization( - &Options::builder() - .model(Model::CustomId(String::from("extra_crispy"))) - .build(), - "model=extra_crispy", - ); - } - - #[test] - fn version() { - check_serialization( - &Options::builder().version("1.2.3").build(), - "version=1.2.3", - ); - } - - #[test] - fn language() { - check_serialization( - &Options::builder().language(Language::en_US).build(), - "language=en-US", - ); - - check_serialization( - &Options::builder().language(Language::ja).build(), - "language=ja", - ); - } - - #[test] - fn punctuate() { - check_serialization( - &Options::builder().punctuate(true).build(), - "punctuate=true", - ); - - check_serialization( - &Options::builder().punctuate(false).build(), - "punctuate=false", - ); - } - - #[test] - fn profanity_filter() { - check_serialization( - &Options::builder().profanity_filter(true).build(), - "profanity_filter=true", - ); - - check_serialization( - &Options::builder().profanity_filter(false).build(), - "profanity_filter=false", - ); - } - - #[test] - fn redact() { - check_serialization(&Options::builder().redact([]).build(), ""); - - check_serialization( - &Options::builder().redact([Redact::Numbers]).build(), - "redact=numbers", - ); - - check_serialization( - &Options::builder() - .redact([Redact::Ssn, Redact::Pci]) - .build(), - "redact=ssn&redact=pci", - ); - - check_serialization( - &Options::builder() - .redact([ - Redact::Numbers, - Redact::Ssn, - Redact::Pci, - Redact::Ssn, - Redact::Numbers, - Redact::Pci, - ]) - .build(), - "redact=numbers&redact=ssn&redact=pci&redact=ssn&redact=numbers&redact=pci", - ); - } - - #[test] - fn diarize() { - check_serialization(&Options::builder().diarize(true).build(), "diarize=true"); - - check_serialization(&Options::builder().diarize(false).build(), "diarize=false"); - } - - #[test] - fn ner() { - check_serialization(&Options::builder().ner(true).build(), "ner=true"); - - check_serialization(&Options::builder().ner(false).build(), "ner=false"); - } - - #[test] - fn multichannel() { - check_serialization( - &Options::builder().multichannel(true).build(), - "multichannel=true", - ); - - check_serialization( - &Options::builder().multichannel(false).build(), - "multichannel=false", - ); - - check_serialization( - &Options::builder() - .multichannel_with_models([ - Model::Finance, - Model::CustomId(String::from("extra_crispy")), - Model::Conversationalai, - ]) - .build(), - "model=finance%3Aextra_crispy%3Aconversationalai&multichannel=true", - ); - } - - #[test] - fn alternatives() { - check_serialization( - &Options::builder().alternatives(4).build(), - "alternatives=4", - ); - } - - #[test] - fn numerals() { - check_serialization(&Options::builder().numerals(true).build(), "numerals=true"); - - check_serialization( - &Options::builder().numerals(false).build(), - "numerals=false", - ); - } - - #[test] - fn search() { - check_serialization(&Options::builder().search([]).build(), ""); - - check_serialization(&Options::builder().search(["Rust"]).build(), "search=Rust"); - - check_serialization( - &Options::builder().search(["Rust", "Deepgram"]).build(), - "search=Rust&search=Deepgram", - ); - - { - let (input, expected) = generate_alphabet_test("search", 25); - check_serialization(&Options::builder().search(input).build(), &expected); - } - } - - #[test] - fn replace() { - check_serialization(&Options::builder().replace([]).build(), ""); - - check_serialization( - &Options::builder() - .replace([Replace { - find: String::from("Aaron"), - replace: Some(String::from("Erin")), - }]) - .build(), - "replace=Aaron%3AErin", - ); - - check_serialization( - &Options::builder() - .replace([Replace { - find: String::from("Voldemort"), - replace: None, - }]) - .build(), - "replace=Voldemort", - ); - - check_serialization( - &Options::builder() - .replace([ - Replace { - find: String::from("Aaron"), - replace: Some(String::from("Erin")), - }, - Replace { - find: String::from("Voldemort"), - replace: None, - }, - ]) - .build(), - "replace=Aaron%3AErin&replace=Voldemort", - ); - - check_serialization( - &Options::builder() - .replace([Replace { - find: String::from("this too"), - replace: Some(String::from("that too")), - }]) - .build(), - "replace=this+too%3Athat+too", - ); - } - - #[test] - fn keywords() { - check_serialization(&Options::builder().keywords([]).build(), ""); - - check_serialization( - &Options::builder().keywords(["Ferris"]).build(), - "keywords=Ferris", - ); - - check_serialization( - &Options::builder().keywords(["Ferris", "Cargo"]).build(), - "keywords=Ferris&keywords=Cargo", - ); - - { - let (input, expected) = generate_alphabet_test("keywords", 200); - - check_serialization(&Options::builder().keywords(input).build(), &expected); - } - - { - let keywords = [Keyword { - keyword: String::from("Ferris"), - intensifier: Some(0.5), - }]; - - check_serialization( - &Options::builder() - .keywords_with_intensifiers(keywords) - .build(), - "keywords=Ferris%3A0.5", - ); - } - - { - let keywords = [ - Keyword { - keyword: String::from("Ferris"), - intensifier: Some(0.5), - }, - Keyword { - keyword: String::from("Cargo"), - intensifier: Some(-1.5), - }, - ]; - - check_serialization( - &Options::builder() - .keywords_with_intensifiers(keywords) - .build(), - "keywords=Ferris%3A0.5&keywords=Cargo%3A-1.5", - ); - } - - check_serialization( - &Options::builder() - .keywords(["Ferris"]) - .keyword_boost_legacy() - .build(), - "keywords=Ferris&keyword_boost=legacy", - ); - } - - #[test] - fn utterances() { - check_serialization( - &Options::builder().utterances(false).build(), - "utterances=false", - ); - - check_serialization( - &Options::builder().utterances(true).build(), - "utterances=true", - ); - - check_serialization( - &Options::builder().utterances_with_utt_split(0.9).build(), - "utterances=true&utt_split=0.9", - ); - } - - #[test] - fn tag() { - check_serialization(&Options::builder().tag(["Tag 1"]).build(), "tag=Tag+1"); - - check_serialization( - &Options::builder().tag(["Tag 1", "Tag 2"]).build(), - "tag=Tag+1&tag=Tag+2", - ); - } - - #[test] - fn detect_language() { - check_serialization( - &Options::builder().detect_language(false).build(), - "detect_language=false", - ); - - check_serialization( - &Options::builder().detect_language(true).build(), - "detect_language=true", - ); - } -} diff --git a/deepgram-rust-sdk/src/transcription/prerecorded/response.rs b/deepgram-rust-sdk/src/transcription/prerecorded/response.rs deleted file mode 100644 index 4d04adb..0000000 --- a/deepgram-rust-sdk/src/transcription/prerecorded/response.rs +++ /dev/null @@ -1,237 +0,0 @@ -//! Deepgram pre-recorded transcription API response types. -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#transcription-prerecorded-responses - -use serde::{Deserialize, Serialize}; -use uuid::Uuid; - -/// Returned by [`Transcription::prerecorded`](crate::transcription::Transcription::prerecorded). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#transcription-prerecorded -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Response { - #[allow(missing_docs)] - pub metadata: ListenMetadata, - - #[allow(missing_docs)] - pub results: ListenResults, -} - -/// Returned by [`Transcription::prerecorded_callback`](crate::transcription::Transcription::prerecorded_callback). -/// -/// See the [Deepgram Callback feature docs][docs] for more info. -/// -/// [docs]: https://developers.deepgram.com/documentation/features/callback/ -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct CallbackResponse { - #[allow(missing_docs)] - pub request_id: Uuid, -} - -/// Metadata about the transcription. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#transcription-prerecorded -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct ListenMetadata { - #[allow(missing_docs)] - pub request_id: Uuid, - - #[allow(missing_docs)] - pub transaction_key: String, - - #[allow(missing_docs)] - pub sha256: String, - - #[allow(missing_docs)] - pub created: String, - - #[allow(missing_docs)] - pub duration: f64, - - #[allow(missing_docs)] - pub channels: usize, -} - -/// Transcription results. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#transcription-prerecorded -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct ListenResults { - #[allow(missing_docs)] - pub channels: Vec, - - /// [`None`] unless the [Utterances feature][docs] is set. - /// Features can be set using an [`OptionsBuilder`](`super::options::OptionsBuilder`). - /// - /// [docs]: https://developers.deepgram.com/documentation/features/utterances/ - pub utterances: Option>, -} - -/// Transcription results for a single audio channel. -/// -/// See the [Deepgram API Reference][api] -/// and the [Deepgram Multichannel feature docs][docs] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#transcription-prerecorded -/// [docs]: https://developers.deepgram.com/documentation/features/multichannel/ -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct ChannelResult { - /// [`None`] unless the [Search feature][docs] is set. - /// Features can be set using an [`OptionsBuilder`](`super::options::OptionsBuilder`). - /// - /// [docs]: https://developers.deepgram.com/documentation/features/search/ - pub search: Option>, - - #[allow(missing_docs)] - pub alternatives: Vec, - - /// [BCP-47][bcp47] language tag for the dominant language identified in the channel. - /// - /// [`None`] unless the [Language Detection feature][docs] is set. - /// Features can be set using an [`OptionsBuilder`](`super::options::OptionsBuilder`). - /// - /// [bcp47]: https://tools.ietf.org/html/bcp47 - /// [docs]: https://developers.deepgram.com/docs/language-detection/ - pub detected_language: Option, -} - -/// Transcription results for a single utterance. -/// -/// See the [Deepgram Utterance feature docs][docs] for more info. -/// -/// [docs]: https://developers.deepgram.com/documentation/features/utterances/ -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Utterance { - #[allow(missing_docs)] - pub start: f64, - - #[allow(missing_docs)] - pub end: f64, - - #[allow(missing_docs)] - pub confidence: f64, - - #[allow(missing_docs)] - pub channel: usize, - - #[allow(missing_docs)] - pub transcript: String, - - #[allow(missing_docs)] - pub words: Vec, - - /// [`None`] unless the [Diarization feature][docs] is set. - /// Features can be set using an [`OptionsBuilder`](`super::options::OptionsBuilder`). - /// - /// [docs]: https://developers.deepgram.com/documentation/features/diarize/ - pub speaker: Option, - - #[allow(missing_docs)] - pub id: Uuid, -} - -/// Search results. -/// -/// See the [Deepgram API Reference][api] -/// and the [Deepgram Search feature docs][docs] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#transcription-prerecorded -/// [docs]: https://developers.deepgram.com/documentation/features/search/ -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct SearchResults { - #[allow(missing_docs)] - pub query: String, - - #[allow(missing_docs)] - pub hits: Vec, -} - -/// Transcript alternatives. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#transcription-prerecorded -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct ResultAlternative { - #[allow(missing_docs)] - pub transcript: String, - - #[allow(missing_docs)] - pub confidence: f64, - - #[allow(missing_docs)] - pub words: Vec, -} - -/// A single transcribed word. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#transcription-prerecorded -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Word { - #[allow(missing_docs)] - pub word: String, - - #[allow(missing_docs)] - pub start: f64, - - #[allow(missing_docs)] - pub end: f64, - - #[allow(missing_docs)] - pub confidence: f64, - - /// [`None`] unless the [Diarization feature][docs] is set. - /// Features can be set using an [`OptionsBuilder`](`super::options::OptionsBuilder`). - /// - /// [docs]: https://developers.deepgram.com/documentation/features/diarize/ - pub speaker: Option, - pub speaker_confidence: Option, - - /// [`None`] unless the [Punctuation feature][docs] is set. - /// Features can be set using an [`OptionsBuilder`](`super::options::OptionsBuilder`). - /// - /// [docs]: https://developers.deepgram.com/documentation/features/punctuate/ - pub punctuated_word: Option, -} - -/// Search result. -/// -/// See the [Deepgram API Reference][api] -/// and the [Deepgram Search feature docs][docs] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#transcription-prerecorded -/// [docs]: https://developers.deepgram.com/documentation/features/search/ -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Hit { - #[allow(missing_docs)] - pub confidence: f64, - - #[allow(missing_docs)] - pub start: f64, - - #[allow(missing_docs)] - pub end: f64, - - #[allow(missing_docs)] - pub snippet: String, -} diff --git a/deepgram-rust-sdk/src/usage.rs b/deepgram-rust-sdk/src/usage.rs deleted file mode 100644 index ad99a63..0000000 --- a/deepgram-rust-sdk/src/usage.rs +++ /dev/null @@ -1,242 +0,0 @@ -//! Get the usage data of a Deepgram Project. -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#usage - -use crate::{send_and_translate_response, Deepgram}; - -pub mod get_fields_options; -pub mod get_usage_options; -pub mod list_requests_options; -pub mod response; - -use response::{Fields, Request, Requests, UsageSummary}; - -/// Get the usage data of a Deepgram Project. -/// -/// Constructed using [`Deepgram::usage`]. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#usage -#[derive(Debug, Clone)] -pub struct Usage<'a>(&'a Deepgram); - -impl Deepgram { - /// Construct a new [`Usage`] from a [`Deepgram`]. - pub fn usage(&self) -> Usage<'_> { - self.into() - } -} - -impl<'a> From<&'a Deepgram> for Usage<'a> { - /// Construct a new [`Usage`] from a [`Deepgram`]. - fn from(deepgram: &'a Deepgram) -> Self { - Self(deepgram) - } -} - -impl Usage<'_> { - /// Get all requests sent to the Deepgram API for the specified project. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#usage-all - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{ - /// # usage::{get_fields_options, get_usage_options, list_requests_options}, - /// # Deepgram, DeepgramError, - /// # }; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// let options = list_requests_options::Options::builder().build(); - /// let requests = dg_client - /// .usage() - /// .list_requests(&project_id, &options) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn list_requests( - &self, - project_id: &str, - options: &list_requests_options::Options, - ) -> crate::Result { - let url = format!( - "https://api.deepgram.com/v1/projects/{}/requests", - project_id, - ); - let request = self - .0 - .client - .get(url) - .query(&list_requests_options::SerializableOptions::from(options)); - - send_and_translate_response(request).await - } - - /// Get the details of the specified request sent to the Deepgram API for the specified project. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#usage-get - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{ - /// # usage::{get_fields_options, get_usage_options, list_requests_options}, - /// # Deepgram, DeepgramError, - /// # }; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// # let request_id = - /// # env::var("DEEPGRAM_REQUEST_ID").expect("DEEPGRAM_REQUEST_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// let request = dg_client - /// .usage() - /// .get_request(&project_id, &request_id) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn get_request(&self, project_id: &str, request_id: &str) -> crate::Result { - let url = format!( - "https://api.deepgram.com/v1/projects/{}/requests/{}", - project_id, request_id, - ); - - send_and_translate_response(self.0.client.get(url)).await - } - - /// Get a summary of usage statistics. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#usage-summary - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{ - /// # usage::{get_fields_options, get_usage_options, list_requests_options}, - /// # Deepgram, DeepgramError, - /// # }; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// let options = get_usage_options::Options::builder().build(); - /// let summary = dg_client - /// .usage() - /// .get_usage(&project_id, &options) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn get_usage( - &self, - project_id: &str, - options: &get_usage_options::Options, - ) -> crate::Result { - let url = format!("https://api.deepgram.com/v1/projects/{}/usage", project_id); - let request = self - .0 - .client - .get(url) - .query(&get_usage_options::SerializableOptions::from(options)); - - send_and_translate_response(request).await - } - - /// Get the features, models, tags, languages, and processing method used for requests in the specified project. - /// - /// See the [Deepgram API Reference][api] for more info. - /// - /// [api]: https://developers.deepgram.com/api-reference/#usage-fields - /// - /// # Examples - /// - /// ```no_run - /// # use std::env; - /// # - /// # use deepgram::{ - /// # usage::{get_fields_options, get_usage_options, list_requests_options}, - /// # Deepgram, DeepgramError, - /// # }; - /// # - /// # #[tokio::main] - /// # async fn main() -> Result<(), DeepgramError> { - /// # let deepgram_api_key = - /// # env::var("DEEPGRAM_API_KEY").expect("DEEPGRAM_API_KEY environmental variable"); - /// # - /// # let project_id = - /// # env::var("DEEPGRAM_PROJECT_ID").expect("DEEPGRAM_PROJECT_ID environmental variable"); - /// # - /// let dg_client = Deepgram::new(&deepgram_api_key); - /// - /// let options = get_fields_options::Options::builder().build(); - /// let summary = dg_client - /// .usage() - /// .get_fields(&project_id, &options) - /// .await?; - /// # - /// # Ok(()) - /// # } - /// ``` - pub async fn get_fields( - &self, - project_id: &str, - options: &get_fields_options::Options, - ) -> crate::Result { - let url = format!( - "https://api.deepgram.com/v1/projects/{}/usage/fields", - project_id, - ); - let request = self - .0 - .client - .get(url) - .query(&get_fields_options::SerializableOptions::from(options)); - - send_and_translate_response(request).await - } -} diff --git a/deepgram-rust-sdk/src/usage/get_fields_options.rs b/deepgram-rust-sdk/src/usage/get_fields_options.rs deleted file mode 100644 index edbfdd7..0000000 --- a/deepgram-rust-sdk/src/usage/get_fields_options.rs +++ /dev/null @@ -1,102 +0,0 @@ -//! Set options for [`Usage::get_fields`](super::Usage::get_fields). -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#usage-fields - -use serde::Serialize; - -/// Used as a parameter for [`Usage::get_fields`](super::Usage::get_fields). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#usage-fields -#[derive(Debug, PartialEq, Clone)] -pub struct Options { - start: Option, - end: Option, -} - -/// Builds an [`Options`] object using [the Builder pattern][builder]. -/// -/// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html -#[derive(Debug, PartialEq, Clone)] -pub struct OptionsBuilder(Options); - -#[derive(Serialize)] -pub(super) struct SerializableOptions<'a> { - #[serde(skip_serializing_if = "Option::is_none")] - start: &'a Option, - - #[serde(skip_serializing_if = "Option::is_none")] - end: &'a Option, -} - -impl Options { - /// Construct a new [`OptionsBuilder`]. - pub fn builder() -> OptionsBuilder { - OptionsBuilder::new() - } -} - -impl OptionsBuilder { - /// Construct a new [`OptionsBuilder`]. - pub fn new() -> Self { - Self(Options { - start: None, - end: None, - }) - } - - /// Set the time range start date. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::list_requests_options::Options; - /// # - /// let options1 = Options::builder() - /// .start("1970-01-01") - /// .build(); - /// ``` - pub fn start(mut self, start: impl Into) -> Self { - self.0.start = Some(start.into()); - self - } - - /// Set the time range end date. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::list_requests_options::Options; - /// # - /// let options1 = Options::builder() - /// .end("2038-01-19") - /// .build(); - /// ``` - pub fn end(mut self, end: impl Into) -> Self { - self.0.end = Some(end.into()); - self - } - - /// Finish building the [`Options`] object. - pub fn build(self) -> Options { - self.0 - } -} - -impl Default for OptionsBuilder { - fn default() -> Self { - Self::new() - } -} - -impl<'a> From<&'a Options> for SerializableOptions<'a> { - fn from(options: &'a Options) -> Self { - // Destructuring it makes sure that we don't forget to use any of it - let Options { start, end } = options; - - Self { start, end } - } -} diff --git a/deepgram-rust-sdk/src/usage/get_usage_options.rs b/deepgram-rust-sdk/src/usage/get_usage_options.rs deleted file mode 100644 index c5529c1..0000000 --- a/deepgram-rust-sdk/src/usage/get_usage_options.rs +++ /dev/null @@ -1,599 +0,0 @@ -//! Set options for [`Usage::get_usage`](super::Usage::get_usage). -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#usage-summary - -use serde::{ser::SerializeSeq, Serialize}; - -/// Used as a parameter for [`Usage::get_usage`](super::Usage::get_usage). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#usage-summary -#[derive(Debug, PartialEq, Clone)] -pub struct Options { - start: Option, - end: Option, - accessor: Option, - tags: Vec, - methods: Vec, - models: Vec, - multichannel: Option, - interim_results: Option, - punctuate: Option, - ner: Option, - utterances: Option, - replace: Option, - profanity_filter: Option, - keywords: Option, - diarize: Option, - search: Option, - redact: Option, - alternatives: Option, - numerals: Option, -} - -/// Used as a parameter for [`OptionsBuilder::method`]. -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] -#[non_exhaustive] -pub enum Method { - #[allow(missing_docs)] - Sync, - - #[allow(missing_docs)] - Async, - - #[allow(missing_docs)] - Streaming, -} - -/// Builds an [`Options`] object using [the Builder pattern][builder]. -/// -/// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html -#[derive(Debug, PartialEq, Clone)] -pub struct OptionsBuilder(Options); - -pub(super) struct SerializableOptions<'a>(&'a Options); - -impl Options { - /// Construct a new [`OptionsBuilder`]. - pub fn builder() -> OptionsBuilder { - OptionsBuilder::new() - } -} - -impl OptionsBuilder { - /// Construct a new [`OptionsBuilder`]. - pub fn new() -> Self { - Self(Options { - start: None, - end: None, - accessor: None, - tags: Vec::new(), - methods: Vec::new(), - models: Vec::new(), - multichannel: None, - interim_results: None, - punctuate: None, - ner: None, - utterances: None, - replace: None, - profanity_filter: None, - keywords: None, - diarize: None, - search: None, - redact: None, - alternatives: None, - numerals: None, - }) - } - - /// Set the time range start date. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .start("1970-01-01") - /// .build(); - /// ``` - pub fn start(mut self, start: impl Into) -> Self { - self.0.start = Some(start.into()); - self - } - - /// Set the time range end date. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .end("2038-01-19") - /// .build(); - /// ``` - pub fn end(mut self, end: impl Into) -> Self { - self.0.end = Some(end.into()); - self - } - - /// Limits results to requests made using the API key corresponding to the given accessor. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .accessor("12345678-1234-1234-1234-1234567890ab") - /// .build(); - /// ``` - pub fn accessor(mut self, accessor: impl Into) -> Self { - self.0.accessor = Some(accessor.into()); - self - } - - /// Limits results to requests associated with the specified tag. - /// - /// Calling this when already set will append to the existing tags, not overwrite them. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .tag(["Tag 1", "Tag 2"]) - /// .build(); - /// ``` - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options1 = Options::builder() - /// .tag(["Tag 1"]) - /// .tag(["Tag 2"]) - /// .build(); - /// - /// let options2 = Options::builder() - /// .tag(["Tag 1", "Tag 2"]) - /// .build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn tag<'a>(mut self, tag: impl IntoIterator) -> Self { - self.0.tags.extend(tag.into_iter().map(String::from)); - self - } - - /// Limits results to requests processed using the specified method. - /// - /// Calling this when already set will append to the existing methods, not overwrite them. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::{Method, Options}; - /// # - /// let options = Options::builder() - /// .method([Method::Sync, Method::Streaming]) - /// .build(); - /// ``` - /// - /// ``` - /// # use deepgram::usage::get_usage_options::{Method, Options}; - /// # - /// let options1 = Options::builder() - /// .method([Method::Sync]) - /// .method([Method::Streaming]) - /// .build(); - /// - /// let options2 = Options::builder() - /// .method([Method::Sync, Method::Streaming]) - /// .build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn method(mut self, method: impl IntoIterator) -> Self { - self.0.methods.extend(method); - self - } - - /// Limits results to requests run with the specified model UUID applied. - /// - /// Calling this when already set will append to the models, not overwrite them. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .model([ - /// "4899aa60-f723-4517-9815-2042acc12a82", - /// "125125fb-e391-458e-a227-a60d6426f5d6", - /// ]) - /// .build(); - /// ``` - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options1 = Options::builder() - /// .model(["4899aa60-f723-4517-9815-2042acc12a82"]) - /// .model(["125125fb-e391-458e-a227-a60d6426f5d6"]) - /// .build(); - /// - /// let options2 = Options::builder() - /// .model([ - /// "4899aa60-f723-4517-9815-2042acc12a82", - /// "125125fb-e391-458e-a227-a60d6426f5d6", - /// ]) - /// .build(); - /// - /// assert_eq!(options1, options2); - /// ``` - pub fn model<'a>(mut self, model: impl IntoIterator) -> Self { - self.0.models.extend(model.into_iter().map(String::from)); - self - } - - /// Limits results to requests that include the Multichannel feature. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .multichannel(true) - /// .build(); - /// ``` - pub fn multichannel(mut self, multichannel: bool) -> Self { - self.0.multichannel = Some(multichannel); - self - } - - /// Limits results to requests that include the Interim Results feature. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .interim_results(true) - /// .build(); - /// ``` - pub fn interim_results(mut self, interim_results: bool) -> Self { - self.0.interim_results = Some(interim_results); - self - } - - /// Limits results to requests that include the Punctuation feature. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .punctuate(true) - /// .build(); - /// ``` - pub fn punctuate(mut self, punctuate: bool) -> Self { - self.0.punctuate = Some(punctuate); - self - } - - /// Limits results to requests that include the Named-Entity Recognition feature. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .ner(true) - /// .build(); - /// ``` - pub fn ner(mut self, ner: bool) -> Self { - self.0.ner = Some(ner); - self - } - - /// Limits results to requests that include the Utterances feature. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .utterances(true) - /// .build(); - /// ``` - pub fn utterances(mut self, utterances: bool) -> Self { - self.0.utterances = Some(utterances); - self - } - - /// Limits results to requests that include the Replace feature. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .replace(true) - /// .build(); - /// ``` - pub fn replace(mut self, replace: bool) -> Self { - self.0.replace = Some(replace); - self - } - - /// Limits results to requests that include the Profanity Filter feature. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .profanity_filter(true) - /// .build(); - /// ``` - pub fn profanity_filter(mut self, profanity_filter: bool) -> Self { - self.0.profanity_filter = Some(profanity_filter); - self - } - - /// Limits results to requests that include the Keywords feature. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .keywords(true) - /// .build(); - /// ``` - pub fn keywords(mut self, keywords: bool) -> Self { - self.0.keywords = Some(keywords); - self - } - - /// Limits results to requests that include the Diarization feature. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .diarize(true) - /// .build(); - /// ``` - pub fn diarize(mut self, diarize: bool) -> Self { - self.0.diarize = Some(diarize); - self - } - - /// Limits results to requests that include the Search feature. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .search(true) - /// .build(); - /// ``` - pub fn search(mut self, search: bool) -> Self { - self.0.search = Some(search); - self - } - - /// Limits results to requests that include the Redaction feature. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .redact(true) - /// .build(); - /// ``` - pub fn redact(mut self, redact: bool) -> Self { - self.0.redact = Some(redact); - self - } - - /// Limits results to requests that include the Alternatives feature. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .alternatives(true) - /// .build(); - /// ``` - pub fn alternatives(mut self, alternatives: bool) -> Self { - self.0.alternatives = Some(alternatives); - self - } - - /// Limits results to requests that include the Numerals feature. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::get_usage_options::Options; - /// # - /// let options = Options::builder() - /// .numerals(true) - /// .build(); - /// ``` - pub fn numerals(mut self, numerals: bool) -> Self { - self.0.numerals = Some(numerals); - self - } - - /// Finish building the [`Options`] object. - pub fn build(self) -> Options { - self.0 - } -} - -impl Default for OptionsBuilder { - fn default() -> Self { - Self::new() - } -} - -impl<'a> From<&'a Options> for SerializableOptions<'a> { - fn from(options: &'a Options) -> Self { - Self(options) - } -} - -impl Serialize for SerializableOptions<'_> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut seq = serializer.serialize_seq(None)?; - - // Destructuring it makes sure that we don't forget to use any of it - let Options { - start, - end, - accessor, - tags, - methods, - models, - multichannel, - interim_results, - punctuate, - ner, - utterances, - replace, - profanity_filter, - keywords, - diarize, - search, - redact, - alternatives, - numerals, - } = self.0; - - if let Some(start) = start { - seq.serialize_element(&("start", start))?; - } - - if let Some(end) = end { - seq.serialize_element(&("end", end))?; - } - - if let Some(accessor) = accessor { - seq.serialize_element(&("accessor", accessor))?; - } - - for element in tags { - seq.serialize_element(&("tag", element))?; - } - - for element in methods { - seq.serialize_element(&("method", AsRef::::as_ref(element)))?; - } - - for element in models { - seq.serialize_element(&("model", element))?; - } - - if let Some(multichannel) = multichannel { - seq.serialize_element(&("multichannel", multichannel))?; - } - - if let Some(interim_results) = interim_results { - seq.serialize_element(&("interim_results", interim_results))?; - } - - if let Some(punctuate) = punctuate { - seq.serialize_element(&("punctuate", punctuate))?; - } - - if let Some(ner) = ner { - seq.serialize_element(&("ner", ner))?; - } - - if let Some(utterances) = utterances { - seq.serialize_element(&("utterances", utterances))?; - } - - if let Some(replace) = replace { - seq.serialize_element(&("replace", replace))?; - } - - if let Some(replace) = replace { - seq.serialize_element(&("replace", replace))?; - } - - if let Some(profanity_filter) = profanity_filter { - seq.serialize_element(&("profanity_filter", profanity_filter))?; - } - - if let Some(keywords) = keywords { - seq.serialize_element(&("keywords", keywords))?; - } - - if let Some(diarize) = diarize { - seq.serialize_element(&("diarize", diarize))?; - } - - if let Some(search) = search { - seq.serialize_element(&("search", search))?; - } - - if let Some(redact) = redact { - seq.serialize_element(&("redact", redact))?; - } - - if let Some(alternatives) = alternatives { - seq.serialize_element(&("alternatives", alternatives))?; - } - - if let Some(numerals) = numerals { - seq.serialize_element(&("numerals", numerals))?; - } - - seq.end() - } -} - -impl AsRef for Method { - fn as_ref(&self) -> &str { - use Method::*; - - match self { - Sync => "sync", - Async => "async", - Streaming => "streaming", - } - } -} - -mod serialize_options_tests { - // TODO -} diff --git a/deepgram-rust-sdk/src/usage/list_requests_options.rs b/deepgram-rust-sdk/src/usage/list_requests_options.rs deleted file mode 100644 index c66a05f..0000000 --- a/deepgram-rust-sdk/src/usage/list_requests_options.rs +++ /dev/null @@ -1,169 +0,0 @@ -//! Set options for [`Usage::list_requests`](super::Usage::list_requests). -//! -//! See the [Deepgram API Reference][api] for more info. -//! -//! [api]: https://developers.deepgram.com/api-reference/#usage-all - -use serde::Serialize; - -/// Used as a parameter for [`Usage::list_requests`](super::Usage::list_requests). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#usage-all -#[derive(Debug, PartialEq, Clone)] -pub struct Options { - start: Option, - end: Option, - limit: Option, - status: Option, -} - -/// Used as a parameter for [`OptionsBuilder::status`]. -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] -#[non_exhaustive] -pub enum Status { - #[allow(missing_docs)] - Succeeded, - - #[allow(missing_docs)] - Failed, -} - -/// Builds an [`Options`] object using [the Builder pattern][builder]. -/// -/// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html -#[derive(Debug, PartialEq, Clone)] -pub struct OptionsBuilder(Options); - -#[derive(Serialize)] -pub(super) struct SerializableOptions<'a> { - #[serde(skip_serializing_if = "Option::is_none")] - start: &'a Option, - - #[serde(skip_serializing_if = "Option::is_none")] - end: &'a Option, - - #[serde(skip_serializing_if = "Option::is_none")] - limit: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - status: Option<&'static str>, -} - -impl Options { - /// Construct a new [`OptionsBuilder`]. - pub fn builder() -> OptionsBuilder { - OptionsBuilder::new() - } -} - -impl OptionsBuilder { - /// Construct a new [`OptionsBuilder`]. - pub fn new() -> Self { - Self(Options { - start: None, - end: None, - limit: None, - status: None, - }) - } - - /// Set the time range start date. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::list_requests_options::Options; - /// # - /// let options1 = Options::builder() - /// .start("1970-01-01") - /// .build(); - /// ``` - pub fn start(mut self, start: impl Into) -> Self { - self.0.start = Some(start.into()); - self - } - - /// Set the time range end date. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::list_requests_options::Options; - /// # - /// let options1 = Options::builder() - /// .end("2038-01-19") - /// .build(); - /// ``` - pub fn end(mut self, end: impl Into) -> Self { - self.0.end = Some(end.into()); - self - } - - /// Set the maximum number of results to return per page. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::list_requests_options::Options; - /// # - /// let options1 = Options::builder() - /// .limit(42) - /// .build(); - /// ``` - pub fn limit(mut self, limit: usize) -> Self { - self.0.limit = Some(limit); - self - } - - /// Limits results to requests to requests that either succeeded or failed. - /// - /// # Examples - /// - /// ``` - /// # use deepgram::usage::list_requests_options::{Options, Status}; - /// # - /// let options1 = Options::builder() - /// .status(Status::Succeeded) - /// .build(); - /// ``` - pub fn status(mut self, status: Status) -> Self { - self.0.status = Some(status); - self - } - - /// Finish building the [`Options`] object. - pub fn build(self) -> Options { - self.0 - } -} - -impl Default for OptionsBuilder { - fn default() -> Self { - Self::new() - } -} - -impl<'a> From<&'a Options> for SerializableOptions<'a> { - fn from(options: &'a Options) -> Self { - // Destructuring it makes sure that we don't forget to use any of it - let Options { - start, - end, - limit, - status, - } = options; - - Self { - start, - end, - limit: *limit, - status: match status { - Some(Status::Succeeded) => Some("succeeded"), - Some(Status::Failed) => Some("failed"), - None => None, - }, - } - } -} diff --git a/deepgram-rust-sdk/src/usage/response.rs b/deepgram-rust-sdk/src/usage/response.rs deleted file mode 100644 index 8e77aba..0000000 --- a/deepgram-rust-sdk/src/usage/response.rs +++ /dev/null @@ -1,282 +0,0 @@ -//! Deepgram usage API response types. - -use serde::{Deserialize, Serialize}; -use uuid::Uuid; - -/// Returned by [`Usage::list_requests`](super::Usage::list_requests). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#usage-all -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Requests { - #[allow(missing_docs)] - pub page: usize, - - #[allow(missing_docs)] - pub limit: usize, - - #[allow(missing_docs)] - pub requests: Vec, -} - -/// Returned by [`Usage::get_request`](super::Usage::get_request). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#usage-get -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Request { - #[allow(missing_docs)] - pub request_id: Uuid, - - #[allow(missing_docs)] - pub created: String, - - #[allow(missing_docs)] - pub path: String, - - #[allow(missing_docs)] - pub api_key_id: Uuid, - - #[allow(missing_docs)] - pub response: Option, - - #[allow(missing_docs)] - pub callback: Option, -} - -/// The response generated by the request. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#usage-get -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Response { - #[allow(missing_docs)] - pub details: Option
, - - #[allow(missing_docs)] - pub message: Option, - - #[allow(missing_docs)] - pub code: i16, - - #[allow(missing_docs)] - pub completed: String, -} - -/// Details about the request. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#usage-get -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Details { - #[allow(missing_docs)] - pub usd: Option, - - #[allow(missing_docs)] - pub duration: f64, - - #[allow(missing_docs)] - pub total_audio: f64, - - #[allow(missing_docs)] - pub channels: usize, - - #[allow(missing_docs)] - pub streams: usize, - - #[allow(missing_docs)] - pub models: Vec, - - #[allow(missing_docs)] - pub method: String, - - #[allow(missing_docs)] - pub tags: Vec, - - #[allow(missing_docs)] - pub features: Vec, - - #[allow(missing_docs)] - pub config: Config, -} - -/// Configuration used when running the request. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#usage-get -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Config { - #[allow(missing_docs)] - pub alternatives: Option, - - #[allow(missing_docs)] - pub diarize: Option, - - #[allow(missing_docs)] - pub keywords: Option>, - - #[allow(missing_docs)] - pub language: Option, - - #[allow(missing_docs)] - pub model: Option, - - #[allow(missing_docs)] - pub tier: Option, - - #[allow(missing_docs)] - pub multichannel: Option, - - #[allow(missing_docs)] - pub ner: Option, - - #[allow(missing_docs)] - pub numerals: Option, - - #[allow(missing_docs)] - pub profanity_filter: Option, - - #[allow(missing_docs)] - pub punctuate: Option, - - #[allow(missing_docs)] - pub redact: Option>, - - #[allow(missing_docs)] - pub search: Option>, - - #[allow(missing_docs)] - pub utterances: Option, -} - -/// Details about a callback request. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#usage-get -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Callback { - #[allow(missing_docs)] - pub attempts: usize, - - #[allow(missing_docs)] - pub code: Option, - - #[allow(missing_docs)] - pub completed: Option, -} - -/// Returned by [`Usage::get_usage`](super::Usage::get_usage). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#usage-summary -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct UsageSummary { - #[allow(missing_docs)] - pub start: String, - - #[allow(missing_docs)] - pub end: String, - - #[allow(missing_docs)] - pub resolution: Resolution, - - #[allow(missing_docs)] - pub results: Vec, -} - -/// The amount of time covered by each [`Result`]. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#usage-summary -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Resolution { - #[allow(missing_docs)] - pub units: String, - - #[allow(missing_docs)] - pub amount: usize, -} - -/// A summary of the usage over a period of time. -/// -/// The resolution of each result is defined in [`UsageSummary::resolution`]. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#usage-summary -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Result { - #[allow(missing_docs)] - pub start: String, - - #[allow(missing_docs)] - pub end: String, - - #[allow(missing_docs)] - pub hours: f64, - - #[allow(missing_docs)] - pub total_hours: f64, - - #[allow(missing_docs)] - pub requests: usize, -} - -/// Returned by [`Usage::get_fields`](super::Usage::get_fields). -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#usage-fields -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Fields { - #[allow(missing_docs)] - pub tags: Vec, - - #[allow(missing_docs)] - pub models: Vec, - - #[allow(missing_docs)] - pub processing_methods: Vec, - - #[allow(missing_docs)] - pub features: Vec, -} - -/// Details about the model used. -/// -/// See the [Deepgram API Reference][api] for more info. -/// -/// [api]: https://developers.deepgram.com/api-reference/#usage-fields -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Model { - #[allow(missing_docs)] - pub name: String, - - #[allow(missing_docs)] - pub language: String, - - #[allow(missing_docs)] - pub version: String, - - #[allow(missing_docs)] - pub model_id: Uuid, -} diff --git a/src/main.rs b/src/main.rs index 7b69ccf..83f87ad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,15 +8,6 @@ use bytes::{BufMut, Bytes, BytesMut}; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; use cpal::Sample; use crossbeam::channel::RecvError; -use deepgram::transcription::live::{Alternatives, Channel, Word as LiveWord}; -use deepgram::transcription::prerecorded::response::Word as PrerecordedWord; -use deepgram::{ - transcription::prerecorded::{ - audio_source::AudioSource, - options::{Language, Options}, - }, - Deepgram, DeepgramError, -}; use egui::text::LayoutJob; use egui::*; use futures::channel::mpsc::{self, Receiver, Sender}; @@ -38,28 +29,6 @@ mod audiofile; mod self_update; mod session; -enum Word { - Live(LiveWord), - Prerecorded(PrerecordedWord), -} - -impl Word { - fn speaker(&self) -> usize { - match self { - Word::Live(word) => word.speaker as usize, - Word::Prerecorded(word) => word.speaker.unwrap(), - } - } - fn word(&self) -> &str { - match self { - Word::Live(word) => &word.word, - Word::Prerecorded(word) => &word.word, - } - } -} - -static TRANSCRIPT: Lazy>>> = Lazy::new(Default::default); -static TRANSCRIPT_FINAL: Lazy>>> = Lazy::new(Default::default); static DURATION: Lazy> = Lazy::new(Default::default); static COMPLETION: Lazy> = Lazy::new(Default::default); static COMPLETION_PROMPT: Lazy> = Lazy::new(|| { @@ -208,33 +177,6 @@ pub struct App { } impl App { - fn get_transcript(&self) -> String { - let mut transcript: String = String::new(); - - let words = TRANSCRIPT_FINAL.lock().unwrap(); - - let lines = words.split(|word| word.is_none()); - - for line in lines { - let mut current_speaker = 100; - - for word in line { - if let Some(word) = word { - if word.speaker() != current_speaker { - current_speaker = word.speaker(); - transcript.push_str(&format!( - "\n[{}]: ", - self.speaker_names.get(current_speaker).unwrap_or(&String::new()) - )); - } - transcript.push_str(&format!("{} ", word.word())); - } - } - } - transcript.push('\n'); - transcript - } - pub fn new(cc: &eframe::CreationContext<'_>) -> Self { cc.egui_ctx.set_visuals(egui::style::Visuals::dark()); cc.egui_ctx.style_mut(|s| s.visuals.override_text_color = Some(Color32::WHITE)); @@ -383,156 +325,6 @@ impl eframe::App for App { .changed() .then(|| setting2.save()); - for (i, session) in self.sessions.iter().enumerate() { - if ui.button(format!("Session {}: {} s", i, session.duration_ms() as f32 / 1000.0)).clicked() { - let samples = session.samples(); - - tokio::spawn(async move { - // clear transcript - TRANSCRIPT_FINAL.lock().unwrap().clear(); - - // dbg!(session.samples().len()); - audiofile::save_wav_file(samples); - - let dg_client = Deepgram::new(Setting::get("deepgram_api_key").value); - - let file = File::open("temp_audio.aac").await.unwrap(); - - let source = AudioSource::from_buffer_with_mime_type(file, "audio/aac"); - - let options = Options::builder() - .punctuate(false) - .diarize(true) - .model(deepgram::transcription::prerecorded::options::Model::CustomId( - "nova-2-meeting".to_string(), - )) - .build(); - - eprintln!("transcribing..."); - let response: deepgram::transcription::prerecorded::response::Response = dg_client - .transcription() - .make_prerecorded_request_builder(source, &options) - .query(&[("filler_words", "true")]) - .send() - .await - .unwrap() - .json() - .await - .unwrap(); - - // let response = dg_client.transcription().prerecorded(source, &options).await.unwrap(); - eprintln!("complete."); - // dbg!(&response); - - let transcript = &response.results.channels[0].alternatives[0].transcript; - println!("{}", transcript); - - let words = &response.results.channels[0].alternatives[0].words; - - for word in words.iter() { - TRANSCRIPT_FINAL.lock().unwrap().push(Some(Word::Prerecorded(word.clone()))); - } - }); - // samples is single-channel f32 little endian - // make into mp3 file - } - } - - if ui - .add_enabled( - !self.is_recording, - Button::new(if self.is_recording { "recording..." } else { "record" }), - ) - .clicked() - { - self.is_recording = true; - self.sessions.push(session::Session { start_ms: now_ms(), end_ms: i64::MAX }); - tokio::spawn(async { - println!("transcription starting..."); - - let dg = Deepgram::new(Setting::get("deepgram_api_key").value); - - let mut results = dg - .transcription() - .stream_request() - .stream(microphone_as_stream()) - .encoding("linear16".to_string()) - .sample_rate(44100) - .channels(1) - .start() - .await - .unwrap(); - - println!("transcription started"); - - while let Some(result) = results.next().await { - // println!("got: {:?}", result); - { - if let Ok(deepgram::transcription::live::StreamResponse::TranscriptResponse { - duration, - is_final, - channel: Channel { mut alternatives, .. }, - .. - }) = result - { - if !is_final { - *DURATION.lock().unwrap() += duration; - } - - if let Some(deepgram::transcription::live::Alternatives { words, .. }) = - alternatives.first_mut() - { - for word in words.iter() { - TRANSCRIPT.lock().unwrap().push(Some(word.clone())); - } - TRANSCRIPT.lock().unwrap().push(None); - - if is_final { - for word in words { - TRANSCRIPT_FINAL.lock().unwrap().push(Some(Word::Live(word.clone()))); - } - TRANSCRIPT_FINAL.lock().unwrap().push(None); - } - } - } - } - } - }); - } - - if ui.button("import audio file").clicked() { - tokio::spawn(async { - let file = rfd::AsyncFileDialog::new().pick_file().await.unwrap().read().await; - - let source = AudioSource::from_buffer_with_mime_type(file, "audio/aac"); - - let options = Options::builder() - .punctuate(false) - .diarize(true) - .model(deepgram::transcription::prerecorded::options::Model::CustomId( - "nova-2-meeting".to_string(), - )) - .build(); - - let dg_client = Deepgram::new(Setting::get("deepgram_api_key").value); - - eprintln!("transcribing..."); - let mut response = dg_client.transcription().prerecorded(source, &options).await.unwrap(); - eprintln!("complete."); - - TRANSCRIPT_FINAL.lock().unwrap().extend( - response.results.channels[0].alternatives[0] - .words - .drain(..) - .map(|w| Some(Word::Prerecorded(w))), - ); - }); - }; - - if ui.button("copy transcript to clipboard").clicked() { - ui.output_mut(|o| o.copied_text = self.get_transcript()); - }; - if ui.button("add window").clicked() { WHEEL_WINDOWS.lock().unwrap().push(Default::default()); }; @@ -552,7 +344,7 @@ impl eframe::App for App { }); } - ScrollArea::vertical().auto_shrink([false, false]).show(ui, |ui| { + ScrollArea::vertical().auto_shrink([false, false]).show(ui, |_ui| { // let size = [ui.available_width(), ui.spacing().interact_size.y.max(20.0)]; // for card in cards { // let i = card.rowid.unwrap(); @@ -561,31 +353,6 @@ impl eframe::App for App { // self.line_selected = i; // } // } - - let words = TRANSCRIPT.lock().unwrap(); - - let lines = words.split(|word| word.is_none()); - - for line in lines { - ui.horizontal_wrapped(|ui| { - for word in line { - if let Some(word) = word { - let color = match word.speaker { - 0 => Color32::RED, - 1 => Color32::GREEN, - 2 => Color32::BLUE, - 3 => Color32::YELLOW, - 4 => Color32::LIGHT_GRAY, - 5 => Color32::DARK_RED, - 6 => Color32::DARK_GREEN, - 7 => Color32::BLACK, - _ => Color32::WHITE, - }; - ui.label(egui::RichText::new(word.word.clone()).color(color).size(15.0)); - } - } - }); - } }); }); @@ -607,8 +374,7 @@ impl eframe::App for App { egui::Window::new(format!("wheel {}", i)).show(ctx, |ui| { ScrollArea::vertical().stick_to_bottom(true).auto_shrink([false, false]).show(ui, |ui| { if ui.button("copy all to clipboard").clicked() { - let mut text = self.get_transcript(); - text.push_str("\n"); + let mut text = "\n".to_string(); for entry in WHEEL_WINDOWS.lock().unwrap().get(i).unwrap().0.iter() { text.push_str(&format!("[{}]: {}\n", entry.role, entry.content)); @@ -714,12 +480,11 @@ impl eframe::App for App { messages.push(ChatMessage { role: User, content: String::new() }); ui.ctx().memory_mut(|m| m.request_focus(Id::new((i * 1000) + messages.len() - 1))); let id = messages.len() - 2; - let transcript = self.get_transcript(); let ctx_cloned = ctx.clone(); let (trigger, tripwire) = Tripwire::new(); self.trigger = Some(trigger); tokio::spawn(async move { - run_openai(GPT_4, tripwire, orig_messages, transcript, move |content| { + run_openai(GPT_4, tripwire, orig_messages, move |content| { WHEEL_WINDOWS .lock() .unwrap() @@ -740,43 +505,6 @@ impl eframe::App for App { }); } - egui::Window::new("Transcript").show(ctx, |ui| { - ScrollArea::vertical().stick_to_bottom(true).auto_shrink([false, false]).show(ui, |ui| { - let words = TRANSCRIPT_FINAL.lock().unwrap(); - - let lines = words.split(|word| word.is_none()); - - for line in lines { - let mut current_speaker = 100; - - ui.horizontal_wrapped(|ui| { - for word in line { - if let Some(word) = word { - if word.speaker() != current_speaker { - current_speaker = word.speaker(); - while current_speaker >= self.speaker_names.len() { - self.speaker_names.push(format!("{}", current_speaker)); - } - ui.end_row(); - ui.horizontal_wrapped(|ui| { - ui.label( - RichText::new(format!( - "[{}]: ", - self.speaker_names.get(current_speaker).unwrap_or(&String::new()) - )) - .size(30.0), - ); - }); - } - ui.label(RichText::new(word.word()).size(30.0)); - // ui.add(Label::new(RichText::new(word.word.clone()).color(color).size(30.0)).wrap(true)); - } - } - }); - } - }); - // ui.allocate_space(ui.available_size()); - }); CentralPanel::default().show(ctx, |_ui| {}); } } @@ -1043,7 +771,6 @@ pub(crate) async fn run_openai( model: &str, tripwire: Tripwire, messages: Vec, - transcript: String, callback: impl Fn(&String) + Send + 'static, ) -> Result<(), Box> { use async_openai::{types::CreateChatCompletionRequestArgs, Client}; @@ -1053,7 +780,7 @@ pub(crate) async fn run_openai( async_openai::config::OpenAIConfig::new().with_api_key(Setting::get("openai_api_key").value), ); - let mut messages = messages + let messages = messages .into_iter() .map(|m| match m.role { System => async_openai::types::ChatCompletionRequestSystemMessageArgs::default() @@ -1075,16 +802,16 @@ pub(crate) async fn run_openai( }) .collect::>(); - if !transcript.is_empty() { - messages.insert( - 0, - async_openai::types::ChatCompletionRequestUserMessageArgs::default() - .content(transcript) - .build() - .unwrap() - .into(), - ); - } + // if !transcript.is_empty() { + // messages.insert( + // 0, + // async_openai::types::ChatCompletionRequestUserMessageArgs::default() + // .content(transcript) + // .build() + // .unwrap() + // .into(), + // ); + // } // dbg!(&messages);