Skip to content

Commit

Permalink
Apple nsss writes .aiff, not .wav files
Browse files Browse the repository at this point in the history
  • Loading branch information
cclauss committed Nov 7, 2024
1 parent d212b16 commit 54626c7
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 9 deletions.
7 changes: 5 additions & 2 deletions pyttsx3/drivers/nsss.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# noinspection PyUnresolvedReferences
import objc
from AppKit import NSSpeechSynthesizer
from Foundation import *
from Foundation import NSURL, NSDate, NSDefaultRunLoopMode, NSObject, NSRunLoop, NSTimer
from PyObjCTools import AppHelper

# noinspection PyProtectedMember
Expand Down Expand Up @@ -150,10 +150,13 @@ def setProperty(self, name, value):

@objc.python_method
def save_to_file(self, text, filename):
"""
Apple writes .aiff, not .wav. https://github.com/nateshmbhat/pyttsx3/issues/361
"""
self._proxy.setBusy(True)
self._completed = True
self._current_text = text
url = Foundation.NSURL.fileURLWithPath_(filename)
url = NSURL.fileURLWithPath_(filename)
self._tts.startSpeakingString_toURL_(text, url)

def speechSynthesizer_didFinishSpeaking_(self, tts, success):
Expand Down
21 changes: 14 additions & 7 deletions tests/test_pyttsx3.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ def test_speaking_text(engine):
engine.runAndWait()


@pytest.mark.xfail(
sys.platform == "darwin", reason="TODO: Fix this test to pass on macOS"
)
def test_saving_to_file(engine, tmp_path):
"""
Apple writes .aiff, not .wav. https://github.com/nateshmbhat/pyttsx3/issues/361
"""
test_file = tmp_path / "test.wav" # Using .wav for easier validation

# Save the speech to a file
Expand All @@ -53,10 +53,17 @@ def test_saving_to_file(engine, tmp_path):
assert test_file.stat().st_size > 0, "The audio file is empty"

# Check if the file is a valid .wav file using the wave module
with wave.open(str(test_file), "rb") as wf:
assert wf.getnchannels() == 1, "The audio file should have 1 channel (mono)"
assert wf.getsampwidth() == 2, "The audio file sample width should be 2 bytes"
assert wf.getframerate() == 22050, "The audio file framerate should be 22050 Hz"
try:
with wave.open(str(test_file), "rb") as wf:
assert wf.getnchannels() == 1, "The audio file should have 1 channel (mono)"
assert (
wf.getsampwidth() == 2
), "The audio file sample width should be 2 bytes"
assert (
wf.getframerate() == 22050
), "The audio file framerate should be 22050 Hz"
except wave.Error:
assert sys.platform in {"darwin", "ios"}, "Apple writes .aiff, not .wav files."


@pytest.mark.skipif(
Expand Down

0 comments on commit 54626c7

Please sign in to comment.