## Supported Audio Formats
The MacTTS service produces audio streams using WAV containers and PCM (signed) codec with 16bit depth and 44.1kHz frequency.
+
+## Caching
+
+The macOS TTS service uses the openHAB TTS cache to cache audio files produced from the most recent queries in order to reduce traffic, improve performance and reduce number of requests.
import org.openhab.core.audio.AudioFormat;
import org.openhab.core.audio.AudioStream;
import org.openhab.core.audio.FixedLengthAudioStream;
+import org.openhab.core.common.Disposable;
import org.openhab.core.voice.Voice;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
*
* @author Kelly Davis - Initial contribution and API
* @author Kai Kreuzer - Refactored to use AudioStream and fixed audio format to produce
+ * @author Laurent Garnier - Add dispose method to delete the temporary file
*/
-class MacTTSAudioStream extends FixedLengthAudioStream {
+class MacTTSAudioStream extends FixedLengthAudioStream implements Disposable {
private final Logger logger = LoggerFactory.getLogger(MacTTSAudioStream.class);
throw new AudioException("No temporary audio file available.");
}
}
+
+ @Override
+ public void dispose() throws IOException {
+ if (file != null && file.exists()) {
+ try {
+ if (!file.delete()) {
+ logger.warn("Failed to delete the file {}", file.getAbsolutePath());
+ }
+ } catch (SecurityException e) {
+ logger.warn("Failed to delete the file {}: {}", file.getAbsolutePath(), e.getMessage());
+ }
+ }
+ }
}
import org.openhab.core.audio.AudioException;
import org.openhab.core.audio.AudioFormat;
import org.openhab.core.audio.AudioStream;
+import org.openhab.core.voice.AbstractCachedTTSService;
+import org.openhab.core.voice.TTSCache;
import org.openhab.core.voice.TTSException;
import org.openhab.core.voice.TTSService;
import org.openhab.core.voice.Voice;
+import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* @author Kai Kreuzer - Initial contribution and API
* @author Pauli Antilla
* @author Kelly Davis
+ * @author Laurent Garnier : Implement TTS LRU cache
*/
-@Component
+@Component(service = TTSService.class)
@NonNullByDefault
-public class MacTTSService implements TTSService {
+public class MacTTSService extends AbstractCachedTTSService {
private final Logger logger = LoggerFactory.getLogger(MacTTSService.class);
+ @Activate
+ public MacTTSService(final @Reference TTSCache ttsCache) {
+ super(ttsCache);
+ }
+
/**
* Set of supported voices
*/
}
@Override
- public AudioStream synthesize(String text, Voice voice, AudioFormat requestedFormat) throws TTSException {
+ public AudioStream synthesizeForCache(String text, Voice voice, AudioFormat requestedFormat) throws TTSException {
// Validate arguments
if (text.isEmpty()) {
throw new TTSException("The passed text is null or empty");
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Set;
import org.junit.jupiter.api.Test;
import org.openhab.core.audio.AudioFormat;
import org.openhab.core.audio.AudioStream;
+import org.openhab.core.storage.StorageService;
import org.openhab.core.voice.TTSException;
import org.openhab.core.voice.Voice;
+import org.openhab.core.voice.internal.cache.TTSLRUCacheImpl;
/**
* Test TTSServiceMacOS
*/
public class TTSServiceMacOSTest {
+ private StorageService storageService;
+
/**
* Test TTSServiceMacOS.getAvailableVoices()
*/
public void getAvailableVoicesTest() {
assumeTrue("Mac OS X".equals(System.getProperty("os.name")));
- MacTTSService ttsServiceMacOS = new MacTTSService();
+ Map<String, Object> config = new HashMap<>();
+ config.put("enableCacheTTS", false);
+ TTSLRUCacheImpl voiceLRUCache = new TTSLRUCacheImpl(storageService, config);
+ MacTTSService ttsServiceMacOS = new MacTTSService(voiceLRUCache);
assertFalse(ttsServiceMacOS.getAvailableVoices().isEmpty());
}
public void getSupportedFormatsTest() {
assumeTrue("Mac OS X".equals(System.getProperty("os.name")));
- MacTTSService ttsServiceMacOS = new MacTTSService();
+ Map<String, Object> config = new HashMap<>();
+ config.put("enableCacheTTS", false);
+ TTSLRUCacheImpl voiceLRUCache = new TTSLRUCacheImpl(storageService, config);
+ MacTTSService ttsServiceMacOS = new MacTTSService(voiceLRUCache);
assertFalse(ttsServiceMacOS.getSupportedFormats().isEmpty());
}
public void synthesizeTest() throws IOException, TTSException {
assumeTrue("Mac OS X".equals(System.getProperty("os.name")));
- MacTTSService ttsServiceMacOS = new MacTTSService();
+ Map<String, Object> config = new HashMap<>();
+ config.put("enableCacheTTS", false);
+ TTSLRUCacheImpl voiceLRUCache = new TTSLRUCacheImpl(storageService, config);
+ MacTTSService ttsServiceMacOS = new MacTTSService(voiceLRUCache);
Set<Voice> voices = ttsServiceMacOS.getAvailableVoices();
Set<AudioFormat> audioFormats = ttsServiceMacOS.getSupportedFormats();
try (AudioStream audioStream = ttsServiceMacOS.synthesize("Hello", voices.iterator().next(),