Last active
January 23, 2024 11:15
-
-
Save xiprox/118fe3042e333fa2b022a7e09d4ebe5f to your computer and use it in GitHub Desktop.
OpenAI TTS chunked transfer streaming dart (not working on web)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:convert'; | |
import 'package:universal_io/io.dart'; | |
import 'package:http/http.dart' as http; | |
import 'dart:typed_data'; | |
const _kOpenAiApiKey = 'sk-QDU...'; | |
abstract interface class OpenAiApi { | |
Future<Uint8List> textToSpeech( | |
String text, { | |
String? voice, | |
double? speed, | |
}); | |
Future<Stream<List<int>>> textToSpeechStream( | |
String text, { | |
String? voice, | |
double? speed, | |
}); | |
} | |
class OpenAiApiImpl implements OpenAiApi { | |
@override | |
Future<Uint8List> textToSpeech( | |
String text, { | |
String? voice, | |
double? speed, | |
}) async { | |
try { | |
final response = await http.post( | |
Uri.parse('https://api.openai.com/v1/audio/speech'), | |
headers: { | |
'Authorization': 'Bearer $_kOpenAiApiKey', | |
HttpHeaders.contentTypeHeader: 'application/json', | |
}, | |
body: json.encode({ | |
'model': 'tts-1', | |
'voice': voice ?? 'nova', | |
'input': text, | |
'speed': speed?.toString() ?? '1', | |
}), | |
); | |
if (response.statusCode != 200) { | |
throw Exception( | |
'Error generating speech: ' | |
'${response.statusCode} - ${response.reasonPhrase} \n ' | |
'${response.body}', | |
); | |
} else { | |
logger.i('Audio generated successfully'); | |
return response.bodyBytes; | |
} | |
} catch (e, s) { | |
logger.e(e); | |
logger.e(s); | |
} | |
return Uint8List(0); | |
} | |
@override | |
Future<Stream<List<int>>> textToSpeechStream( | |
String text, { | |
String? voice, | |
double? speed, | |
}) async { | |
try { | |
final request = http.Request( | |
'POST', | |
Uri.parse('https://api.openai.com/v1/audio/speech'), | |
); | |
request.headers.addAll({ | |
'Authorization': 'Bearer $_kOpenAiApiKey', | |
// HttpHeaders.transferEncodingHeader: 'chunked', | |
HttpHeaders.contentTypeHeader: 'application/json', | |
}); | |
request.body = json.encode({ | |
'model': 'tts-1', | |
'voice': voice ?? 'nova', | |
'input': text, | |
'speed': speed?.toString() ?? '1', | |
}); | |
final streamedResponse = await request.send(); | |
if (streamedResponse.statusCode != 200) { | |
final response = await http.Response.fromStream(streamedResponse); | |
throw Exception( | |
'Error generating speech: ' | |
'${response.statusCode} - ${response.reasonPhrase} \n ' | |
'${response.body}', | |
); | |
} else { | |
logger.i('Audio generated successfully'); | |
return streamedResponse.stream.asBroadcastStream(); | |
} | |
} catch (e, s) { | |
logger.e(e); | |
logger.e(s); | |
} | |
return const Stream.empty(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment