Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java:Transcribe, medical streaming #7044

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 24 additions & 11 deletions .doc_gen/metadata/transcribe_metadata.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
# zexi 0.4.3
transcribe_StartTranscriptionJob:
languages:
Java:
versions:
- sdk_version: 2
github: javav2/example_code/transcribe
sdkguide:
excerpts:
- description:
snippet_tags:
- transcribe.java-streaming-demo
.NET:
versions:
- sdk_version: 3
Expand Down Expand Up @@ -251,8 +242,17 @@ transcribe_DeleteVocabulary:
- python.example_code.transcribe.DeleteVocabulary
services:
transcribe: {DeleteVocabulary}
transcribe_StartStreamTranscriptionAsync:
transcribe_StartStreamTranscription:
languages:
Java:
versions:
- sdk_version: 2
github: javav2/example_code/transcribe
sdkguide:
excerpts:
- description:
snippet_tags:
- transcribe.java-streaming-demo
C++:
versions:
- sdk_version: 1
Expand All @@ -262,7 +262,20 @@ transcribe_StartStreamTranscriptionAsync:
snippet_tags:
- transcribe.cpp.stream_transcription_async.code
services:
transcribe: {StartStreamTranscriptionAsync}
transcribe: {StartStreamTranscription}
transcribe_StartMedicalStreamTranscription:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like both of these APIs are part of a separate service client transcribe_streaming, so you'll need to create an entry for that in services.yaml and reference it here for the API ref links to work correctly.

languages:
Java:
versions:
- sdk_version: 2
github: javav2/example_code/transcribe
sdkguide:
excerpts:
- description:
snippet_tags:
- transcribe.java-medical-streaming-demo
services:
transcribe: {StartMedicalStreamTranscription}
transcribe_Scenario_GettingStartedTranscriptionJobs:
title: Transcribe audio and get job data with &TSC; using an &AWS; SDK
title_abbrev: Transcribe audio and get job data
Expand Down
2 changes: 1 addition & 1 deletion cpp/example_code/transcribe/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Next, for information on code example structures and how to build and run the ex

Code excerpts that show you how to call individual service functions.

