react-native-deepgram
Version:
React Native SDK for Deepgram's AI-powered speech-to-text, real-time transcription, and text intelligence APIs. Supports live audio streaming, file transcription, sentiment analysis, and topic detection for iOS and Android.
144 lines (128 loc) • 3.62 kB
text/typescript
import { useRef, useCallback, useEffect, useState } from 'react';
import type {
UseDeepgramTextIntelligenceProps,
UseDeepgramTextIntelligenceReturn,
DeepgramTextIntelligenceInput,
} from './types';
import { DEEPGRAM_BASEURL } from './constants';
import { buildParams } from './helpers';
export function useDeepgramTextIntelligence({
onBeforeAnalyze = () => {},
onAnalyzeSuccess = () => {},
onAnalyzeError = () => {},
options = {},
trackState = false,
}: UseDeepgramTextIntelligenceProps = {}): UseDeepgramTextIntelligenceReturn {
const [internalState, setInternalState] = useState<{
status: 'idle' | 'loading' | 'analyzing' | 'error';
error: Error | null;
}>({
status: 'idle',
error: null,
});
const abortCtrl = useRef<AbortController | null>(null);
const {
summarize,
topics,
customTopic,
customTopicMode,
intents,
customIntent,
customIntentMode,
sentiment,
language,
callback,
callbackMethod,
} = options;
const analyze = useCallback(
async (input: DeepgramTextIntelligenceInput) => {
onBeforeAnalyze();
if (trackState) {
setInternalState({ status: 'analyzing', error: null });
}
try {
const apiKey = (globalThis as any).__DEEPGRAM_API_KEY__;
if (!apiKey) throw new Error('Deepgram API key missing');
const { text, url: sourceUrl } = input;
if (!text && !sourceUrl) {
throw new Error(
'Either `text` or `url` is required to analyze content.'
);
}
const paramMap = {
summarize,
topics,
intents,
sentiment,
language,
custom_topic: customTopic,
custom_topic_mode: customTopicMode,
custom_intent: customIntent,
custom_intent_mode: customIntentMode,
callback,
callback_method: callbackMethod,
};
const params = buildParams(paramMap);
const url = `${DEEPGRAM_BASEURL}/read${params ? `?${params}` : ''}`;
abortCtrl.current?.abort();
abortCtrl.current = new AbortController();
const res = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Token ${apiKey}`,
},
body: JSON.stringify({
...(text ? { text } : {}),
...(sourceUrl ? { url: sourceUrl } : {}),
}),
signal: abortCtrl.current.signal,
});
if (!res.ok) {
const errText = await res.text();
throw new Error(`HTTP ${res.status}: ${errText}`);
}
const json = await res.json();
onAnalyzeSuccess(json);
if (trackState) {
setInternalState({ status: 'idle', error: null });
}
} catch (err: any) {
if (err.name === 'AbortError') return;
onAnalyzeError(err);
if (trackState) {
setInternalState({
status: 'error',
error: err instanceof Error ? err : new Error(String(err)),
});
}
}
},
[
onBeforeAnalyze,
onAnalyzeSuccess,
onAnalyzeError,
summarize,
topics,
customTopic,
customTopicMode,
intents,
customIntent,
customIntentMode,
sentiment,
language,
callback,
callbackMethod,
trackState,
]
);
useEffect(() => {
return () => {
abortCtrl.current?.abort();
};
}, []);
return {
analyze,
...(trackState ? { state: internalState } : {}),
};
}