public async Task ExecuteAsync(WorkerJobHelper <AIJob> jobHelper)
        {
            S3Locator inputFile;

            if (!jobHelper.JobInput.TryGet <S3Locator>(nameof(inputFile), out inputFile))
            {
                throw new Exception("Invalid or missing input file.");
            }

            string mediaFileUrl;

            if (!string.IsNullOrWhiteSpace(inputFile.HttpEndpoint))
            {
                mediaFileUrl = inputFile.HttpEndpoint;
            }
            else
            {
                var bucketLocation = await inputFile.GetBucketLocationAsync();

                var s3SubDomain = !string.IsNullOrWhiteSpace(bucketLocation) ? $"s3-{bucketLocation}" : "s3";
                mediaFileUrl = $"https://{s3SubDomain}.amazonaws.com/{inputFile.AwsS3Bucket}/{inputFile.AwsS3Key}";
            }

            string mediaFormat;

            if (mediaFileUrl.EndsWith("mp3", StringComparison.OrdinalIgnoreCase))
            {
                mediaFormat = "mp3";
            }
            else if (mediaFileUrl.EndsWith("mp4", StringComparison.OrdinalIgnoreCase))
            {
                mediaFormat = "mp4";
            }
            else if (mediaFileUrl.EndsWith("wav", StringComparison.OrdinalIgnoreCase))
            {
                mediaFormat = "wav";
            }
            else if (mediaFileUrl.EndsWith("flac", StringComparison.OrdinalIgnoreCase))
            {
                mediaFormat = "flac";
            }
            else
            {
                throw new Exception($"Unable to determine media format from input file '{mediaFileUrl}'");
            }

            var transcribeParameters = new StartTranscriptionJobRequest
            {
                TranscriptionJobName = "TranscriptionJob-" + jobHelper.JobAssignmentId.Substring(jobHelper.JobAssignmentId.LastIndexOf("/") + 1),
                LanguageCode         = "en-US",
                Media = new Media {
                    MediaFileUri = mediaFileUrl
                },
                MediaFormat      = mediaFormat,
                OutputBucketName = jobHelper.Request.GetRequiredContextVariable("ServiceOutputBucket")
            };

            using (var transcribeService = new AmazonTranscribeServiceClient())
                await transcribeService.StartTranscriptionJobAsync(transcribeParameters);
        }
示例#2
0
        public override async Task <FunctionResponse> ProcessMessageAsync(S3Event request)
        {
            foreach (var record in request.Records)
            {
                LogInfo($"processing 's3://{record.S3.Bucket.Name}/{record.S3.Object.Key}'");

                // extract the video etag from the filename
                var videoEtag = Path.GetFileNameWithoutExtension(record.S3.Object.Key);

                try {
                    // kick off a transcribe job
                    var transcriptionResponse = await _transcribe.StartTranscriptionJobAsync(
                        new StartTranscriptionJobRequest {
                        // TODO: need a better name (add timestamp?) so that we can re-transcribe a transcribed video
                        TranscriptionJobName = $"transcribe-{videoEtag}",
                        Media = new Media {
                            MediaFileUri = $"https://s3-{record.AwsRegion}.amazonaws.com/{record.S3.Bucket.Name}/{record.S3.Object.Key}"
                        },
                        MediaFormat      = MediaFormat.Mp3,
                        LanguageCode     = LanguageCode.EnUS,
                        OutputBucketName = _outputBucketName
                    },
                        CancellationToken.None
                        );

                    // send a message to the progress queue
                    await _sqsClient.SendMessageAsync(new Amazon.SQS.Model.SendMessageRequest {
                        MessageBody = SerializeJson(new ProgressMessage {
                            Type    = MessageType.INDEXING_STARTED,
                            Message = SerializeJson(new IndexingStartedMessage {
                                Job = transcriptionResponse
                            })
                        }),
                        QueueUrl = _notifyQueueUrl
                    });
                } catch (Exception e) {
                    LogError(e);
                }
            }
            return(new FunctionResponse {
            });
        }