- [StartStreamTranscriptionAsync](get_transcript.cpp#L28)
- [StartStreamTranscription](get_transcript.cpp#L28)


<!--custom.examples.start-->
Expand Down
3 changes: 2 additions & 1 deletion javav2/example_code/transcribe/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ For prerequisites, see the [README](../../README.md#Prerequisites) in the `javav
Code excerpts that show you how to call individual service functions.

- [ListTranscriptionJobs](src/main/java/com/amazonaws/transcribe/ListTranscriptionJobs.java#L12)
- [StartTranscriptionJob](src/main/java/com/amazonaws/transcribestreaming/TranscribeStreamingDemoApp.java#L26)
- [StartMedicalStreamTranscription](src/main/java/com/amazonaws/transcribestreaming/TranscribeMedicalStreamingDemoApp.java#L25)
- [StartStreamTranscription](src/main/java/com/amazonaws/transcribestreaming/TranscribeStreamingDemoApp.java#L26)

### Scenarios

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests? At least simple integration tests like other Java examples.

// SPDX-License-Identifier: Apache-2.0

package com.amazonaws.transcribestreaming;

import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.transcribestreaming.TranscribeStreamingAsyncClient;
import software.amazon.awssdk.services.transcribestreaming.model.*;
import javax.sound.sampled.*;
import java.io.*;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;

// snippet-start:[transcribe.java-medical-streaming-demo]
/*
To run this AWS code example, ensure that you have set up your development
environment, including your AWS credentials.

For information, see this documentation topic:

https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html

This code demonstrates the process of starting a medical transcription job using the AWS Transcribe
Streaming service, including setting up the audio input stream, configuring the transcription request,
and handling the transcription response.
*/

public class TranscribeMedicalStreamingDemoApp {
private static TranscribeStreamingAsyncClient client;

public static void main(String args[])
throws ExecutionException, InterruptedException, LineUnavailableException {

client = TranscribeStreamingAsyncClient.builder()
.credentialsProvider(getCredentials())
.build();

CompletableFuture<Void> result = client.startMedicalStreamTranscription(getMedicalRequest(16_000),
new AudioStreamPublisher(getStreamFromMic()),
getMedicalResponseHandler());

result.get();
client.close();
}

private static InputStream getStreamFromMic() throws LineUnavailableException {

// Signed PCM AudioFormat with 16kHz, 16 bit sample size, mono
int sampleRate = 16000;
AudioFormat format = new AudioFormat(sampleRate, 16, 1, true, false);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);

if (!AudioSystem.isLineSupported(info)) {
System.out.println("Line not supported");
System.exit(0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This strikes me as an unusual way to handle this. Why not throw an exception?

}

TargetDataLine line = (TargetDataLine) AudioSystem.getLine(info);
line.open(format);
line.start();

InputStream audioStream = new AudioInputStream(line);
return audioStream;
}

private static AwsCredentialsProvider getCredentials() {
return DefaultCredentialsProvider.create();
}

private static StartMedicalStreamTranscriptionRequest getMedicalRequest(Integer mediaSampleRateHertz) {
return StartMedicalStreamTranscriptionRequest.builder()
.languageCode(LanguageCode.EN_US.toString()) // For medical transcription, EN_US is typically used.
.mediaEncoding(MediaEncoding.PCM)
.mediaSampleRateHertz(mediaSampleRateHertz)
.specialty(Specialty.PRIMARYCARE) // Specify the medical specialty.
.type(Type.CONVERSATION) // Set the type as CONVERSATION or DICTATION.
.build();
}

private static StartMedicalStreamTranscriptionResponseHandler getMedicalResponseHandler() {
return StartMedicalStreamTranscriptionResponseHandler.builder()
.onResponse(r -> {
System.out.println("Received Initial response");
})
.onError(e -> {
System.out.println(e.getMessage());
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
System.out.println("Error Occurred: " + sw.toString());
})
.onComplete(() -> {
System.out.println("=== All records streamed successfully ===");
})
.subscriber(event -> {
List<MedicalResult> results = ((MedicalTranscriptEvent) event).transcript().results();
if (results.size() > 0) {
if (!results.get(0).alternatives().get(0).transcript().isEmpty()) {
System.out.println(results.get(0).alternatives().get(0).transcript());
}
}
})
.build();
}

private static class AudioStreamPublisher implements Publisher<AudioStream> {
private final InputStream inputStream;
private static Subscription currentSubscription;

private AudioStreamPublisher(InputStream inputStream) {
this.inputStream = inputStream;
}

@Override
public void subscribe(Subscriber<? super AudioStream> s) {

if (this.currentSubscription == null) {
this.currentSubscription = new SubscriptionImpl(s, inputStream);
} else {
this.currentSubscription.cancel();
this.currentSubscription = new SubscriptionImpl(s, inputStream);
}
s.onSubscribe(currentSubscription);
}
}

public static class SubscriptionImpl implements Subscription {
private static final int CHUNK_SIZE_IN_BYTES = 1024 * 1;
private final Subscriber<? super AudioStream> subscriber;
private final InputStream inputStream;
private ExecutorService executor = Executors.newFixedThreadPool(1);
private AtomicLong demand = new AtomicLong(0);

SubscriptionImpl(Subscriber<? super AudioStream> s, InputStream inputStream) {
this.subscriber = s;
this.inputStream = inputStream;
}

@Override
public void request(long n) {
if (n <= 0) {
subscriber.onError(new IllegalArgumentException("Demand must be positive"));
}

demand.getAndAdd(n);
executor.submit(() -> {
try {
do {
ByteBuffer audioBuffer = getNextEvent();
if (audioBuffer.remaining() > 0) {
AudioEvent audioEvent = audioEventFromBuffer(audioBuffer);
subscriber.onNext(audioEvent);
} else {
subscriber.onComplete();
break;
}
} while (demand.decrementAndGet() > 0);
} catch (Exception e) {
subscriber.onError(e);
}
});
}

@Override
public void cancel() {
executor.shutdown();
}

private ByteBuffer getNextEvent() {
ByteBuffer audioBuffer = null;
byte[] audioBytes = new byte[CHUNK_SIZE_IN_BYTES];

int len = 0;
try {
len = inputStream.read(audioBytes);

if (len <= 0) {
audioBuffer = ByteBuffer.allocate(0);
} else {
audioBuffer = ByteBuffer.wrap(audioBytes, 0, len);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}

return audioBuffer;
}

private AudioEvent audioEventFromBuffer(ByteBuffer bb) {
return AudioEvent.builder()
.audioChunk(SdkBytes.fromByteBuffer(bb))
.build();
}
}
}
// snippet-end:[transcribe.java-medical-streaming-demo]
Loading