diff --git a/assemblyai/_audio.py b/assemblyai/_audio.py index e0bab83..3756ac9 100644 --- a/assemblyai/_audio.py +++ b/assemblyai/_audio.py @@ -90,7 +90,9 @@ def _resolve_audio( elif hasattr(data, "read"): audio = data.read() name = getattr(data, "name", None) - if name: + # `name` is a file descriptor (an int) for anonymous files such as + # `tempfile.TemporaryFile()`, so only a str is a usable path. + if isinstance(name, str) and name: filename = os.path.basename(name) suffix = os.path.splitext(name)[1].lower() else: diff --git a/tests/unit/test_sync.py b/tests/unit/test_sync.py index 054101c..9aac646 100644 --- a/tests/unit/test_sync.py +++ b/tests/unit/test_sync.py @@ -1,3 +1,5 @@ +import tempfile + import httpx import pytest from pytest_httpx import HTTPXMock @@ -316,6 +318,24 @@ def test_transcribe_path_input(httpx_mock: HTTPXMock, tmp_path): assert b'filename="call.wav"' in body +def test_transcribe_file_object_without_a_path_name(httpx_mock: HTTPXMock): + # Given an anonymous temporary file, whose `name` is a file descriptor + # rather than a path + _mock_ok(httpx_mock) + with tempfile.TemporaryFile() as audio_file: + audio_file.write(b"RIFFfake-wav-bytes") + audio_file.seek(0) + + # When transcribing the file object + result = aai.SyncTranscriber().transcribe(audio_file) + + # Then it succeeds and ships the audio under the default name + assert result.text == "hello world" + body = httpx_mock.get_requests()[0].read() + assert b'filename="audio.wav"' in body + assert b"RIFFfake-wav-bytes" in body + + def test_keyterms_prompt_too_long_raises(): # Given a keyterms_prompt exceeding the character cap # When building the config, Then validation fails immediately