Skip to content

Commit 3d5ab9e

Browse files
committed
feat: adding silentMode for ios
1 parent ea97783 commit 3d5ab9e

3 files changed

Lines changed: 38 additions & 6 deletions

File tree

example/src/views/RootView.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ const RootView: React.FC = () => {
2222
>([]);
2323

2424
React.useEffect(() => {
25+
// Speech.initialize({silentMode: 'ignore'});
26+
2527
const onSpeechEnd = () => {
2628
setIsStarted(false);
2729
setIsPaused(false);

ios/Speech.mm

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ - (instancetype)init {
2323
defaultOptions = @{
2424
@"pitch": @(1.0),
2525
@"volume": @(1.0),
26+
@"silentMode": @"obey",
2627
@"rate": @(AVSpeechUtteranceDefaultSpeechRate),
2728
@"language": [AVSpeechSynthesisVoice currentLanguageCode] ?: @"en-US"
2829
};
@@ -32,6 +33,20 @@ - (instancetype)init {
3233
return self;
3334
}
3435

36+
- (void)configureAudioSessionWithOptions:(NSDictionary *)options {
37+
NSError *error = nil;
38+
NSString *silentMode = options[@"silentMode"] ?: @"obey";
39+
40+
if ([silentMode isEqualToString:@"ignore"]) {
41+
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
42+
} else if ([silentMode isEqualToString:@"respect"]) {
43+
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&error];
44+
}
45+
if (error) {
46+
NSLog(@"[Speech] AVAudioSession setCategory error: %@", error.localizedDescription);
47+
}
48+
}
49+
3550
- (NSDictionary *)getEventData:(AVSpeechUtterance *)utterance {
3651
return @{
3752
@"id": @(utterance.hash)
@@ -56,6 +71,9 @@ - (NSDictionary *)getValidatedOptions:(VoiceOptions &)options {
5671
if (options.language()) {
5772
validatedOptions[@"language"] = options.language();
5873
}
74+
if (options.silentMode()) {
75+
validatedOptions[@"silentMode"] = options.silentMode();
76+
}
5977
if (options.pitch()) {
6078
float pitch = MAX(0.5, MIN(2.0, options.pitch().value()));
6179
validatedOptions[@"pitch"] = @(pitch);
@@ -105,7 +123,7 @@ - (void)reset {
105123

106124
- (void)getAvailableVoices:(NSString *)language
107125
resolve:(RCTPromiseResolveBlock)resolve
108-
reject:(RCTPromiseRejectBlock)reject
126+
reject:(RCTPromiseRejectBlock)reject
109127
{
110128
NSMutableArray *voicesArray = [NSMutableArray new];
111129
NSArray *speechVoices = [AVSpeechSynthesisVoice speechVoices];
@@ -170,6 +188,8 @@ - (void)speak:(NSString *)text
170188
AVSpeechUtterance *utterance;
171189

172190
@try {
191+
[self configureAudioSessionWithOptions:self.globalOptions];
192+
173193
utterance = [self getDefaultUtterance:text];
174194
[self.synthesizer speakUtterance:utterance];
175195
resolve(nil);
@@ -193,17 +213,18 @@ - (void)speakWithOptions:(NSString *)text
193213
AVSpeechUtterance *utterance;
194214

195215
@try {
196-
utterance = [self getDefaultUtterance:text];
197216
NSDictionary *validatedOptions = [self getValidatedOptions:options];
217+
[self configureAudioSessionWithOptions:validatedOptions];
218+
219+
utterance = [self getDefaultUtterance:text];
198220

199221
if (validatedOptions[@"voice"]) {
200222
AVSpeechSynthesisVoice *voice = [AVSpeechSynthesisVoice voiceWithIdentifier:validatedOptions[@"voice"]];
201-
202223
if (voice) {
203224
utterance.voice = voice;
204-
} else if (validatedOptions[@"language"]) {
205-
utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:validatedOptions[@"language"]];
206225
}
226+
} else if (validatedOptions[@"language"]) {
227+
utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:validatedOptions[@"language"]];
207228
}
208229
if (validatedOptions[@"pitch"]) {
209230
utterance.pitchMultiplier = [validatedOptions[@"pitch"] floatValue];
@@ -224,7 +245,7 @@ - (void)speakWithOptions:(NSString *)text
224245
}
225246
}
226247

227-
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer
248+
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer
228249
didStartSpeechUtterance:(AVSpeechUtterance *)utterance {
229250
[self emitOnStart:[self getEventData:utterance]];
230251
}

src/NativeSpeech.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ export interface VoiceProps {
3030
identifier: string;
3131
}
3232
export interface VoiceOptions {
33+
/**
34+
* Determines how speech audio should behave with the iOS silent switch (ringer)
35+
* @platform ios
36+
*
37+
* - `obey`: (Default) The library does not change the app's audio session. Speech audio will follow the app's current audio configuration or the system default
38+
* - `respect`: Speech audio will be silenced by the ringer switch. This is for non-critical speech
39+
* - `ignore`: Speech audio will play even if the ringer switch is on silent. Use this for critical speech like navigation
40+
*/
41+
silentMode?: 'obey' | 'respect' | 'ignore';
3342
/** The language code to use (e.g., 'en', 'fr', 'en-US', 'fr-FR') */
3443
language?: string;
3544
/** Volume level from 0.0 to 1.0 */

0 commit comments

Comments
 (0)