Skip to content

Commit 399cbeb

Browse files
authored
Merge pull request #62 from deepgram/synchronous-prerecorded
Adding new feature non-async prerecorded
2 parents 134ee8c + bb57b4d commit 399cbeb

File tree

3 files changed

+135
-2
lines changed

3 files changed

+135
-2
lines changed

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,28 @@ pip install deepgram-sdk
1919

2020
#### Transcribe an Existing File or Pre-recorded Audio
2121

22+
```python
23+
from deepgram import Deepgram
24+
import json
25+
26+
DEEPGRAM_API_KEY = 'YOUR_API_KEY'
27+
PATH_TO_FILE = 'some/file.wav'
28+
29+
def main():
30+
# Initializes the Deepgram SDK
31+
deepgram = Deepgram(DEEPGRAM_API_KEY)
32+
# Open the audio file
33+
with open(PATH_TO_FILE, 'rb') as audio:
34+
# ...or replace mimetype as appropriate
35+
source = {'buffer': audio, 'mimetype': 'audio/wav'}
36+
response = deepgram.transcription.sync_prerecorded(source, {'punctuate': True})
37+
print(json.dumps(response, indent=4))
38+
39+
main()
40+
```
41+
42+
#### Transcribe an Existing File or Pre-recorded Audio Asynchronously
43+
2244
```python
2345
from deepgram import Deepgram
2446
import asyncio, json

deepgram/_utils.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from typing import Any, Union, Optional, IO, Mapping, Tuple, List, cast
22
import aiohttp
33
import urllib.parse
4+
import urllib.request
5+
import urllib.error
46
import io
57
import json
68
import re
@@ -117,6 +119,48 @@ async def attempt():
117119
return await attempt()
118120

119121

122+
def _sync_request(
123+
path: str, options: Options,
124+
method: str = 'GET', payload: Payload = None,
125+
headers: Optional[Mapping[str, str]] = None
126+
) -> Any:
127+
if headers is None:
128+
headers = {}
129+
destination = cast(str, options.get('api_url', DEFAULT_ENDPOINT)) + path
130+
updated_headers = _prepare_headers(options, headers)
131+
132+
def attempt():
133+
req = urllib.request.Request(
134+
destination,
135+
data=_normalize_payload(payload),
136+
headers=updated_headers,
137+
method=method)
138+
try:
139+
with urllib.request.urlopen(req) as resp:
140+
content = resp.read().strip()
141+
if not content:
142+
return None
143+
body = json.loads(content)
144+
if body.get('error'):
145+
raise Exception(f'DG: {content}')
146+
return body
147+
except urllib.error.URLError as exc:
148+
raise (Exception(f'DG: {exc}') if exc.status < 500 else exc)
149+
150+
tries = RETRY_COUNT
151+
while tries > 0:
152+
try:
153+
return attempt()
154+
except urllib.error.URLError as exc:
155+
if isinstance(payload, io.IOBase):
156+
raise exc # stream is now invalid as payload
157+
# the way aiohttp handles streaming form data
158+
# means that just seeking this back still runs into issues
159+
tries -= 1
160+
continue
161+
return attempt()
162+
163+
120164
async def _socket_connect(
121165
path: str, options: Options, headers: Optional[Mapping[str, str]] = None
122166
) -> websockets.client.WebSocketClientProtocol:

deepgram/transcription.py

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
TranscriptionSource, PrerecordedTranscriptionResponse,
1010
LiveTranscriptionResponse, Metadata, EventHandler)
1111
from ._enums import LiveTranscriptionEvent
12-
from ._utils import _request, _make_query_string, _socket_connect
12+
from ._utils import _request, _sync_request, _make_query_string, _socket_connect
1313

1414

1515
class PrerecordedTranscription:
16-
"""This class provides an interface for doing transcription on prerecorded audio files."""
16+
"""This class provides an interface for doing transcription asynchronously on prerecorded audio files."""
1717

1818
_root = "/listen"
1919

@@ -63,6 +63,58 @@ async def __call__(
6363
)
6464

6565

66+
class SyncPrerecordedTranscription:
67+
"""This class provides an interface for doing transcription synchronously on prerecorded audio files."""
68+
69+
_root = "/listen"
70+
71+
def __init__(self, options: Options,
72+
transcription_options: PrerecordedOptions) -> None:
73+
"""
74+
This function initializes the options and transcription_options for the PrerecordedTranscription class.
75+
76+
:param options:Options: Used to Pass in the options for the transcription.
77+
:param transcription_options:PrerecordedOptions: Used to Specify the transcription options for a prerecorded audio file.
78+
:return: Nothing.
79+
80+
"""
81+
82+
self.options = options
83+
self.transcription_options = transcription_options
84+
85+
def __call__(
86+
self, source: TranscriptionSource
87+
) -> PrerecordedTranscriptionResponse:
88+
89+
"""
90+
The __call__ function is a special method that allows the class to be called
91+
as a function. This is useful for creating instances of the class, where we can
92+
call `SyncPrerecordedTranscription()` and pass in arguments to set up an instance of
93+
the class. For example:
94+
95+
sync_prerecorded_transcription = SyncPrerecordedTranscription(...)
96+
97+
:param source:TranscriptionSource: Used to Pass in the audio file.
98+
:return: A `prerecordedtranscriptionresponse` object, which contains the transcription results.
99+
100+
"""
101+
102+
if 'buffer' in source and 'mimetype' not in source:
103+
raise Exception(
104+
'DG: Mimetype must be provided if the source is bytes'
105+
)
106+
payload = cast(
107+
Union[bytes, Dict],
108+
source.get('buffer', {'url': source.get('url')})
109+
)
110+
content_type = cast(str, source.get('mimetype', 'application/json'))
111+
return _sync_request(
112+
f'{self._root}{_make_query_string(self.transcription_options)}',
113+
self.options, method='POST', payload=payload,
114+
headers={'Content-Type': content_type}
115+
)
116+
117+
66118
class LiveTranscription:
67119
"""
68120
This class allows you to perform live transcription by connecting to Deepgram's Transcribe Streaming API.
@@ -283,6 +335,21 @@ async def prerecorded(
283335
self.options, full_options
284336
)(source)
285337

338+
339+
def sync_prerecorded(
340+
self, source: TranscriptionSource,
341+
options: PrerecordedOptions = None, **kwargs
342+
) -> PrerecordedTranscriptionResponse:
343+
"""Retrieves a transcription for an already-existing audio file,
344+
local or web-hosted."""
345+
if options is None:
346+
options = {}
347+
full_options = cast(PrerecordedOptions, {**options, **kwargs})
348+
return SyncPrerecordedTranscription(
349+
self.options, full_options
350+
)(source)
351+
352+
286353
async def live(
287354
self, options: LiveOptions = None, **kwargs
288355
) -> LiveTranscription:

0 commit comments

Comments
 (0)