示例#3
0
        internal static async Task ProcessJobAssignmentAsync(AwsAiServiceWorkerRequest @event)
        {
            var resourceManager = @event.GetAwsV4ResourceManager();
            var table           = new DynamoDbTable(@event.StageVariables["TableName"]);
            var jobAssignmentId = @event.JobAssignmentId;

            try
            {
                // 1. Setting job assignment status to RUNNING
                await UpdateJobAssignmentStatusAsync(resourceManager, table, jobAssignmentId, "RUNNING", null);

                // 2. Retrieving WorkflowJob
                var job = await RetrieveJobAsync(resourceManager, table, jobAssignmentId);

                // 3. Retrieve JobProfile
                var jobProfile = await RetrieveJobProfileAsync(resourceManager, job);

                // 4. Retrieve job inputParameters
                var jobInput = job.JobInput;

                // 5. Check if we support jobProfile and if we have required parameters in jobInput
                ValidateJobProfile(jobProfile, jobInput);

                S3Locator inputFile;
                if (!jobInput.TryGet <S3Locator>(nameof(inputFile), out inputFile))
                {
                    throw new Exception("Invalid or missing input file.");
                }

                S3Locator outputLocation;
                if (!jobInput.TryGet <S3Locator>(nameof(outputLocation), out outputLocation))
                {
                    throw new Exception("Invalid or missing output location.");
                }

                switch (jobProfile.Name)
                {
                case JOB_PROFILE_TRANSCRIBE_AUDIO:
                    string mediaFileUrl;
                    if (!string.IsNullOrWhiteSpace(inputFile.HttpEndpoint))
                    {
                        mediaFileUrl = inputFile.HttpEndpoint;
                    }
                    else
                    {
                        var bucketLocation = await inputFile.GetBucketLocationAsync();

                        var s3SubDomain = !string.IsNullOrWhiteSpace(bucketLocation) ? $"s3-{bucketLocation}" : "s3";
                        mediaFileUrl = $"https://{s3SubDomain}.amazonaws.com/{inputFile.AwsS3Bucket}/{inputFile.AwsS3Key}";
                    }

                    string mediaFormat;
                    if (mediaFileUrl.EndsWith("mp3", StringComparison.OrdinalIgnoreCase))
                    {
                        mediaFormat = "mp3";
                    }
                    else if (mediaFileUrl.EndsWith("mp4", StringComparison.OrdinalIgnoreCase))
                    {
                        mediaFormat = "mp4";
                    }
                    else if (mediaFileUrl.EndsWith("wav", StringComparison.OrdinalIgnoreCase))
                    {
                        mediaFormat = "wav";
                    }
                    else if (mediaFileUrl.EndsWith("flac", StringComparison.OrdinalIgnoreCase))
                    {
                        mediaFormat = "flac";
                    }
                    else
                    {
                        throw new Exception($"Unable to determine media format from input file '{mediaFileUrl}'");
                    }

                    var transcribeParameters = new StartTranscriptionJobRequest
                    {
                        TranscriptionJobName = "TranscriptionJob-" + jobAssignmentId.Substring(jobAssignmentId.LastIndexOf("/") + 1),
                        LanguageCode         = "en-US",
                        Media = new Media {
                            MediaFileUri = mediaFileUrl
                        },
                        MediaFormat      = mediaFormat,
                        OutputBucketName = @event.StageVariables["ServiceOutputBucket"]
                    };

                    var transcribeService = new AmazonTranscribeServiceClient();

                    var startJobResponse = await transcribeService.StartTranscriptionJobAsync(transcribeParameters);

                    Logger.Debug(startJobResponse.ToMcmaJson().ToString());
                    break;

                case JOB_PROFILE_TRANSLATE_TEXT:
                    var s3Bucket = inputFile.AwsS3Bucket;
                    var s3Key    = inputFile.AwsS3Key;

                    GetObjectResponse s3Object;
                    try
                    {
                        s3Object = await inputFile.GetAsync();
                    }
                    catch (Exception error)
                    {
                        throw new Exception($"Unable to read file in bucket '{s3Bucket}' with key '{s3Key}'.", error);
                    }

                    var inputText = await new StreamReader(s3Object.ResponseStream).ReadToEndAsync();

                    var translateParameters = new TranslateTextRequest
                    {
                        SourceLanguageCode = jobInput.TryGet("sourceLanguageCode", out string srcLanguageCode) ? srcLanguageCode : "auto",
                        TargetLanguageCode = jobInput.Get <string>("targetLanguageCode"),
                        Text = inputText
                    };

                    var translateService  = new AmazonTranslateClient();
                    var translateResponse = await translateService.TranslateTextAsync(translateParameters);

                    var s3Params = new PutObjectRequest
                    {
                        BucketName  = outputLocation.AwsS3Bucket,
                        Key         = (!string.IsNullOrWhiteSpace(outputLocation.AwsS3KeyPrefix) ? outputLocation.AwsS3Key : string.Empty) + Guid.NewGuid() + ".txt",
                        ContentBody = translateResponse.TranslatedText
                    };

                    var outputS3 = await outputLocation.GetClientAsync();

                    await outputS3.PutObjectAsync(s3Params);

                    var jobOutput = new JobParameterBag();
                    jobOutput["outputFile"] = new S3Locator
                    {
                        AwsS3Bucket = s3Params.BucketName,
                        AwsS3Key    = s3Params.Key
                    };

                    Logger.Debug("Updating job assignment");
                    await UpdateJobAssignmentWithOutputAsync(table, jobAssignmentId, jobOutput);
                    await UpdateJobAssignmentStatusAsync(resourceManager, table, jobAssignmentId, "COMPLETED");

                    break;

                case JOB_PROFILE_DETECT_CELEBRITIES:
                    var randomBytes = new byte[16];
                    new Random().NextBytes(randomBytes);
                    var clientToken = randomBytes.HexEncode();

                    var base64JobId = Encoding.UTF8.GetBytes(jobAssignmentId).HexEncode();

                    var rekoParams = new StartCelebrityRecognitionRequest
                    {
                        Video = new Video
                        {
                            S3Object = new Amazon.Rekognition.Model.S3Object
                            {
                                Bucket = inputFile.AwsS3Bucket,
                                Name   = inputFile.AwsS3Key
                            }
                        },
                        ClientRequestToken  = clientToken,
                        JobTag              = base64JobId,
                        NotificationChannel = new NotificationChannel
                        {
                            RoleArn     = REKO_SNS_ROLE_ARN,
                            SNSTopicArn = SNS_TOPIC_ARN
                        }
                    };

                    var rekognitionClient             = new AmazonRekognitionClient();
                    var startCelebRecognitionResponse = await rekognitionClient.StartCelebrityRecognitionAsync(rekoParams);

                    Logger.Debug(startCelebRecognitionResponse.ToMcmaJson().ToString());
                    break;
                }
            }
            catch (Exception ex)
            {
                Logger.Exception(ex);

                try
                {
                    await UpdateJobAssignmentStatusAsync(resourceManager, table, jobAssignmentId, "FAILED", ex.ToString());
                }
                catch (Exception innerEx)
                {
                    Logger.Exception(innerEx);
                }
            }
        }
示例#4
0
        private async void BeginTranscription_Click(object sender, RoutedEventArgs e)
        {
            this._ctlBeginTranscription.IsEnabled = false;
            try
            {
                this._ctlStatusLog.Text     = "";
                this._ctlTranscription.Text = "";

                var filepath = this._ctlFilepath.Text;
                if (string.IsNullOrEmpty(filepath))
                {
                    MessageBox.Show($"An mp4 file must be selected first before transcribing", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }
                if (!System.IO.File.Exists(filepath))
                {
                    MessageBox.Show($"File {filepath} does not exist", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                var s3Key    = System.IO.Path.GetFileName(filepath);
                var s3Bucket = _ctlS3Bucket.Text;


                var            chain = new CredentialProfileStoreChain();
                AWSCredentials credentials;
                if (!chain.TryGetAWSCredentials(this._ctlProfile.Text, out credentials))
                {
                    MessageBox.Show($"Profile {this._ctlProfile.Text} was not found", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                var region = RegionEndpoint.GetBySystemName(this._ctlRegion.Text);

                var transcriptionJobName = $"{s3Key}-{Guid.NewGuid().ToString()}";

                using (var s3Client = new AmazonS3Client(credentials, region))
                    using (var transcribeClient = new AmazonTranscribeServiceClient(credentials, region))
                        using (var httpClient = new HttpClient()) // Http Client to download the transcription once complete
                        {
                            AppendStatusLine("Ensuring S3 bucket exists");
                            await s3Client.PutBucketAsync(s3Bucket);


                            var transferUtility = new TransferUtility(s3Client);

                            AppendStatusLine("Starting upload");

                            var uploadRequest = new TransferUtilityUploadRequest
                            {
                                FilePath   = filepath,
                                BucketName = s3Bucket,
                                Key        = s3Key
                            };

                            uploadRequest.UploadProgressEvent += ProgressUploadStatus;

                            await transferUtility.UploadAsync(uploadRequest);

                            var mediaFileUri = $"https://s3.{region.SystemName}.amazonaws.com/{s3Bucket}/{s3Key}";
                            AppendStatusLine($"Upload Complete to: {mediaFileUri}");

                            await transcribeClient.StartTranscriptionJobAsync(new StartTranscriptionJobRequest
                            {
                                LanguageCode = LanguageCode.EnUS,
                                Media        = new Media
                                {
                                    MediaFileUri = mediaFileUri
                                },
                                MediaFormat          = MediaFormat.Mp4,
                                TranscriptionJobName = transcriptionJobName
                            });

                            AppendStatusLine($"Started transcription job: {transcriptionJobName}");

                            GetTranscriptionJobRequest request = new GetTranscriptionJobRequest {
                                TranscriptionJobName = transcriptionJobName
                            };
                            GetTranscriptionJobResponse response = null;
                            do
                            {
                                AppendStatusLine($"... {DateTime.Now} Waiting for transcription job to complete");
                                await Task.Delay(TimeSpan.FromSeconds(2));

                                response = await transcribeClient.GetTranscriptionJobAsync(request);
                            } while (response.TranscriptionJob.TranscriptionJobStatus == TranscriptionJobStatus.IN_PROGRESS);

                            if (response.TranscriptionJob.TranscriptionJobStatus == TranscriptionJobStatus.FAILED)
                            {
                                AppendStatusLine($"Transcription job failed: {response.TranscriptionJob.FailureReason}");
                                return;
                            }

                            AppendStatusLine("Job Done");

                            var transcriptionDocument = await httpClient.GetStringAsync(response.TranscriptionJob.Transcript.TranscriptFileUri);

                            var root = JsonConvert.DeserializeObject(transcriptionDocument) as JObject;

                            var sb = new StringBuilder();
                            foreach (JObject transcriptionNode in root["results"]["transcripts"])
                            {
                                if (sb.Length != 0)
                                {
                                    sb.AppendLine("\n\n");
                                }

                                sb.Append(transcriptionNode["transcript"]);
                            }

                            this._ctlTranscription.Text = sb.ToString();
                        }
            }
            catch (Exception ex)
            {
                AppendStatusLine($"Unknown error: {ex.Message}");
            }
            finally
            {
                this._ctlBeginTranscription.IsEnabled = true;
            }
        }
示例#5
0
        public override async Task ProcessMessageAsync(Message message, ILambdaContext context)
        {
            if (message.Iterations < 0)
            {
                return;
            }
            var suffix = DateTime.UtcNow.ToString("yyyyMMddHHmmss");

            // Initiate describe voices request.
            var describeVoiceResponse = await _pollyClient.DescribeVoicesAsync(new DescribeVoicesRequest {
                // LanguageCode = "en-US"
            });

            // LogInfo(JsonConvert.SerializeObject(describeVoiceResponse.Voices));
            var randomIndex = _rand.Next(describeVoiceResponse.Voices.Count);
            var randomVoice = describeVoiceResponse.Voices[randomIndex];

            LogInfo($"Selected random voice '{randomVoice.Name}' in {randomVoice.LanguageName}");

            // Initiate speech synthesis request.
            var synthesizeResponse = await _pollyClient.SynthesizeSpeechAsync(new SynthesizeSpeechRequest {
                VoiceId      = randomVoice.Id,
                OutputFormat = OutputFormat.Mp3,
                Text         = message.Text
            });

            var audioStream = new MemoryStream();
            await synthesizeResponse.AudioStream.CopyToAsync(audioStream);

            audioStream.Position = 0;

            // Ensure audio file is in an s3 bucket for Transcribe to consume.
            await _s3Client.PutObjectAsync(new PutObjectRequest {
                BucketName  = _audioBucket,
                Key         = $"polly_{suffix}.mp3",
                InputStream = audioStream
            });

            // Initiate Transcription Job
            var transcriptionName     = $"transcribe_{suffix}";
            var mediaUri              = $"https://s3-us-east-1.amazonaws.com/{_audioBucket}/polly_{suffix}.mp3";
            var transcriptionResponse = await _transcribeClient.StartTranscriptionJobAsync(new StartTranscriptionJobRequest {
                LanguageCode = "en-US",
                MediaFormat  = MediaFormat.Mp3,
                Media        = new Media {
                    MediaFileUri = mediaUri
                },
                OutputBucketName     = _textBucket,
                TranscriptionJobName = transcriptionName
            });

            // Wait for transcription job to complete
            while (true)
            {
                await Task.Delay(TimeSpan.FromSeconds(3));

                var transcriptionJobStatusReponse = await _transcribeClient.GetTranscriptionJobAsync(new GetTranscriptionJobRequest {
                    TranscriptionJobName = transcriptionName
                });

                if (transcriptionJobStatusReponse.TranscriptionJob.TranscriptionJobStatus == TranscriptionJobStatus.FAILED)
                {
                    LogWarn("Transcribe job failed");
                    return;
                }
                if (transcriptionJobStatusReponse.TranscriptionJob.TranscriptionJobStatus == TranscriptionJobStatus.COMPLETED)
                {
                    LogInfo("Job Completed!!");
                    break;
                }
                LogInfo("Checking job status... again.");
            }

            // Retrieve text file from s3 and extract the text
            var s3Response = await _s3Client.GetObjectAsync(new GetObjectRequest {
                BucketName = _textBucket,
                Key        = $"{transcriptionName}.json"
            });

            var text = await new StreamReader(s3Response.ResponseStream).ReadToEndAsync();

            LogInfo(text);
            var json          = JObject.Parse(text);
            var transcription = json["results"]["transcripts"][0]["transcript"].ToString();

            LogInfo(transcription);

            if (message.Iterations >= 0 && transcription.Length > 0)
            {
                await _snsClient.PublishAsync(new PublishRequest {
                    TopicArn = _topic,
                    Message  = JsonConvert.SerializeObject(new Message {
                        Iterations = message.Iterations - 1,
                        Text       = transcription,
                        Link       = mediaUri
                    })
                });
            }

            // :)
        }