2022-09-16 14:34:26 -04:00
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
# include <aws/core/Aws.h>
# include <aws/core/utils/threading/Semaphore.h>
# include <aws/core/auth/AWSCredentialsProviderChain.h>
# include <aws/transcribestreaming/TranscribeStreamingServiceClient.h>
# include <aws/transcribestreaming/model/StartStreamTranscriptionHandler.h>
# include <aws/transcribestreaming/model/StartStreamTranscriptionRequest.h>
# include <aws/core/platform/FileSystem.h>
# include <fstream>
# include <chrono>
# include <thread>
# include <array>
using namespace Aws ;
using namespace Aws : : TranscribeStreamingService ;
using namespace Aws : : TranscribeStreamingService : : Model ;
2022-09-19 15:49:59 -04:00
//TODO(User): Update path to location of local .wav test file, if necessary.
2022-09-22 15:17:12 -04:00
static const Aws : : String FILE_NAME { MEDIA_DIR " /transcribe-test-file.wav " } ;
2024-02-05 06:56:57 -08:00
static const int SAMPLE_RATE = 8000 ; // for the file above
// If you're able to specify chunk size with your audio type (such as with PCM), set each chunk to between 50 ms and 200 ms
static const int CHUNK_LENGTH = 125 ;
// chunk_size_in_bytes = chunk_duration_in_millisecond / 1000 * audio_sample_rate * 2
static const int BUFFER_SIZE = CHUNK_LENGTH * SAMPLE_RATE / 1000 * 2 ;
2022-09-16 14:34:26 -04:00
// snippet-start:[transcribe.cpp.stream_transcription_async.code]
2022-09-22 15:17:12 -04:00
int main ( ) {
Aws : : SDKOptions options ;
2024-03-13 17:26:57 -04:00
2022-09-22 15:17:12 -04:00
Aws : : InitAPI ( options ) ;
{
//TODO(User): Set to the region of your AWS account.
const Aws : : String region = Aws : : Region : : US_WEST_2 ;
2022-09-16 14:34:26 -04:00
2022-09-22 15:17:12 -04:00
//Load a profile that has been granted AmazonTranscribeFullAccess AWS managed permission policy.
Aws : : Client : : ClientConfiguration config ;
2022-09-16 14:34:26 -04:00
# ifdef _WIN32
2023-08-21 11:51:15 -04:00
// ATTENTION: On Windows with the AWS C++ SDK, this example only runs if the SDK is built
// with the curl library.
2022-09-23 16:15:07 -04:00
// For more information, see the accompanying ReadMe.
// For more information, see "Building the SDK for Windows with curl".
2022-09-22 15:17:12 -04:00
// https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/setup-windows.html
2022-09-23 16:15:07 -04:00
//TODO(User): Update to the location of your .crt file.
2022-09-22 15:17:12 -04:00
config . caFile = " C:/curl/bin/curl-ca-bundle.crt " ;
2022-09-16 14:34:26 -04:00
# endif
2022-09-22 15:17:12 -04:00
config . region = region ;
2022-09-16 14:34:26 -04:00
2022-09-22 15:17:12 -04:00
TranscribeStreamingServiceClient client ( config ) ;
StartStreamTranscriptionHandler handler ;
handler . SetOnErrorCallback (
[ ] ( const Aws : : Client : : AWSError < TranscribeStreamingServiceErrors > & error ) {
std : : cerr < < " ERROR: " + error . GetMessage ( ) < < std : : endl ;
} ) ;
//SetTranscriptEventCallback called for every 'chunk' of file transcripted.
// Partial results are returned in real time.
2024-02-05 06:56:57 -08:00
handler . SetTranscriptEventCallback ( [ ] ( const TranscriptEvent & ev ) {
2022-09-22 15:17:12 -04:00
for ( auto & & r : ev . GetTranscript ( ) . GetResults ( ) ) {
if ( r . GetIsPartial ( ) ) {
std : : cout < < " [partial] " ;
}
else {
std : : cout < < " [Final] " ;
}
for ( auto & & alt : r . GetAlternatives ( ) ) {
std : : cout < < alt . GetTranscript ( ) < < std : : endl ;
}
}
} ) ;
2022-09-16 14:34:26 -04:00
2022-09-22 15:17:12 -04:00
StartStreamTranscriptionRequest request ;
2024-02-05 06:56:57 -08:00
request . SetMediaSampleRateHertz ( SAMPLE_RATE ) ;
2022-09-22 15:17:12 -04:00
request . SetLanguageCode ( LanguageCode : : en_US ) ;
request . SetMediaEncoding (
2022-09-23 16:15:07 -04:00
MediaEncoding : : pcm ) ; // wav and aiff files are PCM formats.
2022-09-22 15:17:12 -04:00
request . SetEventStreamHandler ( handler ) ;
2022-09-16 14:34:26 -04:00
2024-02-05 06:56:57 -08:00
auto OnStreamReady = [ ] ( AudioStream & stream ) {
2022-09-22 15:17:12 -04:00
Aws : : FStream file ( FILE_NAME , std : : ios_base : : in | std : : ios_base : : binary ) ;
if ( ! file . is_open ( ) ) {
std : : cerr < < " Failed to open " < < FILE_NAME < < ' \n ' ;
}
std : : array < char , BUFFER_SIZE > buf ;
int i = 0 ;
while ( file ) {
file . read ( & buf [ 0 ] , buf . size ( ) ) ;
2022-09-16 14:34:26 -04:00
2022-09-22 15:17:12 -04:00
if ( ! file )
std : : cout < < " File: only " < < file . gcount ( ) < < " could be read "
< < std : : endl ;
2022-09-16 14:34:26 -04:00
2022-09-22 15:17:12 -04:00
Aws : : Vector < unsigned char > bits { buf . begin ( ) , buf . end ( ) } ;
AudioEvent event ( std : : move ( bits ) ) ;
if ( ! stream ) {
std : : cerr < < " Failed to create a stream " < < std : : endl ;
break ;
}
//The std::basic_istream::gcount() is used to count the characters in the given string. It returns
//the number of characters extracted by the last read() operation.
if ( file . gcount ( ) > 0 ) {
if ( ! stream . WriteAudioEvent ( event ) ) {
std : : cerr < < " Failed to write an audio event " < < std : : endl ;
break ;
}
}
else {
break ;
}
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds (
2022-09-23 16:15:07 -04:00
25 ) ) ; // Slow down because we are streaming from a file.
2022-09-22 15:17:12 -04:00
}
if ( ! stream . WriteAudioEvent (
AudioEvent ( ) ) ) {
2022-09-23 16:15:07 -04:00
// Per the spec, we have to send an empty event (an event without a payload) at the end.
2022-09-22 15:17:12 -04:00
std : : cerr < < " Failed to send an empty frame " < < std : : endl ;
}
else {
std : : cout < < " Successfully sent the empty frame " < < std : : endl ;
}
stream . flush ( ) ;
stream . Close ( ) ;
2024-02-05 06:56:57 -08:00
} ;
2022-09-16 14:34:26 -04:00
2022-09-22 15:17:12 -04:00
Aws : : Utils : : Threading : : Semaphore signaling ( 0 /*initialCount*/ , 1 /*maxCount*/ ) ;
2024-02-05 06:56:57 -08:00
auto OnResponseCallback = [ & signaling ] (
2022-09-22 15:17:12 -04:00
const TranscribeStreamingServiceClient * /*unused*/ ,
const Model : : StartStreamTranscriptionRequest & /*unused*/ ,
2024-02-05 06:56:57 -08:00
const Model : : StartStreamTranscriptionOutcome & outcome ,
2022-09-22 15:17:12 -04:00
const std : : shared_ptr < const Aws : : Client : : AsyncCallerContext > & /*unused*/ ) {
2022-11-11 13:54:33 -05:00
2024-02-05 06:56:57 -08:00
if ( ! outcome . IsSuccess ( ) ) {
std : : cerr < < " Transcribe streaming error "
< < outcome . GetError ( ) . GetMessage ( ) < < std : : endl ;
}
2022-11-11 13:54:33 -05:00
2024-02-05 06:56:57 -08:00
signaling . Release ( ) ;
2022-09-22 15:17:12 -04:00
} ;
2022-09-16 14:34:26 -04:00
std : : cout < < " Starting... " < < std : : endl ;
2022-09-22 15:17:12 -04:00
client . StartStreamTranscriptionAsync ( request , OnStreamReady , OnResponseCallback ,
nullptr /*context*/ ) ;
signaling . WaitOne ( ) ; // Prevent the application from exiting until we're done.
2022-09-16 14:34:26 -04:00
std : : cout < < " Done " < < std : : endl ;
2022-09-22 15:17:12 -04:00
}
2022-09-16 14:34:26 -04:00
2022-09-22 15:17:12 -04:00
Aws : : ShutdownAPI ( options ) ;
2022-09-16 14:34:26 -04:00
2022-09-22 15:17:12 -04:00
return 0 ;
2022-09-16 14:34:26 -04:00
}
// snippet-end:[transcribe.cpp.stream_transcription_async.code]