software.amazon.awssdk.services.transcribestreaming.DefaultTranscribeStreamingAsyncClient Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of transcribestreaming Show documentation
Show all versions of transcribestreaming Show documentation
The AWS Java SDK for AWS Transcribe Streaming module holds the client classes that are used for
communicating with AWS Transcribe Streaming Service
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
* the License. A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
package software.amazon.awssdk.services.transcribestreaming;
import static software.amazon.awssdk.utils.FunctionalUtils.runAndLogError;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import org.reactivestreams.Publisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.annotations.Generated;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.auth.signer.EventStreamAws4Signer;
import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration;
import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler;
import software.amazon.awssdk.awscore.client.handler.AwsClientHandlerUtils;
import software.amazon.awssdk.awscore.eventstream.EventStreamAsyncResponseTransformer;
import software.amazon.awssdk.awscore.eventstream.EventStreamTaggedUnionJsonMarshaller;
import software.amazon.awssdk.awscore.eventstream.EventStreamTaggedUnionPojoSupplier;
import software.amazon.awssdk.awscore.eventstream.RestEventStreamAsyncResponseTransformer;
import software.amazon.awssdk.awscore.exception.AwsServiceException;
import software.amazon.awssdk.core.RequestOverrideConfiguration;
import software.amazon.awssdk.core.SdkPojoBuilder;
import software.amazon.awssdk.core.SdkResponse;
import software.amazon.awssdk.core.async.AsyncRequestBody;
import software.amazon.awssdk.core.async.SdkPublisher;
import software.amazon.awssdk.core.client.config.SdkAdvancedAsyncClientOption;
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
import software.amazon.awssdk.core.client.config.SdkClientOption;
import software.amazon.awssdk.core.client.handler.AsyncClientHandler;
import software.amazon.awssdk.core.client.handler.AttachHttpMetadataResponseHandler;
import software.amazon.awssdk.core.client.handler.ClientExecutionParams;
import software.amazon.awssdk.core.http.HttpResponseHandler;
import software.amazon.awssdk.core.metrics.CoreMetric;
import software.amazon.awssdk.core.protocol.VoidSdkResponse;
import software.amazon.awssdk.core.signer.Signer;
import software.amazon.awssdk.metrics.MetricCollector;
import software.amazon.awssdk.metrics.MetricPublisher;
import software.amazon.awssdk.metrics.NoOpMetricCollector;
import software.amazon.awssdk.protocols.core.ExceptionMetadata;
import software.amazon.awssdk.protocols.json.AwsJsonProtocol;
import software.amazon.awssdk.protocols.json.AwsJsonProtocolFactory;
import software.amazon.awssdk.protocols.json.BaseAwsJsonProtocolFactory;
import software.amazon.awssdk.protocols.json.JsonOperationMetadata;
import software.amazon.awssdk.services.transcribestreaming.model.AudioEvent;
import software.amazon.awssdk.services.transcribestreaming.model.AudioStream;
import software.amazon.awssdk.services.transcribestreaming.model.BadRequestException;
import software.amazon.awssdk.services.transcribestreaming.model.ConflictException;
import software.amazon.awssdk.services.transcribestreaming.model.InternalFailureException;
import software.amazon.awssdk.services.transcribestreaming.model.LimitExceededException;
import software.amazon.awssdk.services.transcribestreaming.model.MedicalTranscriptResultStream;
import software.amazon.awssdk.services.transcribestreaming.model.ServiceUnavailableException;
import software.amazon.awssdk.services.transcribestreaming.model.StartMedicalStreamTranscriptionRequest;
import software.amazon.awssdk.services.transcribestreaming.model.StartMedicalStreamTranscriptionResponse;
import software.amazon.awssdk.services.transcribestreaming.model.StartMedicalStreamTranscriptionResponseHandler;
import software.amazon.awssdk.services.transcribestreaming.model.StartStreamTranscriptionRequest;
import software.amazon.awssdk.services.transcribestreaming.model.StartStreamTranscriptionResponse;
import software.amazon.awssdk.services.transcribestreaming.model.StartStreamTranscriptionResponseHandler;
import software.amazon.awssdk.services.transcribestreaming.model.TranscribeStreamingException;
import software.amazon.awssdk.services.transcribestreaming.model.TranscribeStreamingRequest;
import software.amazon.awssdk.services.transcribestreaming.model.TranscriptResultStream;
import software.amazon.awssdk.services.transcribestreaming.transform.AudioEventMarshaller;
import software.amazon.awssdk.services.transcribestreaming.transform.StartMedicalStreamTranscriptionRequestMarshaller;
import software.amazon.awssdk.services.transcribestreaming.transform.StartStreamTranscriptionRequestMarshaller;
import software.amazon.awssdk.utils.CompletableFutureUtils;
/**
* Internal implementation of {@link TranscribeStreamingAsyncClient}.
*
* @see TranscribeStreamingAsyncClient#builder()
*/
@Generated("software.amazon.awssdk:codegen")
@SdkInternalApi
final class DefaultTranscribeStreamingAsyncClient implements TranscribeStreamingAsyncClient {
private static final Logger log = LoggerFactory.getLogger(DefaultTranscribeStreamingAsyncClient.class);
private final AsyncClientHandler clientHandler;
private final AwsJsonProtocolFactory protocolFactory;
private final SdkClientConfiguration clientConfiguration;
private final Executor executor;
protected DefaultTranscribeStreamingAsyncClient(SdkClientConfiguration clientConfiguration) {
this.clientHandler = new AwsAsyncClientHandler(clientConfiguration);
this.clientConfiguration = clientConfiguration;
this.protocolFactory = init(AwsJsonProtocolFactory.builder()).build();
this.executor = clientConfiguration.option(SdkAdvancedAsyncClientOption.FUTURE_COMPLETION_EXECUTOR);
}
@Override
public final String serviceName() {
return SERVICE_NAME;
}
/**
*
* Starts a bidirectional HTTP/2 stream where audio is streamed to Amazon Transcribe Medical and the transcription
* results are streamed to your application.
*
*
* @param startMedicalStreamTranscriptionRequest
* @return A Java Future containing the result of the StartMedicalStreamTranscription operation returned by the
* service.
* The CompletableFuture returned by this method can be completed exceptionally with the following
* exceptions.
*
* - BadRequestException One or more arguments to the
StartStreamTranscription
or
* StartMedicalStreamTranscription
operation was invalid. For example,
* MediaEncoding
was not set to a valid encoding, or LanguageCode
was not set to a
* valid code. Check the parameters and try your request again.
* - LimitExceededException You have exceeded the maximum number of concurrent transcription streams, are
* starting transcription streams too quickly, or the maximum audio length of 4 hours. Wait until a stream
* has finished processing, or break your audio stream into smaller chunks and try your request again.
* - InternalFailureException A problem occurred while processing the audio. Amazon Transcribe or Amazon
* Transcribe Medical terminated processing. Try your request again.
* - ConflictException A new stream started with the same session ID. The current stream has been
* terminated.
* - ServiceUnavailableException Service is currently unavailable. Try your request later.
* - SdkException Base class for all exceptions that can be thrown by the SDK (both service and client).
* Can be used for catch all scenarios.
* - SdkClientException If any client side error occurs such as an IO related failure, failure to get
* credentials, etc.
* - TranscribeStreamingException Base class for all service exceptions. Unknown exceptions will be thrown
* as an instance of this type.
*
* @sample TranscribeStreamingAsyncClient.StartMedicalStreamTranscription
* @see AWS API Documentation
*/
@Override
public CompletableFuture startMedicalStreamTranscription(
StartMedicalStreamTranscriptionRequest startMedicalStreamTranscriptionRequest, Publisher requestStream,
StartMedicalStreamTranscriptionResponseHandler asyncResponseHandler) {
List metricPublishers = resolveMetricPublishers(clientConfiguration,
startMedicalStreamTranscriptionRequest.overrideConfiguration().orElse(null));
MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector
.create("ApiCall");
try {
apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Transcribe Streaming");
apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StartMedicalStreamTranscription");
startMedicalStreamTranscriptionRequest = applySignerOverride(startMedicalStreamTranscriptionRequest,
EventStreamAws4Signer.create());
JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false)
.isPayloadJson(true).build();
HttpResponseHandler responseHandler = new AttachHttpMetadataResponseHandler(
protocolFactory.createResponseHandler(operationMetadata, StartMedicalStreamTranscriptionResponse::builder));
HttpResponseHandler voidResponseHandler = protocolFactory.createResponseHandler(JsonOperationMetadata
.builder().isPayloadJson(false).hasStreamingSuccessResponse(true).build(), VoidSdkResponse::builder);
HttpResponseHandler extends MedicalTranscriptResultStream> eventResponseHandler = protocolFactory
.createResponseHandler(
JsonOperationMetadata.builder().isPayloadJson(true).hasStreamingSuccessResponse(false).build(),
EventStreamTaggedUnionPojoSupplier.builder()
.putSdkPojoSupplier("TranscriptEvent", MedicalTranscriptResultStream::transcriptEventBuilder)
.defaultSdkPojoSupplier(() -> new SdkPojoBuilder(MedicalTranscriptResultStream.UNKNOWN))
.build());
HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory,
operationMetadata);
EventStreamTaggedUnionJsonMarshaller eventMarshaller = EventStreamTaggedUnionJsonMarshaller.builder()
.putMarshaller(AudioEvent.class, new AudioEventMarshaller(protocolFactory)).build();
SdkPublisher eventPublisher = SdkPublisher.adapt(requestStream);
Publisher adapted = eventPublisher.map(event -> eventMarshaller.marshall(event)).map(
AwsClientHandlerUtils::encodeEventStreamRequestToByteBuffer);
CompletableFuture future = new CompletableFuture<>();
EventStreamAsyncResponseTransformer asyncResponseTransformer = EventStreamAsyncResponseTransformer
. builder()
.eventStreamResponseHandler(asyncResponseHandler).eventResponseHandler(eventResponseHandler)
.initialResponseHandler(responseHandler).exceptionResponseHandler(errorResponseHandler).future(future)
.executor(executor).serviceName(serviceName()).build();
RestEventStreamAsyncResponseTransformer restAsyncResponseTransformer = RestEventStreamAsyncResponseTransformer
. builder()
.eventStreamAsyncResponseTransformer(asyncResponseTransformer)
.eventStreamResponseHandler(asyncResponseHandler).build();
CompletableFuture executeFuture = clientHandler.execute(
new ClientExecutionParams()
.withOperationName("StartMedicalStreamTranscription")
.withMarshaller(new StartMedicalStreamTranscriptionRequestMarshaller(protocolFactory))
.withAsyncRequestBody(AsyncRequestBody.fromPublisher(adapted)).withFullDuplex(true)
.withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler)
.withMetricCollector(apiCallMetricCollector).withInput(startMedicalStreamTranscriptionRequest),
restAsyncResponseTransformer);
AwsRequestOverrideConfiguration requestOverrideConfig = startMedicalStreamTranscriptionRequest
.overrideConfiguration().orElse(null);
CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> {
if (e != null) {
try {
asyncResponseHandler.exceptionOccurred(e);
} finally {
future.completeExceptionally(e);
}
}
metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect()));
});
executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture);
return CompletableFutureUtils.forwardExceptionTo(future, executeFuture);
} catch (Throwable t) {
runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring",
() -> asyncResponseHandler.exceptionOccurred(t));
metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect()));
return CompletableFutureUtils.failedFuture(t);
}
}
/**
*
* Starts a bidirectional HTTP2 stream where audio is streamed to Amazon Transcribe and the transcription results
* are streamed to your application.
*
*
* The following are encoded as HTTP2 headers:
*
*
* -
*
* x-amzn-transcribe-language-code
*
*
* -
*
* x-amzn-transcribe-media-encoding
*
*
* -
*
* x-amzn-transcribe-sample-rate
*
*
* -
*
* x-amzn-transcribe-session-id
*
*
*
*
* @param startStreamTranscriptionRequest
* @return A Java Future containing the result of the StartStreamTranscription operation returned by the service.
* The CompletableFuture returned by this method can be completed exceptionally with the following
* exceptions.
*
* - BadRequestException One or more arguments to the
StartStreamTranscription
or
* StartMedicalStreamTranscription
operation was invalid. For example,
* MediaEncoding
was not set to a valid encoding, or LanguageCode
was not set to a
* valid code. Check the parameters and try your request again.
* - LimitExceededException You have exceeded the maximum number of concurrent transcription streams, are
* starting transcription streams too quickly, or the maximum audio length of 4 hours. Wait until a stream
* has finished processing, or break your audio stream into smaller chunks and try your request again.
* - InternalFailureException A problem occurred while processing the audio. Amazon Transcribe or Amazon
* Transcribe Medical terminated processing. Try your request again.
* - ConflictException A new stream started with the same session ID. The current stream has been
* terminated.
* - ServiceUnavailableException Service is currently unavailable. Try your request later.
* - SdkException Base class for all exceptions that can be thrown by the SDK (both service and client).
* Can be used for catch all scenarios.
* - SdkClientException If any client side error occurs such as an IO related failure, failure to get
* credentials, etc.
* - TranscribeStreamingException Base class for all service exceptions. Unknown exceptions will be thrown
* as an instance of this type.
*
* @sample TranscribeStreamingAsyncClient.StartStreamTranscription
* @see AWS API Documentation
*/
@Override
public CompletableFuture startStreamTranscription(StartStreamTranscriptionRequest startStreamTranscriptionRequest,
Publisher requestStream, StartStreamTranscriptionResponseHandler asyncResponseHandler) {
List metricPublishers = resolveMetricPublishers(clientConfiguration, startStreamTranscriptionRequest
.overrideConfiguration().orElse(null));
MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector
.create("ApiCall");
try {
apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Transcribe Streaming");
apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StartStreamTranscription");
startStreamTranscriptionRequest = applySignerOverride(startStreamTranscriptionRequest, EventStreamAws4Signer.create());
JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false)
.isPayloadJson(true).build();
HttpResponseHandler responseHandler = new AttachHttpMetadataResponseHandler(
protocolFactory.createResponseHandler(operationMetadata, StartStreamTranscriptionResponse::builder));
HttpResponseHandler voidResponseHandler = protocolFactory.createResponseHandler(JsonOperationMetadata
.builder().isPayloadJson(false).hasStreamingSuccessResponse(true).build(), VoidSdkResponse::builder);
HttpResponseHandler extends TranscriptResultStream> eventResponseHandler = protocolFactory.createResponseHandler(
JsonOperationMetadata.builder().isPayloadJson(true).hasStreamingSuccessResponse(false).build(),
EventStreamTaggedUnionPojoSupplier.builder()
.putSdkPojoSupplier("TranscriptEvent", TranscriptResultStream::transcriptEventBuilder)
.defaultSdkPojoSupplier(() -> new SdkPojoBuilder(TranscriptResultStream.UNKNOWN)).build());
HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory,
operationMetadata);
EventStreamTaggedUnionJsonMarshaller eventMarshaller = EventStreamTaggedUnionJsonMarshaller.builder()
.putMarshaller(AudioEvent.class, new AudioEventMarshaller(protocolFactory)).build();
SdkPublisher eventPublisher = SdkPublisher.adapt(requestStream);
Publisher adapted = eventPublisher.map(event -> eventMarshaller.marshall(event)).map(
AwsClientHandlerUtils::encodeEventStreamRequestToByteBuffer);
CompletableFuture future = new CompletableFuture<>();
EventStreamAsyncResponseTransformer asyncResponseTransformer = EventStreamAsyncResponseTransformer
. builder()
.eventStreamResponseHandler(asyncResponseHandler).eventResponseHandler(eventResponseHandler)
.initialResponseHandler(responseHandler).exceptionResponseHandler(errorResponseHandler).future(future)
.executor(executor).serviceName(serviceName()).build();
RestEventStreamAsyncResponseTransformer restAsyncResponseTransformer = RestEventStreamAsyncResponseTransformer
. builder()
.eventStreamAsyncResponseTransformer(asyncResponseTransformer)
.eventStreamResponseHandler(asyncResponseHandler).build();
CompletableFuture executeFuture = clientHandler.execute(
new ClientExecutionParams()
.withOperationName("StartStreamTranscription")
.withMarshaller(new StartStreamTranscriptionRequestMarshaller(protocolFactory))
.withAsyncRequestBody(AsyncRequestBody.fromPublisher(adapted)).withFullDuplex(true)
.withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler)
.withMetricCollector(apiCallMetricCollector).withInput(startStreamTranscriptionRequest),
restAsyncResponseTransformer);
AwsRequestOverrideConfiguration requestOverrideConfig = startStreamTranscriptionRequest.overrideConfiguration()
.orElse(null);
CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> {
if (e != null) {
try {
asyncResponseHandler.exceptionOccurred(e);
} finally {
future.completeExceptionally(e);
}
}
metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect()));
});
executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture);
return CompletableFutureUtils.forwardExceptionTo(future, executeFuture);
} catch (Throwable t) {
runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring",
() -> asyncResponseHandler.exceptionOccurred(t));
metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect()));
return CompletableFutureUtils.failedFuture(t);
}
}
@Override
public void close() {
clientHandler.close();
}
private > T init(T builder) {
return builder
.clientConfiguration(clientConfiguration)
.defaultServiceExceptionSupplier(TranscribeStreamingException::builder)
.protocol(AwsJsonProtocol.REST_JSON)
.protocolVersion("1.1")
.registerModeledException(
ExceptionMetadata.builder().errorCode("ConflictException")
.exceptionBuilderSupplier(ConflictException::builder).httpStatusCode(409).build())
.registerModeledException(
ExceptionMetadata.builder().errorCode("ServiceUnavailableException")
.exceptionBuilderSupplier(ServiceUnavailableException::builder).httpStatusCode(503).build())
.registerModeledException(
ExceptionMetadata.builder().errorCode("InternalFailureException")
.exceptionBuilderSupplier(InternalFailureException::builder).httpStatusCode(500).build())
.registerModeledException(
ExceptionMetadata.builder().errorCode("BadRequestException")
.exceptionBuilderSupplier(BadRequestException::builder).httpStatusCode(400).build())
.registerModeledException(
ExceptionMetadata.builder().errorCode("LimitExceededException")
.exceptionBuilderSupplier(LimitExceededException::builder).httpStatusCode(429).build());
}
private static List resolveMetricPublishers(SdkClientConfiguration clientConfiguration,
RequestOverrideConfiguration requestOverrideConfiguration) {
List publishers = null;
if (requestOverrideConfiguration != null) {
publishers = requestOverrideConfiguration.metricPublishers();
}
if (publishers == null || publishers.isEmpty()) {
publishers = clientConfiguration.option(SdkClientOption.METRIC_PUBLISHERS);
}
if (publishers == null) {
publishers = Collections.emptyList();
}
return publishers;
}
private T applySignerOverride(T request, Signer signer) {
if (request.overrideConfiguration().flatMap(c -> c.signer()).isPresent()) {
return request;
}
Consumer signerOverride = b -> b.signer(signer).build();
AwsRequestOverrideConfiguration overrideConfiguration = request.overrideConfiguration()
.map(c -> c.toBuilder().applyMutation(signerOverride).build())
.orElse((AwsRequestOverrideConfiguration.builder().applyMutation(signerOverride).build()));
return (T) request.toBuilder().overrideConfiguration(overrideConfiguration).build();
}
private static boolean isSignerOverridden(SdkClientConfiguration clientConfiguration) {
return Boolean.TRUE.equals(clientConfiguration.option(SdkClientOption.SIGNER_OVERRIDDEN));
}
private HttpResponseHandler createErrorResponseHandler(BaseAwsJsonProtocolFactory protocolFactory,
JsonOperationMetadata operationMetadata) {
return protocolFactory.createErrorResponseHandler(operationMetadata);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy