-
Notifications
You must be signed in to change notification settings - Fork 5.6k
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
meyertst-aws
wants to merge
6
commits into
awsdocs:main
Choose a base branch
from
meyertst-aws:transcribe
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+233
−13
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
5efc577
add a medical transcribe example
scmacdon 6460492
Fix so that transcript outputs
meyertst-aws 52b5f6a
update-metadata
meyertst-aws 285ce8e
Merge branch 'awsdocs:main' into transcribe
meyertst-aws 2f1b521
fix yaml
meyertst-aws a8acac3
remove hard-coded region
meyertst-aws File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
206 changes: 206 additions & 0 deletions
206
...be/src/main/java/com/amazonaws/transcribestreaming/TranscribeMedicalStreamingDemoApp.java
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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] |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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.