#include "deepgram_client.h" #include // Returns string that caller must free static char *dg_find_transcript(char *json_response) { printf("Parsing response: %s \n", json_response); char *start = strstr(json_response, "\"transcript\":\""); if (!start) return NULL; start += 14; // Skip past "transcript":" char *end = strchr(start, '"'); // Find closing quote // Copy substring between start and end size_t len = end - start; char *result = malloc(len + 1); strncpy(result, start, len); result[len] = '\0'; return result; } char *dg_transcribe(FILE *audio_file) { CURL *curl; CURLcode res; struct curl_slist *headers = NULL; // Initialize response buffer struct curl_response_data response = {0}; response.data = malloc(1); response.size = 0; // Get file size fseek(audio_file, 0, SEEK_END); long file_size = ftell(audio_file); fseek(audio_file, 0, SEEK_SET); struct curl_file_data data; data.file = audio_file; data.size = file_size; curl = curl_easy_init(); if (curl) { // Set headers for Deepgram API char *deepgram_api_key = getenv("DEEPGRAM_API_KEY"); if (!deepgram_api_key) { fprintf(stderr, "DEEPGRAM_API_KEY environment variable not set\n"); free(response.data); curl_easy_cleanup(curl); return NULL; } char auth_header[256]; snprintf(auth_header, sizeof(auth_header), "Authorization: Token %s", deepgram_api_key); headers = curl_slist_append(headers, auth_header); curl_easy_setopt(curl, CURLOPT_URL, "https://api.deepgram.com/v1/" "listen?encoding=linear16&sample_rate=48000&channels=1"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_POST, 1L); curl_easy_setopt(curl, CURLOPT_READFUNCTION, curl_read_callback_file); curl_easy_setopt(curl, CURLOPT_READDATA, &data); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, file_size); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_callback_response); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); res = curl_easy_perform(curl); if (res != CURLE_OK) { fprintf(stderr, "curl failed: %s\n", curl_easy_strerror(res)); free(response.data); curl_slist_free_all(headers); curl_easy_cleanup(curl); return NULL; } printf("done performing curl\n"); curl_slist_free_all(headers); curl_easy_cleanup(curl); } // Parse transcript from complete response char *transcript = dg_find_transcript(response.data); free(response.data); return transcript; } struct curl_response_data *dg_text_to_speech(char *text) { CURL *curl; CURLcode res; struct curl_slist *headers = NULL; // Create JSON payload - need to escape the text properly // Worst case: every char needs escaping, so allocate 2x + overhead size_t text_len = strlen(text); size_t payload_size = text_len * 2 + 100; char *json_payload = malloc(payload_size); // Simple approach: replace problematic chars with spaces char *escaped_text = malloc(text_len + 1); strcpy(escaped_text, text); for (int i = 0; escaped_text[i]; i++) { if (escaped_text[i] == '"' || escaped_text[i] == '\n' || escaped_text[i] == '\r' || escaped_text[i] == '\t') { escaped_text[i] = ' '; } } snprintf(json_payload, payload_size, "{" "\"text\":\"%s\"" "}", escaped_text); free(escaped_text); // Initialize response buffer struct curl_response_data *response = malloc(sizeof(struct curl_response_data)); response->data = malloc(1); response->size = 0; curl = curl_easy_init(); if (curl) { char *deepgram_api_key = getenv("DEEPGRAM_API_KEY"); if (!deepgram_api_key) { fprintf(stderr, "DEEPGRAM_API_KEY environment variable not set\n"); free(response->data); curl_easy_cleanup(curl); return NULL; } char auth_header[256]; snprintf(auth_header, sizeof(auth_header), "Authorization: Token %s", deepgram_api_key); headers = curl_slist_append(headers, auth_header); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, "https://api.deepgram.com/v1/" "speak?encoding=linear16&sample_rate=48000"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_POST, 1L); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_payload); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_callback_response); curl_easy_setopt(curl, CURLOPT_WRITEDATA, response); res = curl_easy_perform(curl); if (res != CURLE_OK) { fprintf(stderr, "curl failed: %s\n", curl_easy_strerror(res)); free(response->data); free(response); curl_slist_free_all(headers); curl_easy_cleanup(curl); return NULL; } curl_slist_free_all(headers); curl_easy_cleanup(curl); } printf("received audio of %d length for tts\n", (int)response->size); // Debug: print first 100 chars to see if it's audio or error message printf("First 100 chars: %.100s\n", response->data); free(json_payload); return response; }