├── Source ├── Rekognition │ ├── Images │ │ ├── Beatles_Trenter_1963.jpg │ │ ├── 1024px-The_Beatles_in_America.jpg │ │ ├── 800px-State_of_the_Map_2019_-_banner.jpg │ │ ├── Beatles_ad_1965_just_the_beatles_crop.jpg │ │ ├── 1280px-The_Beatles_in_Treslong._NL-HlmNHA_1478_2587K_14.jpg │ │ └── License.txt │ ├── AWSRekognition.dpr │ ├── Forms.Image.dfm │ ├── Forms.Main.dfm │ ├── Forms.Main.pas │ └── Forms.Image.pas ├── Polly │ ├── AWSPollySample.dpr │ ├── Forms.Main.fmx │ └── Forms.Main.pas ├── Lex │ ├── AWSLexSample.dpr │ ├── Forms.Main.dfm │ ├── Forms.Main.pas │ └── AWSLexSample.dproj ├── Translate │ ├── AWSTranslateSample.dpr │ ├── Forms.Main.dfm │ └── Forms.Main.pas ├── Transcribe │ ├── AWSTranscribeSample.dpr │ ├── AWS.Transcribe.VocabularyFilter.pas │ ├── Forms.NewJob.pas │ ├── Forms.VocabularyFilter.dfm │ ├── Forms.NewJob.dfm │ ├── Forms.VocabularyFilter.pas │ ├── Forms.Main.dfm │ ├── Forms.TranscriptionJob.dfm │ ├── AWS.Transcribe.Transcript.pas │ ├── Forms.TranscriptionJob.pas │ └── Forms.Main.pas └── AWSSamples.groupproj ├── README.md ├── .gitignore └── LICENSE /Source/Rekognition/Images/Beatles_Trenter_1963.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landgraf-dev/aws-sdk-delphi-samples/HEAD/Source/Rekognition/Images/Beatles_Trenter_1963.jpg -------------------------------------------------------------------------------- /Source/Rekognition/Images/1024px-The_Beatles_in_America.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landgraf-dev/aws-sdk-delphi-samples/HEAD/Source/Rekognition/Images/1024px-The_Beatles_in_America.jpg -------------------------------------------------------------------------------- /Source/Rekognition/Images/800px-State_of_the_Map_2019_-_banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landgraf-dev/aws-sdk-delphi-samples/HEAD/Source/Rekognition/Images/800px-State_of_the_Map_2019_-_banner.jpg -------------------------------------------------------------------------------- /Source/Rekognition/Images/Beatles_ad_1965_just_the_beatles_crop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landgraf-dev/aws-sdk-delphi-samples/HEAD/Source/Rekognition/Images/Beatles_ad_1965_just_the_beatles_crop.jpg -------------------------------------------------------------------------------- /Source/Rekognition/Images/1280px-The_Beatles_in_Treslong._NL-HlmNHA_1478_2587K_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landgraf-dev/aws-sdk-delphi-samples/HEAD/Source/Rekognition/Images/1280px-The_Beatles_in_Treslong._NL-HlmNHA_1478_2587K_14.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sample projects using AWS SDK for Delphi 2 | 3 | This repository contains sample Delphi projects using [**AWS SDK for Delphi**](https://github.com/landgraf-dev/aws-sdk-delphi). Several Amazon Web Services are used, like AWS Polly, AWS Translate, AWS Lex, among others. 4 | -------------------------------------------------------------------------------- /Source/Polly/AWSPollySample.dpr: -------------------------------------------------------------------------------- 1 | program AWSPollySample; 2 | 3 | uses 4 | System.StartUpCopy, 5 | FMX.Forms, 6 | Forms.Main in 'Forms.Main.pas' {Form7}; 7 | 8 | {$R *.res} 9 | 10 | begin 11 | Application.Initialize; 12 | Application.CreateForm(TForm7, Form7); 13 | Application.Run; 14 | end. 15 | -------------------------------------------------------------------------------- /Source/Lex/AWSLexSample.dpr: -------------------------------------------------------------------------------- 1 | program AWSLexSample; 2 | 3 | uses 4 | Vcl.Forms, 5 | Forms.Main in 'Forms.Main.pas' {Form1}; 6 | 7 | {$R *.res} 8 | 9 | begin 10 | Application.Initialize; 11 | Application.MainFormOnTaskbar := True; 12 | Application.CreateForm(TForm1, Form1); 13 | Application.Run; 14 | end. 15 | -------------------------------------------------------------------------------- /Source/Translate/AWSTranslateSample.dpr: -------------------------------------------------------------------------------- 1 | program AWSTranslateSample; 2 | 3 | uses 4 | Vcl.Forms, 5 | Forms.Main in 'Forms.Main.pas' {MainForm}; 6 | 7 | {$R *.res} 8 | 9 | begin 10 | Application.Initialize; 11 | Application.MainFormOnTaskbar := True; 12 | Application.CreateForm(TMainForm, MainForm); 13 | Application.Run; 14 | end. 15 | -------------------------------------------------------------------------------- /Source/Rekognition/Images/License.txt: -------------------------------------------------------------------------------- 1 | Images is this folder: 2 | 3 | https://commons.wikimedia.org/wiki/File:State_of_the_Map_2019_-_banner.jpg 4 | https://commons.wikimedia.org/wiki/File:Beatles_ad_1965_just_the_beatles_crop.jpg 5 | https://commons.wikimedia.org/wiki/File:The_Beatles_in_America.JPG 6 | https://commons.wikimedia.org/wiki/File:Beatles_Trenter_1963.jpg 7 | https://commons.wikimedia.org/wiki/File:The_Beatles_in_Treslong._NL-HlmNHA_1478_2587K_14.JPG -------------------------------------------------------------------------------- /Source/Rekognition/AWSRekognition.dpr: -------------------------------------------------------------------------------- 1 | program AWSRekognition; 2 | 3 | uses 4 | Vcl.Forms, 5 | Forms.Main in 'Forms.Main.pas' {Form8}, 6 | Forms.Image in 'Forms.Image.pas' {ImageForm}; 7 | 8 | {$R *.res} 9 | 10 | begin 11 | ReportMemoryLeaksOnShutdown := True; 12 | Application.Initialize; 13 | Application.MainFormOnTaskbar := True; 14 | Application.CreateForm(TForm8, Form8); 15 | Application.CreateForm(TImageForm, ImageForm); 16 | Application.Run; 17 | end. 18 | -------------------------------------------------------------------------------- /Source/Transcribe/AWSTranscribeSample.dpr: -------------------------------------------------------------------------------- 1 | program AWSTranscribeSample; 2 | 3 | uses 4 | Vcl.Forms, 5 | AWS.Transcribe.Transcript in 'AWS.Transcribe.Transcript.pas', 6 | AWS.Transcribe.VocabularyFilter in 'AWS.Transcribe.VocabularyFilter.pas', 7 | Forms.Main in 'Forms.Main.pas' {MainForm}, 8 | Forms.TranscriptionJob in 'Forms.TranscriptionJob.pas' {TranscriptionJobForm}, 9 | Forms.VocabularyFilter in 'Forms.VocabularyFilter.pas' {VocabularyFilterForm}, 10 | Forms.NewJob in 'Forms.NewJob.pas' {NewJobForm}; 11 | 12 | {$R *.res} 13 | 14 | begin 15 | Application.Initialize; 16 | Application.MainFormOnTaskbar := True; 17 | Application.CreateForm(TMainForm, MainForm); 18 | Application.Run; 19 | end. 20 | -------------------------------------------------------------------------------- /Source/Rekognition/Forms.Image.dfm: -------------------------------------------------------------------------------- 1 | object ImageForm: TImageForm 2 | Left = 0 3 | Top = 0 4 | BorderStyle = bsSizeToolWin 5 | Caption = 'Image' 6 | ClientHeight = 386 7 | ClientWidth = 500 8 | Color = clBtnFace 9 | Font.Charset = DEFAULT_CHARSET 10 | Font.Color = clWindowText 11 | Font.Height = -11 12 | Font.Name = 'Tahoma' 13 | Font.Style = [] 14 | OldCreateOrder = False 15 | ShowHint = True 16 | OnPaint = FormPaint 17 | OnResize = FormResize 18 | PixelsPerInch = 96 19 | TextHeight = 13 20 | object PaintBox1: TPaintBox 21 | Left = 0 22 | Top = 0 23 | Width = 500 24 | Height = 386 25 | Align = alClient 26 | ParentShowHint = False 27 | ShowHint = False 28 | OnMouseMove = PaintBox1MouseMove 29 | ExplicitLeft = 296 30 | ExplicitTop = 224 31 | ExplicitWidth = 105 32 | ExplicitHeight = 105 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /Source/Transcribe/AWS.Transcribe.VocabularyFilter.pas: -------------------------------------------------------------------------------- 1 | unit AWS.Transcribe.VocabularyFilter; 2 | 3 | interface 4 | 5 | uses 6 | Bcl.Types.Nullable, 7 | AWS.Transcribe; 8 | 9 | type 10 | TVocabularyFilter = class (TVocabularyFilterInfo) 11 | private 12 | FDownloadUri: Nullable; 13 | procedure SetDownloadUri(const AValue: string); 14 | function GetDownloadUri: string; 15 | function GetIsSetDownloadUri: Boolean; 16 | public 17 | property DownloadUri: string read GetDownloadUri write SetDownloadUri; 18 | property IsSetDownloadUri: Boolean read GetIsSetDownloadUri; 19 | end; 20 | 21 | implementation 22 | 23 | { TVocabularyFilter } 24 | 25 | function TVocabularyFilter.GetDownloadUri: string; 26 | begin 27 | Result := FDownloadUri.ValueOrDefault; 28 | end; 29 | 30 | procedure TVocabularyFilter.SetDownloadUri(const AValue: string); 31 | begin 32 | FDownloadUri := AValue; 33 | end; 34 | 35 | function TVocabularyFilter.GetIsSetDownloadUri: Boolean; 36 | begin 37 | Result := FDownloadUri.HasValue; 38 | end; 39 | 40 | end. 41 | -------------------------------------------------------------------------------- /Source/Polly/Forms.Main.fmx: -------------------------------------------------------------------------------- 1 | object Form7: TForm7 2 | Left = 0 3 | Top = 0 4 | Caption = 'Form7' 5 | ClientHeight = 79 6 | ClientWidth = 433 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | DesignerMasterStyle = 0 11 | object Edit1: TEdit 12 | Touch.InteractiveGestures = [LongTap, DoubleTap] 13 | TabOrder = 1 14 | Text = 'Hello, world!' 15 | Position.X = 14.000000000000000000 16 | Position.Y = 32.000000000000000000 17 | Size.Width = 289.000000000000000000 18 | Size.Height = 22.000000000000000000 19 | Size.PlatformDefault = False 20 | end 21 | object Button1: TButton 22 | Position.X = 310.000000000000000000 23 | Position.Y = 31.000000000000000000 24 | Size.Width = 105.000000000000000000 25 | Size.Height = 25.000000000000000000 26 | Size.PlatformDefault = False 27 | TabOrder = 2 28 | Text = 'Speak' 29 | OnClick = Button1Click 30 | end 31 | object MediaPlayer1: TMediaPlayer 32 | Left = 190 33 | Top = 24 34 | end 35 | object Label1: TLabel 36 | Position.X = 14.000000000000000000 37 | Position.Y = 12.000000000000000000 38 | Text = 'Type text:' 39 | TabOrder = 4 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /Source/Rekognition/Forms.Main.dfm: -------------------------------------------------------------------------------- 1 | object Form8: TForm8 2 | Left = 0 3 | Top = 0 4 | BorderStyle = bsSizeToolWin 5 | Caption = 'AWS Rekognition' 6 | ClientHeight = 386 7 | ClientWidth = 158 8 | Color = clBtnFace 9 | Font.Charset = DEFAULT_CHARSET 10 | Font.Color = clWindowText 11 | Font.Height = -11 12 | Font.Name = 'Tahoma' 13 | Font.Style = [] 14 | OldCreateOrder = False 15 | OnShow = FormShow 16 | DesignSize = ( 17 | 158 18 | 386) 19 | PixelsPerInch = 96 20 | TextHeight = 13 21 | object Button1: TButton 22 | Left = 8 23 | Top = 8 24 | Width = 97 25 | Height = 25 26 | Caption = 'Load image...' 27 | TabOrder = 0 28 | OnClick = Button1Click 29 | end 30 | object Button2: TButton 31 | Left = 8 32 | Top = 39 33 | Width = 97 34 | Height = 25 35 | Caption = 'Detect text' 36 | TabOrder = 1 37 | OnClick = Button2Click 38 | end 39 | object Button3: TButton 40 | Left = 8 41 | Top = 183 42 | Width = 97 43 | Height = 25 44 | Caption = 'Detect celebrities' 45 | TabOrder = 2 46 | OnClick = Button3Click 47 | end 48 | object lbText: TListBox 49 | Left = 8 50 | Top = 72 51 | Width = 142 52 | Height = 105 53 | Anchors = [akLeft, akTop, akRight] 54 | ItemHeight = 13 55 | TabOrder = 3 56 | ExplicitWidth = 212 57 | end 58 | object lbCelebrities: TListBox 59 | Left = 8 60 | Top = 214 61 | Width = 142 62 | Height = 163 63 | Anchors = [akLeft, akTop, akRight, akBottom] 64 | ItemHeight = 13 65 | TabOrder = 4 66 | ExplicitWidth = 212 67 | ExplicitHeight = 105 68 | end 69 | object OpenPictureDialog1: TOpenPictureDialog 70 | Left = 73 71 | Top = 104 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Uncomment these types if you want even more clean repository. But be careful. 2 | # It can make harm to an existing project source. Read explanations below. 3 | # 4 | # Resource files are binaries containing manifest, project icon and version info. 5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. 6 | #*.res 7 | # 8 | # Type library file (binary). In old Delphi versions it should be stored. 9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored. 10 | #*.tlb 11 | # 12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7. 13 | # Uncomment this if you are not using diagrams or use newer Delphi version. 14 | #*.ddp 15 | # 16 | # Visual LiveBindings file. Added in Delphi XE2. 17 | # Uncomment this if you are not using LiveBindings Designer. 18 | #*.vlb 19 | # 20 | # Deployment Manager configuration file for your project. Added in Delphi XE2. 21 | # Uncomment this if it is not mobile development and you do not use remote debug feature. 22 | #*.deployproj 23 | # 24 | # C++ object files produced when C/C++ Output file generation is configured. 25 | # Uncomment this if you are not using external objects (zlib library for example). 26 | #*.obj 27 | # 28 | 29 | # Delphi compiler-generated binaries (safe to delete) 30 | *.exe 31 | *.dll 32 | *.bpl 33 | *.bpi 34 | *.dcp 35 | *.so 36 | *.apk 37 | *.drc 38 | *.map 39 | *.dres 40 | *.rsm 41 | *.tds 42 | *.dcu 43 | *.lib 44 | *.a 45 | *.o 46 | *.ocx 47 | 48 | # Delphi autogenerated files (duplicated info) 49 | *.cfg 50 | *.hpp 51 | *Resource.rc 52 | 53 | # Delphi local files (user-specific info) 54 | *.local 55 | *.identcache 56 | *.projdata 57 | *.tvsconfig 58 | *.dsk 59 | 60 | # Delphi history and backups 61 | __history/ 62 | __recovery/ 63 | *.~* 64 | 65 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi) 66 | *.stat 67 | 68 | Source/Lex/AWSLexSample.res 69 | Source/Polly/AWSPollySample.res 70 | Source/Translate/AWSTranslateSample.res 71 | Source/Rekognition/AWSRekognition.res 72 | *.dsv 73 | Source/Transcribe/AWSTranscribeSample.res 74 | -------------------------------------------------------------------------------- /Source/Lex/Forms.Main.dfm: -------------------------------------------------------------------------------- 1 | object Form1: TForm1 2 | Left = 0 3 | Top = 0 4 | Caption = 'Form1' 5 | ClientHeight = 391 6 | ClientWidth = 501 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | OnCreate = FormCreate 14 | TextHeight = 13 15 | object PageControl1: TPageControl 16 | Left = 0 17 | Top = 0 18 | Width = 501 19 | Height = 391 20 | ActivePage = TabSheet1 21 | Align = alClient 22 | TabOrder = 0 23 | object TabSheet1: TTabSheet 24 | Caption = 'Chat' 25 | DesignSize = ( 26 | 493 27 | 363) 28 | object Button1: TButton 29 | Left = 2 30 | Top = 5 31 | Width = 161 32 | Height = 25 33 | Caption = 'Restart chat' 34 | TabOrder = 0 35 | OnClick = Button1Click 36 | end 37 | object mmChat: TMemo 38 | Left = 2 39 | Top = 36 40 | Width = 486 41 | Height = 298 42 | Anchors = [akLeft, akTop, akRight, akBottom] 43 | TabOrder = 1 44 | end 45 | object edMessage: TEdit 46 | Left = 2 47 | Top = 339 48 | Width = 421 49 | Height = 21 50 | Anchors = [akLeft, akRight, akBottom] 51 | TabOrder = 2 52 | end 53 | object Send: TButton 54 | Left = 431 55 | Top = 339 56 | Width = 57 57 | Height = 21 58 | Anchors = [akRight, akBottom] 59 | Caption = 'Send' 60 | Default = True 61 | TabOrder = 3 62 | OnClick = SendClick 63 | end 64 | end 65 | object tsLog: TTabSheet 66 | Caption = 'Log' 67 | ImageIndex = 1 68 | object mmLog: TMemo 69 | Left = 0 70 | Top = 0 71 | Width = 493 72 | Height = 363 73 | Align = alClient 74 | TabOrder = 0 75 | ExplicitLeft = 104 76 | ExplicitTop = 200 77 | ExplicitWidth = 185 78 | ExplicitHeight = 89 79 | end 80 | end 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /Source/Polly/Forms.Main.pas: -------------------------------------------------------------------------------- 1 | unit Forms.Main; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, System.IOUtils, 7 | FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls, FMX.Controls.Presentation, FMX.Edit, 8 | FMX.Media, AWS.Polly, AWS.RegionEndpoints; 9 | 10 | type 11 | TForm7 = class(TForm) 12 | MediaPlayer1: TMediaPlayer; 13 | Edit1: TEdit; 14 | Button1: TButton; 15 | Label1: TLabel; 16 | procedure Button1Click(Sender: TObject); 17 | private 18 | procedure PlayAudioStream(Stream: TStream); 19 | public 20 | end; 21 | 22 | var 23 | Form7: TForm7; 24 | 25 | implementation 26 | 27 | {$R *.fmx} 28 | 29 | procedure TForm7.Button1Click(Sender: TObject); 30 | var 31 | Client: IAmazonPolly; 32 | Request: ISynthesizeSpeechRequest; 33 | Response: ISynthesizeSpeechResponse; 34 | begin 35 | // Create client 36 | Client := TAmazonPollyClient.Create(TRegionEndpoints.USWest2); 37 | 38 | // Build request 39 | Request := TSynthesizeSpeechRequest.Create; 40 | Request.Text := Edit1.Text; 41 | Request.VoiceId := TVoiceId.Joanna; 42 | Request.OutputFormat := TOutputFormat.Mp3; 43 | Request.LanguageCode := TLanguageCode.EnUS; 44 | 45 | // Retrieve response 46 | Response := Client.SynthesizeSpeech(Request); 47 | 48 | // Play audio 49 | PlayAudioStream(Response.AudioStream); 50 | end; 51 | 52 | procedure TForm7.PlayAudioStream(Stream: TStream); 53 | const 54 | BufferSize = 65536; 55 | var 56 | Buffer: TArray; 57 | FileName: string; 58 | FileStream: TFileStream; 59 | BytesRead: Integer; 60 | begin 61 | FileName := TPath.GetTempFileName; 62 | 63 | // Copy audio stream to file 64 | FileStream := TFileStream.Create(FileName, fmCreate); 65 | try 66 | SetLength(Buffer, BufferSize); 67 | repeat 68 | BytesRead := Stream.Read(Buffer[0], BufferSize); 69 | FileStream.Write(Buffer[0], BytesRead); 70 | until BytesRead < BufferSize; 71 | finally 72 | FileStream.Free; 73 | end; 74 | 75 | // Play audio 76 | MediaPlayer1.FileName := FileName; 77 | MediaPlayer1.Play; 78 | 79 | // Delete file 80 | TFile.Delete(FileName); 81 | end; 82 | 83 | end. 84 | -------------------------------------------------------------------------------- /Source/Translate/Forms.Main.dfm: -------------------------------------------------------------------------------- 1 | object MainForm: TMainForm 2 | Left = 0 3 | Top = 0 4 | ActiveControl = MemoLeft 5 | Caption = 'AWS Translate' 6 | ClientHeight = 350 7 | ClientWidth = 451 8 | Color = clBtnFace 9 | Font.Charset = DEFAULT_CHARSET 10 | Font.Color = clWindowText 11 | Font.Height = -11 12 | Font.Name = 'Tahoma' 13 | Font.Style = [] 14 | OldCreateOrder = False 15 | OnCreate = FormCreate 16 | PixelsPerInch = 96 17 | TextHeight = 13 18 | object Splitter1: TSplitter 19 | Left = 210 20 | Top = 0 21 | Height = 350 22 | ExplicitLeft = 264 23 | ExplicitTop = 144 24 | ExplicitHeight = 100 25 | end 26 | object Panel1: TPanel 27 | Left = 0 28 | Top = 0 29 | Width = 210 30 | Height = 350 31 | Align = alLeft 32 | BevelOuter = bvNone 33 | TabOrder = 0 34 | DesignSize = ( 35 | 210 36 | 350) 37 | object cbLanguageLeft: TComboBox 38 | Left = 5 39 | Top = 5 40 | Width = 200 41 | Height = 21 42 | Style = csDropDownList 43 | TabOrder = 0 44 | end 45 | object MemoLeft: TMemo 46 | Left = 5 47 | Top = 32 48 | Width = 201 49 | Height = 311 50 | Anchors = [akLeft, akTop, akRight, akBottom] 51 | Lines.Strings = ( 52 | 'Hello, world!') 53 | TabOrder = 1 54 | end 55 | end 56 | object Panel2: TPanel 57 | Left = 237 58 | Top = 0 59 | Width = 214 60 | Height = 350 61 | Align = alClient 62 | BevelOuter = bvNone 63 | TabOrder = 1 64 | ExplicitWidth = 274 65 | DesignSize = ( 66 | 214 67 | 350) 68 | object cbLanguageRight: TComboBox 69 | Left = 5 70 | Top = 5 71 | Width = 200 72 | Height = 21 73 | Style = csDropDownList 74 | TabOrder = 0 75 | end 76 | object MemoRight: TMemo 77 | Left = 5 78 | Top = 32 79 | Width = 202 80 | Height = 311 81 | Anchors = [akLeft, akTop, akRight, akBottom] 82 | TabOrder = 1 83 | ExplicitWidth = 211 84 | end 85 | end 86 | object Panel3: TPanel 87 | Left = 213 88 | Top = 0 89 | Width = 24 90 | Height = 350 91 | Align = alLeft 92 | BevelOuter = bvNone 93 | TabOrder = 2 94 | object SpeedButton1: TSpeedButton 95 | Left = 0 96 | Top = 32 97 | Width = 23 98 | Height = 22 99 | Caption = '->' 100 | OnClick = SpeedButton1Click 101 | end 102 | object SpeedButton2: TSpeedButton 103 | Left = 0 104 | Top = 60 105 | Width = 23 106 | Height = 22 107 | Caption = '<-' 108 | OnClick = SpeedButton2Click 109 | end 110 | end 111 | end 112 | -------------------------------------------------------------------------------- /Source/Rekognition/Forms.Main.pas: -------------------------------------------------------------------------------- 1 | unit Forms.Main; 2 | 3 | interface 4 | 5 | uses 6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, 7 | System.IOUtils, AWS.Rekognition, Vcl.Graphics, PNGImage, JPEG, 8 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.ExtDlgs, Vcl.StdCtrls; 9 | 10 | type 11 | TForm8 = class(TForm) 12 | Button1: TButton; 13 | OpenPictureDialog1: TOpenPictureDialog; 14 | Button2: TButton; 15 | Button3: TButton; 16 | lbText: TListBox; 17 | lbCelebrities: TListBox; 18 | procedure Button1Click(Sender: TObject); 19 | procedure Button2Click(Sender: TObject); 20 | procedure FormShow(Sender: TObject); 21 | procedure Button3Click(Sender: TObject); 22 | private 23 | FClient: IAmazonRekognition; 24 | procedure LoadImage(const FileName: string); 25 | function Client: IAmazonRekognition; 26 | function CreateAWSImage: AWS.Rekognition.TImage; 27 | public 28 | end; 29 | 30 | var 31 | Form8: TForm8; 32 | 33 | implementation 34 | 35 | {$R *.dfm} 36 | 37 | uses Forms.Image; 38 | 39 | procedure TForm8.Button1Click(Sender: TObject); 40 | begin 41 | if OpenPictureDialog1.Execute then 42 | LoadImage(OpenPictureDialog1.FileName); 43 | end; 44 | 45 | procedure TForm8.Button2Click(Sender: TObject); 46 | var 47 | Request: IDetectTextRequest; 48 | Response: IDetectTextResponse; 49 | TextDetection: TTextDetection; 50 | begin 51 | Request := TDetectTextRequest.Create; 52 | Request.Image := CreateAWSImage; 53 | Response := Client.DetectText(Request); 54 | for TextDetection in Response.TextDetections do 55 | if not TextDetection.IsSetParentId then 56 | lbText.AddItem(TextDetection.DetectedText, TextDetection); 57 | Response.KeepTextDetections := True; 58 | ImageForm.TextDetections := Response.TextDetections; 59 | end; 60 | 61 | procedure TForm8.Button3Click(Sender: TObject); 62 | var 63 | Request: IRecognizeCelebritiesRequest; 64 | Response: IRecognizeCelebritiesResponse; 65 | Celebrity: TCelebrity; 66 | begin 67 | Request := TRecognizeCelebritiesRequest.Create; 68 | Request.Image := CreateAWSImage; 69 | Response := Client.RecognizeCelebrities(Request); 70 | for Celebrity in Response.CelebrityFaces do 71 | lbCelebrities.AddItem(Celebrity.Name, Celebrity); 72 | Response.KeepCelebrityFaces := True; 73 | ImageForm.Celebrities := Response.CelebrityFaces; 74 | end; 75 | 76 | function TForm8.Client: IAmazonRekognition; 77 | begin 78 | if FClient = nil then 79 | FClient := TAmazonRekognitionClient.Create; 80 | Result := FClient; 81 | end; 82 | 83 | function TForm8.CreateAWSImage: AWS.Rekognition.TImage; 84 | begin 85 | Result := AWS.Rekognition.TImage.Create; 86 | Result.Bytes := TBytesStream.Create; 87 | ImageForm.Image.SaveToStream(Result.Bytes); 88 | Result.Bytes.Position := 0; 89 | end; 90 | 91 | procedure TForm8.FormShow(Sender: TObject); 92 | var 93 | FileName: string; 94 | begin 95 | FileName := TPath.Combine(TPath.GetDirectoryName(ParamStr(0)), '..\..\images\Beatles_Trenter_1963.jpg'); 96 | if TFile.Exists(FileName) then 97 | LoadImage(FileName); 98 | end; 99 | 100 | procedure TForm8.LoadImage(const FileName: string); 101 | begin 102 | ImageForm.Image.LoadFromFile(FileName); 103 | lbText.Clear; 104 | lbCelebrities.Clear; 105 | if not ImageForm.Visible then 106 | begin 107 | ImageForm.Top := Self.Top; 108 | ImageForm.Left := Self.Left + Self.ClientWidth + 1; 109 | end; 110 | ImageForm.Show; 111 | end; 112 | 113 | end. 114 | -------------------------------------------------------------------------------- /Source/AWSSamples.groupproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | {6A02A6BC-EDF7-42AB-AF7E-C243588F03B6} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Default.Personality.12 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /Source/Transcribe/Forms.NewJob.pas: -------------------------------------------------------------------------------- 1 | unit Forms.NewJob; 2 | 3 | interface 4 | 5 | uses 6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, 7 | Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons; 8 | 9 | type 10 | TNewJobForm = class(TForm) 11 | JobNameEdit: TEdit; 12 | Label1: TLabel; 13 | Label2: TLabel; 14 | MediaUriEdit: TEdit; 15 | Label3: TLabel; 16 | Label4: TLabel; 17 | VocabularyFilterEdit: TComboBox; 18 | Label5: TLabel; 19 | ContentRedactionEdit: TComboBox; 20 | ConfirmButton: TBitBtn; 21 | CancelButton: TBitBtn; 22 | Label6: TLabel; 23 | LanguageCodeEdit: TComboBox; 24 | procedure FormShow(Sender: TObject); 25 | procedure JobNameEditChange(Sender: TObject); 26 | procedure FormCreate(Sender: TObject); 27 | private 28 | function GetJobName: string; 29 | function GetLanguageCode: string; 30 | function GetMediaUri: string; 31 | function GetVocabularyFilter: string; 32 | function GetContentRedaction: string; 33 | procedure ValidateForm; 34 | procedure FillFilterOprions; 35 | procedure FillLanguageOptions; 36 | public 37 | procedure SetAvailableFilter(const AFilterName: string); 38 | property JobName: string read GetJobName; 39 | property LanguageCode: string read GetLanguageCode; 40 | property MediaUri: string read GetMediaUri; 41 | property VocabularyFilter: string read GetVocabularyFilter; 42 | property ContentRedaction: string read GetContentRedaction; 43 | end; 44 | 45 | implementation 46 | 47 | {$R *.dfm} 48 | 49 | uses 50 | AWS.Transcribe; 51 | 52 | const 53 | SAMPLE_MEDIA_URI = 'https://aws-ml-blog.s3.amazonaws.com/artifacts/transcribe_audio_processing/medical-diarization.wav'; 54 | VALID_LANG_CODES = 'af-ZA,ar-AE,ar-SA,cy-GB,da-DK,de-CH,de-DE,en-AB,en-AU,en-GB,en-IE,en-IN,en-US,en-WL,es-ES,es-US,fa-IR,fr-CA,fr-FR,ga-IE,gd-GB,he-IL,hi-IN,id-ID,it-IT,ja-JP,ko-KR,ms-MY,nl-NL,pt-BR,pt-PT,ru-RU,ta-IN,te-IN,tr-TR,zh-CN,zh-TW,th-TH,en-ZA,en-NZ'; 55 | 56 | procedure TNewJobForm.FormCreate(Sender: TObject); 57 | begin 58 | FillLanguageOptions; 59 | FillFilterOprions; 60 | end; 61 | 62 | procedure TNewJobForm.FormShow(Sender: TObject); 63 | begin 64 | MediaUriEdit.Text := SAMPLE_MEDIA_URI; 65 | LanguageCodeEdit.ItemIndex := LanguageCodeEdit.Items.IndexOf(TLanguageCode.EnUS.Value); // since sample media is en-US 66 | VocabularyFilterEdit.ItemIndex := 0; 67 | ContentRedactionEdit.ItemIndex := 0; 68 | end; 69 | 70 | procedure TNewJobForm.FillLanguageOptions; 71 | begin 72 | LanguageCodeEdit.Items.Clear; 73 | LanguageCodeEdit.Items.CommaText := VALID_LANG_CODES; 74 | LanguageCodeEdit.Items.Insert(0, 'Automatically identify language'); 75 | end; 76 | 77 | procedure TNewJobForm.FillFilterOprions; 78 | begin 79 | VocabularyFilterEdit.Items.Clear; 80 | VocabularyFilterEdit.Items.Add('None'); 81 | end; 82 | 83 | procedure TNewJobForm.SetAvailableFilter(const AFilterName: string); 84 | begin 85 | VocabularyFilterEdit.Items.Add(AFilterName); 86 | end; 87 | 88 | function TNewJobForm.GetJobName: string; 89 | begin 90 | Result := Trim(JobNameEdit.Text); 91 | end; 92 | 93 | function TNewJobForm.GetLanguageCode: string; 94 | begin 95 | if LanguageCodeEdit.ItemIndex>0 then 96 | Result := LanguageCodeEdit.Text 97 | else 98 | Result := ''; // identify language 99 | end; 100 | 101 | function TNewJobForm.GetMediaUri: string; 102 | begin 103 | Result := MediaUriEdit.Text; 104 | end; 105 | 106 | function TNewJobForm.GetVocabularyFilter: string; 107 | begin 108 | if VocabularyFilterEdit.ItemIndex>0 then 109 | Result := VocabularyFilterEdit.Text 110 | else 111 | Result := ''; // do not apply a vocabulary filter 112 | end; 113 | 114 | function TNewJobForm.GetContentRedaction: string; 115 | begin 116 | case ContentRedactionEdit.ItemIndex of 117 | 1: Result := TRedactionOutput.Redacted.Value; 118 | 2: Result := TRedactionOutput.Redacted_and_unredacted.Value; 119 | else 120 | Result := ''; // do not apply content redaction 121 | end; 122 | end; 123 | 124 | procedure TNewJobForm.JobNameEditChange(Sender: TObject); 125 | begin 126 | ValidateForm; 127 | end; 128 | 129 | procedure TNewJobForm.ValidateForm; 130 | begin 131 | ConfirmButton.Enabled := (JobName<>'') and (Pos(' ', JobName)=0) and (MediaUri<>''); 132 | end; 133 | 134 | end. 135 | -------------------------------------------------------------------------------- /Source/Lex/Forms.Main.pas: -------------------------------------------------------------------------------- 1 | unit Forms.Main; 2 | 3 | interface 4 | 5 | uses 6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, 7 | System.Generics.Collections, 8 | AWS.LexRuntimeV2, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls; 9 | 10 | type 11 | TForm1 = class(TForm) 12 | PageControl1: TPageControl; 13 | TabSheet1: TTabSheet; 14 | Button1: TButton; 15 | mmChat: TMemo; 16 | edMessage: TEdit; 17 | Send: TButton; 18 | tsLog: TTabSheet; 19 | mmLog: TMemo; 20 | procedure Button1Click(Sender: TObject); 21 | procedure FormCreate(Sender: TObject); 22 | procedure SendClick(Sender: TObject); 23 | private const 24 | BotId = 'XXXXXXX'; 25 | BotAliasId = 'XXXXXX'; 26 | LocaleId = 'en_US'; 27 | private 28 | FClient: IAmazonLexRuntimeV2; 29 | FSessionId: string; 30 | function Client: IAmazonLexRuntimeV2; 31 | procedure StartChat; 32 | function GetRecognizeTextV2Response(const BotId, BotAliasId, LocaleId, 33 | SessionId, UserInput: string): IRecognizeTextResponse; 34 | procedure AddToChat(const Msg: string); 35 | procedure LogResponse(Response: IRecognizeTextResponse); 36 | // procedure Log(const Msg: string); 37 | procedure OrderFullfilled(Intent: TIntent); 38 | public 39 | end; 40 | 41 | var 42 | Form1: TForm1; 43 | 44 | implementation 45 | 46 | {$R *.dfm} 47 | 48 | procedure TForm1.AddToChat(const Msg: string); 49 | begin 50 | mmChat.Lines.Add(Msg); 51 | mmChat.ScrollBy(0, mmChat.Lines.Count); 52 | end; 53 | 54 | procedure TForm1.Button1Click(Sender: TObject); 55 | begin 56 | StartChat; 57 | edMessage.SetFocus; 58 | end; 59 | 60 | function TForm1.Client: IAmazonLexRuntimeV2; 61 | begin 62 | if FClient = nil then 63 | FClient := TAmazonLexRuntimeV2Client.Create; 64 | Result := FClient; 65 | end; 66 | 67 | procedure TForm1.FormCreate(Sender: TObject); 68 | begin 69 | StartChat; 70 | end; 71 | 72 | function TForm1.GetRecognizeTextV2Response(const BotId, BotAliasId, LocaleId, 73 | SessionId, UserInput: string): IRecognizeTextResponse; 74 | var 75 | Request: IRecognizeTextRequest; 76 | begin 77 | Request := TRecognizeTextRequest.Create; 78 | Request.BotAliasId := BotAliasId; 79 | Request.BotId := BotId; 80 | Request.LocaleId := LocaleId; 81 | Request.SessionId := SessionId; 82 | Request.Text := UserInput; 83 | Result := Client.RecognizeText(Request); 84 | LogResponse(Result); 85 | end; 86 | 87 | //procedure TForm1.Log(const Msg: string); 88 | //begin 89 | // mmLog.Lines.Add(Msg); 90 | // mmLog.ScrollBy(0, mmLog.Lines.Count); 91 | //end; 92 | 93 | procedure TForm1.LogResponse(Response: IRecognizeTextResponse); 94 | begin 95 | end; 96 | 97 | procedure TForm1.OrderFullfilled(Intent: TIntent); 98 | var 99 | SlotValue: string; 100 | Slot: TPair; 101 | begin 102 | AddToChat('System: Your order will be processed with following information:'); 103 | for Slot in Intent.Slots do 104 | begin 105 | if (Slot.Value <> nil) and (Slot.Value.Value <> nil) then 106 | SlotValue := Slot.Value.Value.InterpretedValue 107 | else 108 | SlotValue := '(not specified)'; 109 | AddToChat(Format('%s: %s', [Slot.Key, SlotValue])); 110 | end; 111 | end; 112 | 113 | procedure TForm1.SendClick(Sender: TObject); 114 | var 115 | UserInput: string; 116 | Response: IRecognizeTextResponse; 117 | Msg: TMessage; 118 | LocalBotId: string; 119 | LocalBotAliasId: string; 120 | begin 121 | UserInput := edMessage.Text; 122 | AddToChat('You: ' + UserInput); 123 | edMessage.Text := ''; 124 | Application.ProcessMessages; 125 | 126 | LocalBotId := GetEnvironmentVariable('AWS_DELPHI_SAMPLES_BOTID'); 127 | if LocalBotId = '' then 128 | LocalBotId := BotId; 129 | 130 | LocalBotAliasId := GetEnvironmentVariable('AWS_DELPHI_SAMPLES_BOTALIASID'); 131 | if LocalBotAliasId = '' then 132 | LocalBotAliasId := BotAliasId; 133 | 134 | Response := GetRecognizeTextV2Response(LocalBotId, LocalBotAliasId, LocaleId, FSessionId, UserInput); 135 | for Msg in Response.Messages do 136 | AddToChat('Bot: ' + Msg.Content); 137 | if Response.IsSetSessionStateValue and Response.SessionStateValue.IsSetIntent 138 | and (Response.SessionStateValue.Intent.ConfirmationState = TConfirmationState.Confirmed) then 139 | OrderFullfilled(Response.SessionStateValue.Intent); 140 | end; 141 | 142 | procedure TForm1.StartChat; 143 | begin 144 | FSessionId := TGuid.NewGuid.ToString.Substring(1, 36); 145 | mmChat.Lines.Clear; 146 | end; 147 | 148 | end. 149 | -------------------------------------------------------------------------------- /Source/Transcribe/Forms.VocabularyFilter.dfm: -------------------------------------------------------------------------------- 1 | object VocabularyFilterForm: TVocabularyFilterForm 2 | Left = 0 3 | Top = 0 4 | BorderStyle = bsDialog 5 | Caption = 'Vocabulary Filter' 6 | ClientHeight = 581 7 | ClientWidth = 484 8 | Color = clBtnFace 9 | Font.Charset = DEFAULT_CHARSET 10 | Font.Color = clWindowText 11 | Font.Height = -12 12 | Font.Name = 'Segoe UI' 13 | Font.Style = [] 14 | Position = poScreenCenter 15 | OnCreate = FormCreate 16 | OnShow = FormShow 17 | TextHeight = 15 18 | object Panel1: TPanel 19 | Left = 0 20 | Top = 541 21 | Width = 484 22 | Height = 40 23 | Align = alBottom 24 | BevelOuter = bvNone 25 | TabOrder = 0 26 | object ConfirmButton: TBitBtn 27 | AlignWithMargins = True 28 | Left = 302 29 | Top = 4 30 | Width = 85 31 | Height = 32 32 | Margins.Left = 4 33 | Margins.Top = 4 34 | Margins.Right = 4 35 | Margins.Bottom = 4 36 | Align = alRight 37 | Enabled = False 38 | Kind = bkOK 39 | NumGlyphs = 2 40 | TabOrder = 0 41 | end 42 | object CancelButton: TBitBtn 43 | AlignWithMargins = True 44 | Left = 395 45 | Top = 4 46 | Width = 85 47 | Height = 32 48 | Margins.Left = 4 49 | Margins.Top = 4 50 | Margins.Right = 4 51 | Margins.Bottom = 4 52 | Align = alRight 53 | Kind = bkCancel 54 | NumGlyphs = 2 55 | TabOrder = 1 56 | end 57 | end 58 | object PageControl: TPageControl 59 | AlignWithMargins = True 60 | Left = 4 61 | Top = 4 62 | Width = 476 63 | Height = 533 64 | Margins.Left = 4 65 | Margins.Top = 4 66 | Margins.Right = 4 67 | Margins.Bottom = 4 68 | ActivePage = FilterDetailsTab 69 | Align = alClient 70 | TabOrder = 1 71 | object FilterDetailsTab: TTabSheet 72 | Caption = 'Filter Details' 73 | object Panel2: TPanel 74 | Left = 0 75 | Top = 0 76 | Width = 468 77 | Height = 503 78 | Margins.Left = 4 79 | Margins.Top = 8 80 | Margins.Right = 4 81 | Margins.Bottom = 4 82 | Align = alClient 83 | BevelOuter = bvNone 84 | BorderWidth = 20 85 | TabOrder = 0 86 | object Label1: TLabel 87 | Left = 20 88 | Top = 20 89 | Width = 428 90 | Height = 20 91 | Align = alTop 92 | AutoSize = False 93 | Caption = 'Vocabulary Filter Name' 94 | ExplicitLeft = 0 95 | ExplicitTop = 0 96 | ExplicitWidth = 486 97 | end 98 | object Label2: TLabel 99 | AlignWithMargins = True 100 | Left = 20 101 | Top = 87 102 | Width = 428 103 | Height = 20 104 | Margins.Left = 0 105 | Margins.Top = 24 106 | Margins.Right = 0 107 | Margins.Bottom = 0 108 | Align = alTop 109 | AutoSize = False 110 | Caption = 'Language Code' 111 | ExplicitLeft = 0 112 | ExplicitTop = 52 113 | ExplicitWidth = 486 114 | end 115 | object Label6: TLabel 116 | AlignWithMargins = True 117 | Left = 20 118 | Top = 154 119 | Width = 428 120 | Height = 20 121 | Margins.Left = 0 122 | Margins.Top = 24 123 | Margins.Right = 0 124 | Margins.Bottom = 0 125 | Align = alTop 126 | AutoSize = False 127 | Caption = 'Words' 128 | ExplicitLeft = 5 129 | ExplicitTop = 70 130 | ExplicitWidth = 524 131 | end 132 | object FilterNameEdit: TEdit 133 | Left = 20 134 | Top = 40 135 | Width = 428 136 | Height = 23 137 | Align = alTop 138 | TabOrder = 0 139 | OnChange = OnEditChange 140 | end 141 | object LanguageCodeEdit: TComboBox 142 | Left = 20 143 | Top = 107 144 | Width = 428 145 | Height = 23 146 | Align = alTop 147 | Style = csDropDownList 148 | TabOrder = 1 149 | Items.Strings = ( 150 | 'Auto-detect') 151 | end 152 | object WordsMemo: TMemo 153 | Left = 20 154 | Top = 174 155 | Width = 428 156 | Height = 309 157 | Align = alClient 158 | TabOrder = 2 159 | OnChange = OnEditChange 160 | end 161 | end 162 | end 163 | end 164 | end 165 | -------------------------------------------------------------------------------- /Source/Transcribe/Forms.NewJob.dfm: -------------------------------------------------------------------------------- 1 | object NewJobForm: TNewJobForm 2 | Left = 0 3 | Top = 0 4 | BorderStyle = bsDialog 5 | BorderWidth = 20 6 | Caption = 'New Transcribe Job' 7 | ClientHeight = 391 8 | ClientWidth = 504 9 | Color = clBtnFace 10 | Font.Charset = DEFAULT_CHARSET 11 | Font.Color = clWindowText 12 | Font.Height = -12 13 | Font.Name = 'Segoe UI' 14 | Font.Style = [] 15 | Position = poScreenCenter 16 | OnCreate = FormCreate 17 | OnShow = FormShow 18 | TextHeight = 15 19 | object Label1: TLabel 20 | Left = 0 21 | Top = 0 22 | Width = 504 23 | Height = 20 24 | Align = alTop 25 | AutoSize = False 26 | Caption = 'Job Name' 27 | ExplicitWidth = 486 28 | end 29 | object Label2: TLabel 30 | AlignWithMargins = True 31 | Left = 0 32 | Top = 67 33 | Width = 504 34 | Height = 20 35 | Margins.Left = 0 36 | Margins.Top = 24 37 | Margins.Right = 0 38 | Margins.Bottom = 0 39 | Align = alTop 40 | AutoSize = False 41 | Caption = 'Language Code' 42 | ExplicitTop = 52 43 | ExplicitWidth = 486 44 | end 45 | object Label3: TLabel 46 | AlignWithMargins = True 47 | Left = 2 48 | Top = 179 49 | Width = 502 50 | Height = 13 51 | Margins.Left = 2 52 | Margins.Top = 2 53 | Margins.Right = 0 54 | Margins.Bottom = 0 55 | Align = alTop 56 | Caption = 57 | 'Amazon S3 location. Supported formats are MP3, MP4, WAV, FLAC, O' + 58 | 'GG, AMR and WEBM' 59 | Font.Charset = DEFAULT_CHARSET 60 | Font.Color = clBlue 61 | Font.Height = -11 62 | Font.Name = 'Segoe UI' 63 | Font.Style = [fsItalic] 64 | ParentFont = False 65 | ExplicitWidth = 423 66 | end 67 | object Label4: TLabel 68 | AlignWithMargins = True 69 | Left = 0 70 | Top = 216 71 | Width = 504 72 | Height = 20 73 | Margins.Left = 0 74 | Margins.Top = 24 75 | Margins.Right = 0 76 | Margins.Bottom = 0 77 | Align = alTop 78 | AutoSize = False 79 | Caption = 'Vocabulary Filter' 80 | ExplicitLeft = -5 81 | ExplicitTop = 263 82 | ExplicitWidth = 524 83 | end 84 | object Label5: TLabel 85 | AlignWithMargins = True 86 | Left = 0 87 | Top = 283 88 | Width = 504 89 | Height = 20 90 | Margins.Left = 0 91 | Margins.Top = 24 92 | Margins.Right = 0 93 | Margins.Bottom = 0 94 | Align = alTop 95 | AutoSize = False 96 | Caption = 'Content redaction' 97 | ExplicitLeft = -5 98 | ExplicitTop = 263 99 | ExplicitWidth = 524 100 | end 101 | object Label6: TLabel 102 | AlignWithMargins = True 103 | Left = 0 104 | Top = 134 105 | Width = 504 106 | Height = 20 107 | Margins.Left = 0 108 | Margins.Top = 24 109 | Margins.Right = 0 110 | Margins.Bottom = 0 111 | Align = alTop 112 | AutoSize = False 113 | Caption = 'Media URI' 114 | ExplicitLeft = 5 115 | ExplicitTop = 70 116 | ExplicitWidth = 524 117 | end 118 | object JobNameEdit: TEdit 119 | Left = 0 120 | Top = 20 121 | Width = 504 122 | Height = 23 123 | Align = alTop 124 | TabOrder = 0 125 | OnChange = JobNameEditChange 126 | end 127 | object MediaUriEdit: TEdit 128 | Left = 0 129 | Top = 154 130 | Width = 504 131 | Height = 23 132 | Align = alTop 133 | TabOrder = 2 134 | OnChange = JobNameEditChange 135 | end 136 | object VocabularyFilterEdit: TComboBox 137 | Left = 0 138 | Top = 236 139 | Width = 504 140 | Height = 23 141 | Align = alTop 142 | Style = csDropDownList 143 | TabOrder = 3 144 | Items.Strings = ( 145 | 'None') 146 | end 147 | object ContentRedactionEdit: TComboBox 148 | Left = 0 149 | Top = 303 150 | Width = 504 151 | Height = 23 152 | Align = alTop 153 | Style = csDropDownList 154 | TabOrder = 4 155 | Items.Strings = ( 156 | 'No' 157 | 'Yes (output redacted transcript only)' 158 | 'Yes (output redacted and unredacted transcripts)') 159 | end 160 | object ConfirmButton: TBitBtn 161 | Left = 167 162 | Top = 360 163 | Width = 85 164 | Height = 25 165 | Kind = bkOK 166 | NumGlyphs = 2 167 | TabOrder = 5 168 | end 169 | object CancelButton: TBitBtn 170 | Left = 255 171 | Top = 360 172 | Width = 85 173 | Height = 25 174 | Kind = bkCancel 175 | NumGlyphs = 2 176 | TabOrder = 6 177 | end 178 | object LanguageCodeEdit: TComboBox 179 | Left = 0 180 | Top = 87 181 | Width = 504 182 | Height = 23 183 | Align = alTop 184 | Style = csDropDownList 185 | TabOrder = 1 186 | Items.Strings = ( 187 | 'Auto-detect') 188 | end 189 | end 190 | -------------------------------------------------------------------------------- /Source/Transcribe/Forms.VocabularyFilter.pas: -------------------------------------------------------------------------------- 1 | unit Forms.VocabularyFilter; 2 | 3 | interface 4 | 5 | uses 6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, 7 | Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons, 8 | Vcl.ExtCtrls, Vcl.ComCtrls, AWS.Transcribe, AWS.Transcribe.VocabularyFilter; 9 | 10 | type 11 | TVocabularyFilterForm = class(TForm) 12 | Panel1: TPanel; 13 | ConfirmButton: TBitBtn; 14 | CancelButton: TBitBtn; 15 | PageControl: TPageControl; 16 | FilterDetailsTab: TTabSheet; 17 | Panel2: TPanel; 18 | Label1: TLabel; 19 | Label2: TLabel; 20 | Label6: TLabel; 21 | FilterNameEdit: TEdit; 22 | LanguageCodeEdit: TComboBox; 23 | WordsMemo: TMemo; 24 | procedure FormCreate(Sender: TObject); 25 | procedure FormShow(Sender: TObject); 26 | procedure OnEditChange(Sender: TObject); 27 | private 28 | FVocabularyFilter: TVocabularyFilter; 29 | function InsertMode: Boolean; 30 | function GetFilterName: string; 31 | function GetLanguageCode: string; 32 | function GetWords: TArray; 33 | private 34 | procedure FillLanguageOptions; 35 | procedure ValidateForm; 36 | procedure DisplayWords; 37 | public 38 | constructor Create(const AVocabularyFilter: TVocabularyFilter); reintroduce; overload; 39 | procedure SetVocabularyFilter(const AVocabularyFilter: TVocabularyFilter); 40 | property FilterName: string read GetFilterName; 41 | property LanguageCode: string read GetLanguageCode; 42 | property Words: TArray read GetWords; 43 | end; 44 | 45 | implementation 46 | 47 | {$R *.dfm} 48 | 49 | uses 50 | Sparkle.Http.Client; 51 | 52 | const 53 | VALID_LANG_CODES = 'af-ZA,ar-AE,ar-SA,cy-GB,da-DK,de-CH,de-DE,en-AB,en-AU,en-GB,en-IE,en-IN,en-US,en-WL,es-ES,es-US,fa-IR,fr-CA,fr-FR,ga-IE,gd-GB,he-IL,hi-IN,id-ID,it-IT,ja-JP,ko-KR,ms-MY,nl-NL,pt-BR,pt-PT,ru-RU,ta-IN,te-IN,tr-TR,zh-CN,zh-TW,th-TH,en-ZA,en-NZ'; 54 | 55 | { TFilterForm } 56 | 57 | constructor TVocabularyFilterForm.Create(const AVocabularyFilter: TVocabularyFilter); 58 | begin 59 | inherited Create(nil); 60 | SetVocabularyFilter(AVocabularyFilter); 61 | end; 62 | 63 | procedure TVocabularyFilterForm.SetVocabularyFilter(const AVocabularyFilter: TVocabularyFilter); 64 | begin 65 | FVocabularyFilter := AVocabularyFilter; 66 | end; 67 | 68 | procedure TVocabularyFilterForm.ValidateForm; 69 | begin 70 | ConfirmButton.Enabled := (FilterName<>'') and (Pos(' ', FilterName)=0) and (WordsMemo.Lines.Text<>''); 71 | end; 72 | 73 | function TVocabularyFilterForm.InsertMode: Boolean; 74 | begin 75 | Result := FVocabularyFilter=nil; 76 | end; 77 | 78 | procedure TVocabularyFilterForm.OnEditChange(Sender: TObject); 79 | begin 80 | ValidateForm; 81 | end; 82 | 83 | procedure TVocabularyFilterForm.FillLanguageOptions; 84 | begin 85 | LanguageCodeEdit.Items.Clear; 86 | LanguageCodeEdit.Items.CommaText := VALID_LANG_CODES; 87 | end; 88 | 89 | procedure TVocabularyFilterForm.FormCreate(Sender: TObject); 90 | begin 91 | FillLanguageOptions; 92 | end; 93 | 94 | procedure TVocabularyFilterForm.FormShow(Sender: TObject); 95 | begin 96 | if InsertMode then 97 | begin 98 | LanguageCodeEdit.ItemIndex := LanguageCodeEdit.Items.IndexOf(TLanguageCode.EnUS.Value); // since sample media is en-US 99 | end else 100 | begin 101 | FilterNameEdit.Text := FVocabularyFilter.VocabularyFilterName; 102 | LanguageCodeEdit.Style := csDropDown; 103 | LanguageCodeEdit.Text := FVocabularyFilter.LanguageCode.Value; 104 | if (FVocabularyFilter.IsSetDownloadUri) then 105 | DisplayWords; 106 | end; 107 | PageControl.ActivePageIndex := 0; 108 | FilterNameEdit.Enabled := InsertMode; 109 | LanguageCodeEdit.Enabled := InsertMode; 110 | ConfirmButton.Visible := InsertMode; 111 | WordsMemo.Enabled := InsertMode; 112 | end; 113 | 114 | procedure TVocabularyFilterForm.DisplayWords; 115 | var 116 | CLient: THttpClient; 117 | Response: THttpResponse; 118 | begin 119 | Client := THttpClient.Create; 120 | try 121 | Response := Client.Get(FVocabularyFilter.DownloadUri); 122 | try 123 | WordsMemo.Lines.Text := TEncoding.UTF8.GetString(Response.ContentAsBytes); 124 | finally 125 | Response.Free; 126 | end; 127 | finally 128 | Client.Free; 129 | end; 130 | end; 131 | 132 | function TVocabularyFilterForm.GetFilterName: string; 133 | begin 134 | Result := FilterNameEdit.Text; 135 | end; 136 | 137 | function TVocabularyFilterForm.GetLanguageCode: string; 138 | begin 139 | Result := LanguageCodeEdit.Text; 140 | end; 141 | 142 | function TVocabularyFilterForm.GetWords: TArray; 143 | begin 144 | Result := WordsMemo.Lines.ToStringArray; 145 | end; 146 | 147 | end. 148 | -------------------------------------------------------------------------------- /Source/Translate/Forms.Main.pas: -------------------------------------------------------------------------------- 1 | unit Forms.Main; 2 | 3 | interface 4 | 5 | uses 6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 7 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, 8 | AWS.Translate, Vcl.Buttons, 9 | System.StrUtils; 10 | 11 | type 12 | TMainForm = class(TForm) 13 | Panel1: TPanel; 14 | cbLanguageLeft: TComboBox; 15 | MemoLeft: TMemo; 16 | Panel2: TPanel; 17 | cbLanguageRight: TComboBox; 18 | MemoRight: TMemo; 19 | Panel3: TPanel; 20 | SpeedButton1: TSpeedButton; 21 | Splitter1: TSplitter; 22 | SpeedButton2: TSpeedButton; 23 | procedure SpeedButton1Click(Sender: TObject); 24 | procedure FormCreate(Sender: TObject); 25 | procedure SpeedButton2Click(Sender: TObject); 26 | private 27 | procedure FillLanguageCombo(Combo: TComboBox; const Selection: string); 28 | function Translate(const SourceText, SourceLanguage, TargetLanguage: string): string; 29 | public 30 | end; 31 | 32 | type 33 | TLanguageInfo = record 34 | Name: string; 35 | Code: string; 36 | end; 37 | 38 | const 39 | Languages: array[0..70] of TLanguageInfo = ( 40 | (Name: 'Afrikaans'; Code: 'af'), 41 | (Name: 'Albanian'; Code: 'sq'), 42 | (Name: 'Amharic'; Code: 'am'), 43 | (Name: 'Arabic'; Code: 'ar'), 44 | (Name: 'Armenian'; Code: 'hy'), 45 | (Name: 'Azerbaijani'; Code: 'az'), 46 | (Name: 'Bengali'; Code: 'bn'), 47 | (Name: 'Bosnian'; Code: 'bs'), 48 | (Name: 'Bulgarian'; Code: 'bg'), 49 | (Name: 'Catalan'; Code: 'ca'), 50 | (Name: 'Chinese (Simplified)'; Code: 'zh'), 51 | (Name: 'Chinese (Traditional)'; Code: 'zh-TW'), 52 | (Name: 'Croatian'; Code: 'hr'), 53 | (Name: 'Czech'; Code: 'cs'), 54 | (Name: 'Danish'; Code: 'da'), 55 | (Name: 'Dari'; Code: 'fa-AF'), 56 | (Name: 'Dutch'; Code: 'nl'), 57 | (Name: 'English'; Code: 'en'), 58 | (Name: 'Estonian'; Code: 'et'), 59 | (Name: 'Farsi (Persian)'; Code: 'fa'), 60 | (Name: 'Filipino Tagalog'; Code: 'tl'), 61 | (Name: 'Finnish'; Code: 'fi'), 62 | (Name: 'French'; Code: 'fr'), 63 | (Name: 'French (Canada)'; Code: 'fr-CA'), 64 | (Name: 'Georgian'; Code: 'ka'), 65 | (Name: 'German'; Code: 'de'), 66 | (Name: 'Greek'; Code: 'el'), 67 | (Name: 'Gujarati'; Code: 'gu'), 68 | (Name: 'Haitian Creole'; Code: 'ht'), 69 | (Name: 'Hausa'; Code: 'ha'), 70 | (Name: 'Hebrew'; Code: 'he'), 71 | (Name: 'Hindi'; Code: 'hi'), 72 | (Name: 'Hungarian'; Code: 'hu'), 73 | (Name: 'Icelandic'; Code: 'is'), 74 | (Name: 'Indonesian'; Code: 'id'), 75 | (Name: 'Italian'; Code: 'it'), 76 | (Name: 'Japanese'; Code: 'ja'), 77 | (Name: 'Kannada'; Code: 'kn'), 78 | (Name: 'Kazakh'; Code: 'kk'), 79 | (Name: 'Korean'; Code: 'ko'), 80 | (Name: 'Latvian'; Code: 'lv'), 81 | (Name: 'Lithuanian'; Code: 'lt'), 82 | (Name: 'Macedonian'; Code: 'mk'), 83 | (Name: 'Malay'; Code: 'ms'), 84 | (Name: 'Malayalam'; Code: 'ml'), 85 | (Name: 'Maltese'; Code: 'mt'), 86 | (Name: 'Mongolian'; Code: 'mn'), 87 | (Name: 'Norwegian'; Code: 'no'), 88 | (Name: 'Pashto'; Code: 'ps'), 89 | (Name: 'Polish'; Code: 'pl'), 90 | (Name: 'Portuguese'; Code: 'pt'), 91 | (Name: 'Romanian'; Code: 'ro'), 92 | (Name: 'Russian'; Code: 'ru'), 93 | (Name: 'Serbian'; Code: 'sr'), 94 | (Name: 'Sinhala'; Code: 'si'), 95 | (Name: 'Slovak'; Code: 'sk'), 96 | (Name: 'Slovenian'; Code: 'sl'), 97 | (Name: 'Somali'; Code: 'so'), 98 | (Name: 'Spanish'; Code: 'es'), 99 | (Name: 'Spanish (Mexico)'; Code: 'es-MX'), 100 | (Name: 'Swahili'; Code: 'sw'), 101 | (Name: 'Swedish'; Code: 'sv'), 102 | (Name: 'Tamil'; Code: 'ta'), 103 | (Name: 'Telugu'; Code: 'te'), 104 | (Name: 'Thai'; Code: 'th'), 105 | (Name: 'Turkish'; Code: 'tr'), 106 | (Name: 'Ukrainian'; Code: 'uk'), 107 | (Name: 'Urdu'; Code: 'ur'), 108 | (Name: 'Uzbek'; Code: 'uz'), 109 | (Name: 'Vietnamese'; Code: 'vi'), 110 | (Name: 'Welsh'; Code: 'cy)') 111 | ); 112 | 113 | var 114 | MainForm: TMainForm; 115 | 116 | implementation 117 | 118 | {$R *.dfm} 119 | 120 | procedure TMainForm.FillLanguageCombo(Combo: TComboBox; const Selection: string); 121 | var 122 | I: Integer; 123 | begin 124 | Combo.Clear; 125 | for I := 0 to High(Languages) do 126 | begin 127 | Combo.Items.Add(Languages[I].Name); 128 | if ContainsText(Languages[I].Name, Selection) then 129 | Combo.ItemIndex := I; 130 | end; 131 | end; 132 | 133 | procedure TMainForm.FormCreate(Sender: TObject); 134 | begin 135 | FillLanguageCombo(cbLanguageLeft, 'English'); 136 | FillLanguageCombo(cbLanguageRight, 'German'); 137 | end; 138 | 139 | procedure TMainForm.SpeedButton1Click(Sender: TObject); 140 | begin 141 | MemoRight.Lines.Text := Translate( 142 | MemoLeft.Lines.Text, 143 | Languages[cbLanguageLeft.ItemIndex].Code, 144 | Languages[cbLanguageRight.ItemIndex].Code); 145 | end; 146 | 147 | procedure TMainForm.SpeedButton2Click(Sender: TObject); 148 | begin 149 | MemoLeft.Lines.Text := Translate( 150 | MemoRight.Lines.Text, 151 | Languages[cbLanguageRight.ItemIndex].Code, 152 | Languages[cbLanguageLeft.ItemIndex].Code); 153 | end; 154 | 155 | function TMainForm.Translate(const SourceText, SourceLanguage, TargetLanguage: string): string; 156 | var 157 | Client: IAmazonTranslate; 158 | Request: ITranslateTextRequest; 159 | Response: ITranslateTextResponse; 160 | begin 161 | Client := TAmazonTranslateClient.Create; 162 | Request := TTranslateTextRequest.Create; 163 | Request.SourceLanguageCode := SourceLanguage; 164 | Request.TargetLanguageCode := TargetLanguage; 165 | Request.Text := SourceText; 166 | Response := Client.TranslateText(Request); 167 | Result := Response.TranslatedText; 168 | end; 169 | 170 | end. 171 | 172 | -------------------------------------------------------------------------------- /Source/Transcribe/Forms.Main.dfm: -------------------------------------------------------------------------------- 1 | object MainForm: TMainForm 2 | Left = 0 3 | Top = 0 4 | BorderStyle = bsDialog 5 | Caption = 'AWS Transcribe Sample' 6 | ClientHeight = 494 7 | ClientWidth = 514 8 | Color = clBtnFace 9 | Font.Charset = DEFAULT_CHARSET 10 | Font.Color = clWindowText 11 | Font.Height = -12 12 | Font.Name = 'Segoe UI' 13 | Font.Style = [] 14 | Position = poScreenCenter 15 | OnCreate = FormCreate 16 | OnDestroy = FormDestroy 17 | OnShow = FormShow 18 | TextHeight = 15 19 | object PageControl: TPageControl 20 | AlignWithMargins = True 21 | Left = 4 22 | Top = 4 23 | Width = 506 24 | Height = 486 25 | Margins.Left = 4 26 | Margins.Top = 4 27 | Margins.Right = 4 28 | Margins.Bottom = 4 29 | ActivePage = FiltersTab 30 | Align = alClient 31 | TabHeight = 28 32 | TabOrder = 0 33 | OnChange = PageControlChange 34 | object JobsTab: TTabSheet 35 | Caption = 'Jobs' 36 | object Panel2: TPanel 37 | Left = 0 38 | Top = 0 39 | Width = 498 40 | Height = 40 41 | Align = alTop 42 | BevelOuter = bvNone 43 | TabOrder = 0 44 | object Label2: TLabel 45 | AlignWithMargins = True 46 | Left = 4 47 | Top = 4 48 | Width = 89 49 | Height = 15 50 | Margins.Left = 4 51 | Margins.Top = 4 52 | Margins.Right = 4 53 | Margins.Bottom = 4 54 | Align = alLeft 55 | Caption = 'Trancription Jobs' 56 | Layout = tlCenter 57 | end 58 | object ListJobsButton: TSpeedButton 59 | AlignWithMargins = True 60 | Left = 101 61 | Top = 6 62 | Width = 75 63 | Height = 28 64 | Margins.Left = 4 65 | Margins.Top = 6 66 | Margins.Right = 4 67 | Margins.Bottom = 6 68 | Align = alLeft 69 | Caption = 'Refresh' 70 | OnClick = ListJobsButtonClick 71 | end 72 | object DeleteJobButton: TSpeedButton 73 | AlignWithMargins = True 74 | Left = 419 75 | Top = 6 76 | Width = 75 77 | Height = 28 78 | Margins.Left = 4 79 | Margins.Top = 6 80 | Margins.Right = 4 81 | Margins.Bottom = 6 82 | Align = alRight 83 | Caption = 'Delete' 84 | Enabled = False 85 | OnClick = DeleteJobButtonClick 86 | ExplicitLeft = 354 87 | end 88 | object ViewJobButton: TSpeedButton 89 | AlignWithMargins = True 90 | Left = 336 91 | Top = 6 92 | Width = 75 93 | Height = 28 94 | Margins.Left = 4 95 | Margins.Top = 6 96 | Margins.Right = 4 97 | Margins.Bottom = 6 98 | Align = alRight 99 | Caption = 'View' 100 | Enabled = False 101 | OnClick = ViewJobButtonClick 102 | ExplicitLeft = 331 103 | end 104 | object CreateJobButton: TSpeedButton 105 | AlignWithMargins = True 106 | Left = 253 107 | Top = 6 108 | Width = 75 109 | Height = 28 110 | Margins.Left = 4 111 | Margins.Top = 6 112 | Margins.Right = 4 113 | Margins.Bottom = 6 114 | Align = alRight 115 | Caption = 'New' 116 | OnClick = CreateJobButtonClick 117 | ExplicitLeft = 314 118 | end 119 | end 120 | object JobsView: TListView 121 | AlignWithMargins = True 122 | Left = 4 123 | Top = 44 124 | Width = 490 125 | Height = 400 126 | Margins.Left = 4 127 | Margins.Top = 4 128 | Margins.Right = 4 129 | Margins.Bottom = 4 130 | Align = alClient 131 | Columns = < 132 | item 133 | AutoSize = True 134 | Caption = 'Name' 135 | end 136 | item 137 | Alignment = taCenter 138 | Caption = 'Lang' 139 | MaxWidth = 60 140 | MinWidth = 60 141 | Width = 60 142 | end 143 | item 144 | Alignment = taCenter 145 | Caption = 'Created' 146 | MaxWidth = 130 147 | MinWidth = 130 148 | Width = 130 149 | end 150 | item 151 | Alignment = taCenter 152 | Caption = 'Status' 153 | MaxWidth = 90 154 | MinWidth = 90 155 | Width = 90 156 | end> 157 | ColumnClick = False 158 | DoubleBuffered = True 159 | HideSelection = False 160 | OwnerData = True 161 | ReadOnly = True 162 | RowSelect = True 163 | ParentDoubleBuffered = False 164 | TabOrder = 1 165 | ViewStyle = vsReport 166 | OnChange = JobsViewChange 167 | OnCustomDrawSubItem = JobsViewCustomDrawSubItem 168 | OnData = JobsViewData 169 | end 170 | end 171 | object FiltersTab: TTabSheet 172 | Caption = 'Filters' 173 | ImageIndex = 1 174 | object Panel3: TPanel 175 | Left = 0 176 | Top = 0 177 | Width = 498 178 | Height = 40 179 | Align = alTop 180 | BevelOuter = bvNone 181 | TabOrder = 0 182 | object Label3: TLabel 183 | AlignWithMargins = True 184 | Left = 4 185 | Top = 4 186 | Width = 92 187 | Height = 32 188 | Margins.Left = 4 189 | Margins.Top = 4 190 | Margins.Right = 4 191 | Margins.Bottom = 4 192 | Align = alLeft 193 | Caption = 'Vocabulary Filters' 194 | Layout = tlCenter 195 | ExplicitHeight = 15 196 | end 197 | object ListFiltersButton: TSpeedButton 198 | AlignWithMargins = True 199 | Left = 104 200 | Top = 6 201 | Width = 75 202 | Height = 28 203 | Margins.Left = 4 204 | Margins.Top = 6 205 | Margins.Right = 4 206 | Margins.Bottom = 6 207 | Align = alLeft 208 | Caption = 'Refresh' 209 | OnClick = ListFiltersButtonClick 210 | ExplicitLeft = 101 211 | end 212 | object DeleteFilterButton: TSpeedButton 213 | AlignWithMargins = True 214 | Left = 419 215 | Top = 6 216 | Width = 75 217 | Height = 28 218 | Margins.Left = 4 219 | Margins.Top = 6 220 | Margins.Right = 4 221 | Margins.Bottom = 6 222 | Align = alRight 223 | Caption = 'Delete' 224 | Enabled = False 225 | OnClick = DeleteFilterButtonClick 226 | ExplicitLeft = 354 227 | end 228 | object ViewFilterButton: TSpeedButton 229 | AlignWithMargins = True 230 | Left = 336 231 | Top = 6 232 | Width = 75 233 | Height = 28 234 | Margins.Left = 4 235 | Margins.Top = 6 236 | Margins.Right = 4 237 | Margins.Bottom = 6 238 | Align = alRight 239 | Caption = 'View' 240 | Enabled = False 241 | OnClick = ViewFilterButtonClick 242 | ExplicitLeft = 331 243 | end 244 | object CreateFilterButton: TSpeedButton 245 | AlignWithMargins = True 246 | Left = 253 247 | Top = 6 248 | Width = 75 249 | Height = 28 250 | Margins.Left = 4 251 | Margins.Top = 6 252 | Margins.Right = 4 253 | Margins.Bottom = 6 254 | Align = alRight 255 | Caption = 'New' 256 | OnClick = CreateFilterButtonClick 257 | ExplicitLeft = 314 258 | end 259 | end 260 | object FiltersView: TListView 261 | AlignWithMargins = True 262 | Left = 4 263 | Top = 44 264 | Width = 490 265 | Height = 400 266 | Margins.Left = 4 267 | Margins.Top = 4 268 | Margins.Right = 4 269 | Margins.Bottom = 4 270 | Align = alClient 271 | Columns = < 272 | item 273 | AutoSize = True 274 | Caption = 'Name' 275 | end 276 | item 277 | Alignment = taCenter 278 | Caption = 'Lang' 279 | MaxWidth = 60 280 | MinWidth = 60 281 | Width = 60 282 | end 283 | item 284 | Alignment = taCenter 285 | Caption = 'Last Modified' 286 | MaxWidth = 130 287 | MinWidth = 130 288 | Width = 130 289 | end> 290 | ColumnClick = False 291 | DoubleBuffered = True 292 | HideSelection = False 293 | OwnerData = True 294 | ReadOnly = True 295 | RowSelect = True 296 | ParentDoubleBuffered = False 297 | TabOrder = 1 298 | ViewStyle = vsReport 299 | OnChange = FiltersViewChange 300 | OnData = FiltersViewData 301 | end 302 | end 303 | end 304 | end 305 | -------------------------------------------------------------------------------- /Source/Rekognition/Forms.Image.pas: -------------------------------------------------------------------------------- 1 | unit Forms.Image; 2 | 3 | interface 4 | 5 | uses 6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, 7 | System.Generics.Collections, AWS.Rekognition, System.Types, 8 | Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, PNGImage, JPEG, 9 | Vcl.ExtCtrls; 10 | 11 | type 12 | TImageForm = class(TForm) 13 | PaintBox1: TPaintBox; 14 | procedure FormPaint(Sender: TObject); 15 | procedure FormResize(Sender: TObject); 16 | procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); 17 | private 18 | FImage: TPicture; 19 | FTextDetections: TObjectList; 20 | ImgBounds: TRect; 21 | FCelebrities: TObjectList; 22 | procedure DrawImage; 23 | function AspectRatio: Double; 24 | function TargetAspectRatio: Double; 25 | function HRatio: Double; 26 | function VRatio: Double; 27 | function TargetControl: TControl; 28 | function ImgH(const Value: Double): Integer; 29 | function ImgV(const Value: Double): Integer; 30 | function CanvasRect(Box: TBoundingBox): TRect; 31 | function CanvasPolygon(Points: TObjectList): TArray; 32 | procedure DrawTextDetection(Canvas: TCanvas; Detection: TTextDetection); 33 | procedure DrawTextDetections(Canvas: TCanvas); 34 | procedure DrawCelebrity(Canvas: TCanvas; Celebrity: TCelebrity); 35 | procedure DrawCelebrities(Canvas: TCanvas); 36 | function FindTextDetection(X, Y: Integer): TTextDetection; 37 | function FindCelebrity(X, Y: Integer): TCelebrity; 38 | procedure ImageChange(Sender: TObject); 39 | procedure SetTextDetections(const Value: TObjectList); 40 | procedure SetCelebrities(const Value: TObjectList); 41 | public 42 | constructor Create(AOwner: TComponent); override; 43 | destructor Destroy; override; 44 | property Image: TPicture read FImage; 45 | property TextDetections: TObjectList read FTextDetections write SetTextDetections; 46 | property Celebrities: TObjectList read FCelebrities write SetCelebrities; 47 | end; 48 | 49 | var 50 | ImageForm: TImageForm; 51 | 52 | implementation 53 | 54 | {$R *.dfm} 55 | 56 | { TImageForm } 57 | 58 | function TImageForm.AspectRatio: Double; 59 | begin 60 | if Image.Height = 0 then 61 | Result := 1 62 | else 63 | Result := Image.Width / Image.Height; 64 | end; 65 | 66 | function TImageForm.CanvasPolygon(Points: TObjectList): TArray; 67 | var 68 | I: Integer; 69 | begin 70 | SetLength(Result, Points.Count); 71 | for I := 0 to Points.Count - 1 do 72 | begin 73 | Result[I].X := ImgH(Points[I].X); 74 | Result[I].Y := ImgV(Points[I].Y); 75 | end; 76 | end; 77 | 78 | function TImageForm.CanvasRect(Box: TBoundingBox): TRect; 79 | begin 80 | Result.Left := ImgH(Box.Left); 81 | Result.Top := ImgV(Box.Top); 82 | Result.Right := ImgH(Box.Left + Box.Width); 83 | Result.Bottom := ImgV(Box.Top + Box.Height); 84 | end; 85 | 86 | constructor TImageForm.Create(AOwner: TComponent); 87 | begin 88 | inherited; 89 | FImage := TPicture.Create; 90 | FImage.OnChange := ImageChange; 91 | end; 92 | 93 | destructor TImageForm.Destroy; 94 | begin 95 | FImage.Free; 96 | TextDetections := nil; 97 | Celebrities := nil; 98 | inherited; 99 | end; 100 | 101 | procedure TImageForm.DrawCelebrities(Canvas: TCanvas); 102 | var 103 | Celebrity: TCelebrity; 104 | begin 105 | if Celebrities = nil then Exit; 106 | for Celebrity in Celebrities do 107 | DrawCelebrity(Canvas, Celebrity); 108 | end; 109 | 110 | procedure TImageForm.DrawImage; 111 | var 112 | ImgHeight: Double; 113 | ImgWidth: Double; 114 | begin 115 | if AspectRatio > TargetAspectRatio then 116 | begin 117 | ImgBounds.Left := 0; 118 | ImgBounds.Right := TargetControl.Width; 119 | ImgHeight := TargetControl.Width / AspectRatio; 120 | ImgBounds.Top := Round((TargetControl.Height - ImgHeight) / 2); 121 | ImgBounds.Bottom := Round(ImgBounds.Top + ImgHeight); 122 | end 123 | else 124 | begin 125 | ImgBounds.Top := 0; 126 | ImgBounds.Bottom := TargetControl.Height; 127 | ImgWidth := TargetControl.Height * AspectRatio; 128 | ImgBounds.Left := Round((TargetControl.Width - ImgWidth) / 2); 129 | ImgBounds.Right := Round(ImgBounds.Left + ImgWidth); 130 | end; 131 | Canvas.StretchDraw(ImgBounds, Image.Graphic); 132 | end; 133 | 134 | procedure TImageForm.DrawTextDetection(Canvas: TCanvas; Detection: TTextDetection); 135 | begin 136 | Canvas.Pen.Width := 3; 137 | Canvas.Pen.Color := clBlue; 138 | Canvas.Brush.Style := bsClear; 139 | if Detection.IsSetGeometry then 140 | if Detection.Geometry.IsSetPolygon then 141 | Canvas.Polygon(CanvasPolygon(Detection.Geometry.Polygon)) 142 | else 143 | if Detection.Geometry.IsSetBoundingBox then 144 | Canvas.Rectangle(CanvasRect(Detection.Geometry.BoundingBox)); 145 | end; 146 | 147 | procedure TImageForm.DrawCelebrity(Canvas: TCanvas; Celebrity: TCelebrity); 148 | begin 149 | Canvas.Pen.Width := 3; 150 | Canvas.Pen.Color := clGreen; 151 | Canvas.Brush.Style := bsClear; 152 | if Celebrity.IsSetFace and Celebrity.Face.IsSetBoundingBox then 153 | Canvas.Rectangle(CanvasRect(Celebrity.Face.BoundingBox)); 154 | end; 155 | 156 | procedure TImageForm.DrawTextDetections(Canvas: TCanvas); 157 | var 158 | TextDetection: TTextDetection; 159 | begin 160 | if TextDetections = nil then Exit; 161 | for TextDetection in TextDetections do 162 | if not TextDetection.IsSetParentId then 163 | DrawTextDetection(Canvas, TextDetection); 164 | end; 165 | 166 | function TImageForm.FindCelebrity(X, Y: Integer): TCelebrity; 167 | var 168 | Celebrity: TCelebrity; 169 | begin 170 | if Celebrities = nil then Exit(nil); 171 | for Celebrity in Celebrities do 172 | if Celebrity.IsSetFace and Celebrity.Face.IsSetBoundingBox then 173 | begin 174 | if PtInRect(CanvasRect(Celebrity.Face.BoundingBox), Point(X, Y)) then 175 | Exit(Celebrity); 176 | end; 177 | Result := nil; 178 | end; 179 | 180 | function TImageForm.FindTextDetection(X, Y: Integer): TTextDetection; 181 | var 182 | R: HRGN; 183 | Pts: TArray; 184 | TextDetection: TTextDetection; 185 | begin 186 | if TextDetections = nil then Exit(nil); 187 | for TextDetection in TextDetections do 188 | if TextDetection.IsSetGeometry and TextDetection.Geometry.IsSetPolygon then 189 | begin 190 | Pts := CanvasPolygon(TextDetection.Geometry.Polygon); 191 | if Length(Pts) > 0 then 192 | begin 193 | R := CreatePolygonRgn(Pts[0], Length(Pts), ALTERNATE); 194 | try 195 | if PtInRegion(R, X, Y) then 196 | Exit(TextDetection); 197 | finally 198 | DeleteObject(R); 199 | end; 200 | end 201 | end; 202 | Result := nil; 203 | end; 204 | 205 | procedure TImageForm.FormPaint(Sender: TObject); 206 | begin 207 | DrawImage; 208 | DrawTextDetections(Self.Canvas); 209 | DrawCelebrities(Self.Canvas); 210 | end; 211 | 212 | procedure TImageForm.FormResize(Sender: TObject); 213 | begin 214 | Invalidate; 215 | end; 216 | 217 | function TImageForm.HRatio: Double; 218 | begin 219 | Result := ImgBounds.Width / Image.Width; 220 | end; 221 | 222 | procedure TImageForm.ImageChange(Sender: TObject); 223 | begin 224 | TextDetections := nil; 225 | Celebrities := nil; 226 | Invalidate; 227 | end; 228 | 229 | function TImageForm.ImgH(const Value: Double): Integer; 230 | begin 231 | Result := Round(Image.Width * Value * HRatio + ImgBounds.Left); 232 | end; 233 | 234 | function TImageForm.ImgV(const Value: Double): Integer; 235 | begin 236 | Result := Round(Image.Height * Value * VRatio + ImgBounds.Top); 237 | end; 238 | 239 | procedure TImageForm.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); 240 | var 241 | TextDetection: TTextDetection; 242 | Celebrity: TCelebrity; 243 | begin 244 | TextDetection := FindTextDetection(X, Y); 245 | Celebrity := FindCelebrity(X, Y); 246 | 247 | if TextDetection <> nil then 248 | Self.Hint := TextDetection.DetectedText 249 | else 250 | if Celebrity <> nil then 251 | Self.Hint := Celebrity.Name 252 | else 253 | Self.Hint := ''; 254 | 255 | if Self.Hint <> '' then 256 | Application.ActivateHint(TargetControl.ClientToScreen(Point(X, Y))) 257 | else 258 | Application.HideHint; 259 | end; 260 | 261 | procedure TImageForm.SetCelebrities(const Value: TObjectList); 262 | begin 263 | if FCelebrities <> Value then 264 | begin 265 | FCelebrities.Free; 266 | FCelebrities := Value; 267 | Invalidate; 268 | end; 269 | end; 270 | 271 | procedure TImageForm.SetTextDetections(const Value: TObjectList); 272 | begin 273 | if FTextDetections <> Value then 274 | begin 275 | FTextDetections.Free; 276 | FTextDetections := Value; 277 | Invalidate; 278 | end; 279 | end; 280 | 281 | function TImageForm.TargetControl: TControl; 282 | begin 283 | // Result := Self; 284 | Result := PaintBox1; 285 | end; 286 | 287 | function TImageForm.TargetAspectRatio: Double; 288 | begin 289 | Result := TargetControl.Width / TargetControl.Height; 290 | end; 291 | 292 | function TImageForm.VRatio: Double; 293 | begin 294 | Result := ImgBounds.Height / Image.Height; 295 | end; 296 | 297 | end. 298 | -------------------------------------------------------------------------------- /Source/Transcribe/Forms.TranscriptionJob.dfm: -------------------------------------------------------------------------------- 1 | object TranscriptionJobForm: TTranscriptionJobForm 2 | Left = 0 3 | Top = 0 4 | BorderStyle = bsDialog 5 | Caption = 'Transcription Job' 6 | ClientHeight = 571 7 | ClientWidth = 624 8 | Color = clBtnFace 9 | Font.Charset = DEFAULT_CHARSET 10 | Font.Color = clWindowText 11 | Font.Height = -12 12 | Font.Name = 'Segoe UI' 13 | Font.Style = [] 14 | Position = poScreenCenter 15 | OnCreate = FormCreate 16 | OnShow = FormShow 17 | TextHeight = 15 18 | object PageControl: TPageControl 19 | AlignWithMargins = True 20 | Left = 4 21 | Top = 4 22 | Width = 616 23 | Height = 523 24 | Margins.Left = 4 25 | Margins.Top = 4 26 | Margins.Right = 4 27 | Margins.Bottom = 4 28 | ActivePage = JobDetailsTab 29 | Align = alClient 30 | TabHeight = 28 31 | TabOrder = 0 32 | OnChange = PageControlChange 33 | object JobDetailsTab: TTabSheet 34 | Caption = 'Job Details' 35 | ImageIndex = 2 36 | object Panel2: TPanel 37 | Left = 0 38 | Top = 0 39 | Width = 608 40 | Height = 485 41 | Align = alClient 42 | BevelOuter = bvNone 43 | BorderWidth = 20 44 | TabOrder = 0 45 | object Label1: TLabel 46 | Left = 20 47 | Top = 20 48 | Width = 568 49 | Height = 20 50 | Align = alTop 51 | AutoSize = False 52 | Caption = 'Job Name' 53 | ExplicitTop = 6 54 | end 55 | object Label2: TLabel 56 | AlignWithMargins = True 57 | Left = 20 58 | Top = 87 59 | Width = 568 60 | Height = 20 61 | Margins.Left = 0 62 | Margins.Top = 24 63 | Margins.Right = 0 64 | Margins.Bottom = 0 65 | Align = alTop 66 | AutoSize = False 67 | Caption = 'Language Code' 68 | ExplicitLeft = 0 69 | ExplicitTop = 52 70 | ExplicitWidth = 486 71 | end 72 | object Label6: TLabel 73 | AlignWithMargins = True 74 | Left = 20 75 | Top = 154 76 | Width = 568 77 | Height = 20 78 | Margins.Left = 0 79 | Margins.Top = 24 80 | Margins.Right = 0 81 | Margins.Bottom = 0 82 | Align = alTop 83 | AutoSize = False 84 | Caption = 'Media URI' 85 | ExplicitLeft = 5 86 | ExplicitTop = 70 87 | ExplicitWidth = 524 88 | end 89 | object Label3: TLabel 90 | AlignWithMargins = True 91 | Left = 22 92 | Top = 199 93 | Width = 566 94 | Height = 13 95 | Margins.Left = 2 96 | Margins.Top = 2 97 | Margins.Right = 0 98 | Margins.Bottom = 0 99 | Align = alTop 100 | Caption = 101 | 'Amazon S3 location. Supported formats are MP3, MP4, WAV, FLAC, O' + 102 | 'GG, AMR and WEBM' 103 | Font.Charset = DEFAULT_CHARSET 104 | Font.Color = clBlue 105 | Font.Height = -11 106 | Font.Name = 'Segoe UI' 107 | Font.Style = [fsItalic] 108 | ParentFont = False 109 | ExplicitWidth = 423 110 | end 111 | object Label4: TLabel 112 | AlignWithMargins = True 113 | Left = 20 114 | Top = 236 115 | Width = 568 116 | Height = 20 117 | Margins.Left = 0 118 | Margins.Top = 24 119 | Margins.Right = 0 120 | Margins.Bottom = 0 121 | Align = alTop 122 | AutoSize = False 123 | Caption = 'Vocabulary Filter' 124 | ExplicitLeft = -5 125 | ExplicitTop = 263 126 | ExplicitWidth = 524 127 | end 128 | object Label5: TLabel 129 | AlignWithMargins = True 130 | Left = 20 131 | Top = 303 132 | Width = 568 133 | Height = 20 134 | Margins.Left = 0 135 | Margins.Top = 24 136 | Margins.Right = 0 137 | Margins.Bottom = 0 138 | Align = alTop 139 | AutoSize = False 140 | Caption = 'Content redaction' 141 | ExplicitLeft = -5 142 | ExplicitTop = 263 143 | ExplicitWidth = 524 144 | end 145 | object JobNameEdit: TEdit 146 | Left = 20 147 | Top = 40 148 | Width = 568 149 | Height = 23 150 | Align = alTop 151 | TabOrder = 0 152 | OnChange = OnEditChange 153 | end 154 | object LanguageCodeEdit: TComboBox 155 | Left = 20 156 | Top = 107 157 | Width = 568 158 | Height = 23 159 | Align = alTop 160 | Style = csDropDownList 161 | TabOrder = 1 162 | Items.Strings = ( 163 | 'Auto-detect') 164 | end 165 | object MediaUriEdit: TEdit 166 | Left = 20 167 | Top = 174 168 | Width = 568 169 | Height = 23 170 | Align = alTop 171 | TabOrder = 2 172 | OnChange = OnEditChange 173 | end 174 | object VocabularyFilterEdit: TComboBox 175 | Left = 20 176 | Top = 256 177 | Width = 568 178 | Height = 23 179 | Align = alTop 180 | Style = csDropDownList 181 | TabOrder = 3 182 | Items.Strings = ( 183 | 'None') 184 | end 185 | object ContentRedactionEdit: TComboBox 186 | Left = 20 187 | Top = 323 188 | Width = 568 189 | Height = 23 190 | Align = alTop 191 | Style = csDropDownList 192 | TabOrder = 4 193 | Items.Strings = ( 194 | 'No' 195 | 'Yes (output redacted transcript only)' 196 | 'Yes (output redacted and unredacted transcripts)') 197 | end 198 | end 199 | end 200 | object TranscriptTab: TTabSheet 201 | Caption = 'Transcript' 202 | ImageIndex = 2 203 | object TranscriptMemo: TMemo 204 | AlignWithMargins = True 205 | Left = 4 206 | Top = 62 207 | Width = 600 208 | Height = 419 209 | Margins.Left = 4 210 | Margins.Top = 4 211 | Margins.Right = 4 212 | Margins.Bottom = 4 213 | Align = alClient 214 | Font.Charset = ANSI_CHARSET 215 | Font.Color = clWindowText 216 | Font.Height = -12 217 | Font.Name = 'Segoe UI' 218 | Font.Style = [] 219 | ParentFont = False 220 | ReadOnly = True 221 | TabOrder = 0 222 | end 223 | object ViewTranscriptOption: TRadioGroup 224 | AlignWithMargins = True 225 | Left = 4 226 | Top = 4 227 | Width = 600 228 | Height = 50 229 | Margins.Left = 4 230 | Margins.Top = 4 231 | Margins.Right = 4 232 | Margins.Bottom = 4 233 | Align = alTop 234 | Columns = 2 235 | ItemIndex = 0 236 | Items.Strings = ( 237 | 'Raw' 238 | 'Segmented') 239 | TabOrder = 1 240 | OnClick = ViewTranscriptOptionClick 241 | end 242 | end 243 | object RedactedTranscriptTab: TTabSheet 244 | Caption = 'Redacted Transcript' 245 | ImageIndex = 3 246 | object RedactedTranscriptMemo: TMemo 247 | AlignWithMargins = True 248 | Left = 4 249 | Top = 62 250 | Width = 600 251 | Height = 419 252 | Margins.Left = 4 253 | Margins.Top = 4 254 | Margins.Right = 4 255 | Margins.Bottom = 4 256 | Align = alClient 257 | Font.Charset = ANSI_CHARSET 258 | Font.Color = clWindowText 259 | Font.Height = -12 260 | Font.Name = 'Segoe UI' 261 | Font.Style = [] 262 | ParentFont = False 263 | ReadOnly = True 264 | TabOrder = 0 265 | end 266 | object ViewRedactedTranscriptOption: TRadioGroup 267 | AlignWithMargins = True 268 | Left = 4 269 | Top = 4 270 | Width = 600 271 | Height = 50 272 | Margins.Left = 4 273 | Margins.Top = 4 274 | Margins.Right = 4 275 | Margins.Bottom = 4 276 | Align = alTop 277 | Columns = 2 278 | ItemIndex = 0 279 | Items.Strings = ( 280 | 'Raw' 281 | 'Segmented') 282 | TabOrder = 1 283 | OnClick = ViewRedactedTranscriptOptionClick 284 | end 285 | end 286 | end 287 | object Panel1: TPanel 288 | Left = 0 289 | Top = 531 290 | Width = 624 291 | Height = 40 292 | Align = alBottom 293 | BevelOuter = bvNone 294 | TabOrder = 1 295 | object ConfirmButton: TBitBtn 296 | AlignWithMargins = True 297 | Left = 442 298 | Top = 4 299 | Width = 85 300 | Height = 32 301 | Margins.Left = 4 302 | Margins.Top = 4 303 | Margins.Right = 4 304 | Margins.Bottom = 4 305 | Align = alRight 306 | Enabled = False 307 | Kind = bkOK 308 | NumGlyphs = 2 309 | TabOrder = 0 310 | end 311 | object CancelButton: TBitBtn 312 | AlignWithMargins = True 313 | Left = 535 314 | Top = 4 315 | Width = 85 316 | Height = 32 317 | Margins.Left = 4 318 | Margins.Top = 4 319 | Margins.Right = 4 320 | Margins.Bottom = 4 321 | Align = alRight 322 | Kind = bkCancel 323 | NumGlyphs = 2 324 | TabOrder = 1 325 | end 326 | end 327 | end 328 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Source/Transcribe/AWS.Transcribe.Transcript.pas: -------------------------------------------------------------------------------- 1 | unit AWS.Transcribe.Transcript; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, 7 | System.JSON, 8 | Generics.Collections, 9 | AWS.Transcribe; 10 | 11 | type 12 | TTranscript = class; 13 | 14 | TTrancriptObject = class abstract 15 | strict private 16 | FTranscript: TTranscript; 17 | protected 18 | procedure LoadObject(const AValue: TJSONObject); virtual; abstract; 19 | public 20 | constructor Create(ATranscript: TTranscript; const AValue: TJSONObject); 21 | property Transcript: TTranscript read FTranscript; 22 | end; 23 | 24 | TTrancriptRedaction = class (TTrancriptObject) 25 | private 26 | FRedactionType: TPiiEntityType; 27 | FConfidence: Single; 28 | FCategory: TRedactionType; 29 | protected 30 | procedure LoadObject(const AValue: TJSONObject); override; 31 | public 32 | property Confidence: Single read FConfidence; 33 | property RedactionType: TPiiEntityType read FRedactionType; 34 | property Category: TRedactionType read FCategory; 35 | end; 36 | 37 | TTrancriptAlternative = class (TTrancriptObject) 38 | private 39 | FConfidence: Single; 40 | FContent: string; 41 | FRedactions: TList; 42 | function GetRedacted: Boolean; 43 | protected 44 | procedure LoadObject(const AValue: TJSONObject); override; 45 | public 46 | destructor Destroy; override; 47 | property Confidence: Single read FConfidence; 48 | property Content: string read FContent; 49 | property Redactions: TList read FRedactions; 50 | property Redacted: Boolean read GetRedacted; 51 | end; 52 | 53 | TTranscriptSegment = class; 54 | 55 | TTrancriptType = (pronunciation, punctuation); 56 | 57 | TTranscriptItem = class (TTrancriptObject) 58 | strict private 59 | FStartTime: Single; 60 | FEndTime: Single; 61 | FAlternatives: TList; 62 | FItemType: TTrancriptType; 63 | FSegment: TTranscriptSegment; 64 | private 65 | function TrancriptType(const AValue: string): TTrancriptType; 66 | protected 67 | procedure LoadObject(const AValue: TJSONObject); override; 68 | public 69 | destructor Destroy; override; 70 | property StartTime: Single read FStartTime; 71 | property EndTime: Single read FEndTime; 72 | property Alternatives: TList read FAlternatives; 73 | property ItemType: TTrancriptType read FItemType; 74 | property Segment: TTranscriptSegment read FSegment write FSegment; 75 | end; 76 | 77 | TTranscriptSegment = class (TTrancriptObject) 78 | strict private 79 | FStartTime: Single; 80 | FItems: TList; 81 | FEndTime: Single; 82 | FSpeakerLabel: string; 83 | protected 84 | procedure LoadObject(const AValue: TJSONObject); override; 85 | public 86 | destructor Destroy; override; 87 | property StartTime: Single read FStartTime; 88 | property EndTime: Single read FEndTime; 89 | property SpeakerLabel: string read FSpeakerLabel; 90 | property Items: TList read FItems; 91 | end; 92 | 93 | TTranscript = class 94 | strict private 95 | FJobName: string; 96 | FIsRedacted: Boolean; 97 | FSpeakers: Integer; 98 | FTexts: TArray; 99 | FItems: TList; 100 | FSegments: TList; 101 | function GetTexts(const AIndex: Integer): string; 102 | function GetItems(const AIndex: Integer): TTranscriptItem; 103 | function GetTextCount: Integer; 104 | function GetItemCount: Integer; 105 | private 106 | procedure LoadTranscript(const AJson: string); 107 | function GetSegmentCount: Integer; 108 | function GetSegments(const AIndex: Integer): TTranscriptSegment; 109 | public 110 | constructor Create(const AJson: string); 111 | destructor Destroy; override; 112 | function ItemAt(const AStartTime: Single): Integer; 113 | property JobName: string read FJobName; 114 | property IsRedacted: Boolean read FIsRedacted; 115 | property Speakers: Integer read FSpeakers; 116 | property Texts[const AIndex: Integer]: string read GetTexts; default; 117 | property Items[const AIndex: Integer]: TTranscriptItem read GetItems; 118 | property Segments[const AIndex: Integer]: TTranscriptSegment read GetSegments; 119 | property TextCount: Integer read GetTextCount; 120 | property ItemCount: Integer read GetItemCount; 121 | property SegmentCount: Integer read GetSegmentCount; 122 | end; 123 | 124 | implementation 125 | 126 | uses 127 | System.TypInfo; 128 | 129 | { TTrancriptObject } 130 | 131 | constructor TTrancriptObject.Create(ATranscript: TTranscript; const AValue: TJSONObject); 132 | begin 133 | inherited Create; 134 | FTranscript := ATranscript; 135 | LoadObject(AValue); 136 | end; 137 | 138 | { TTrancriptRedaction } 139 | 140 | procedure TTrancriptRedaction.LoadObject(const AValue: TJSONObject); 141 | begin 142 | FCategory := TRedactionType.PII; {'category'} 143 | FRedactionType := AValue.GetValue('type'); 144 | FConfidence := AValue.GetValue('confidence'); 145 | end; 146 | 147 | { TTrancriptAlternative } 148 | 149 | procedure TTrancriptAlternative.LoadObject(const AValue: TJSONObject); 150 | var 151 | I: Integer; 152 | A: TJsonArray; 153 | begin 154 | FContent := AValue.GetValue('content'); 155 | if Redacted then 156 | begin 157 | FRedactions := TObjectList.Create(True); 158 | A := AValue.FindValue('redactions') as TJsonArray; 159 | for I := 0 to A.Count-1 do 160 | FRedactions.Add(TTrancriptRedaction.Create(Transcript, A.Items[I] as TJsonObject)); 161 | FConfidence := 0.0; // not applied 162 | end else 163 | FConfidence := AValue.GetValue('confidence'); 164 | end; 165 | 166 | destructor TTrancriptAlternative.Destroy; 167 | begin 168 | if Redacted then 169 | FRedactions.Free; 170 | inherited; 171 | end; 172 | 173 | function TTrancriptAlternative.GetRedacted: Boolean; 174 | begin 175 | Result := FContent='[PII]'; 176 | end; 177 | 178 | { TTranscriptItem } 179 | 180 | procedure TTranscriptItem.LoadObject(const AValue: TJSONObject); 181 | var 182 | I: Integer; 183 | A: TJsonArray; 184 | begin 185 | FAlternatives := TObjectList.Create(True); 186 | FSegment := nil; 187 | FItemType := TrancriptType(AValue.GetValue('type')); 188 | if FItemType=TTrancriptType.pronunciation then 189 | begin 190 | FStartTime := AValue.GetValue('start_time'); 191 | FEndTime := AValue.GetValue('end_time'); 192 | end else 193 | begin 194 | FStartTime := 0; // not applied 195 | FEndTime := 0; // not applied 196 | end; 197 | A := AValue.FindValue('alternatives') as TJsonArray; 198 | for I := 0 to A.Count-1 do 199 | FAlternatives.Add(TTrancriptAlternative.Create(Transcript, A.Items[I] as TJsonObject)); 200 | end; 201 | 202 | destructor TTranscriptItem.Destroy; 203 | begin 204 | FAlternatives.Free; 205 | inherited; 206 | end; 207 | 208 | function TTranscriptItem.TrancriptType(const AValue: string): TTrancriptType; 209 | begin 210 | Result := TTrancriptType(GetEnumValue(TypeInfo(TTrancriptType), AValue)); 211 | end; 212 | 213 | { TTranscriptSegment } 214 | 215 | procedure TTranscriptSegment.LoadObject(const AValue: TJSONObject); 216 | var 217 | I: Integer; 218 | J: Integer; 219 | A: TJsonArray; 220 | S: Single; 221 | E: Single; 222 | L: string; 223 | O: TTranscriptItem; 224 | begin 225 | FItems := TList.Create; 226 | FStartTime := AValue.GetValue('start_time'); 227 | FEndTime := AValue.GetValue('end_time'); 228 | FSpeakerLabel := AValue.GetValue('speaker_label'); 229 | 230 | A := AValue.FindValue('items') as TJSONArray; 231 | for I := 0 to A.Count-1 do 232 | begin 233 | S := A.Items[I].GetValue('start_time'); 234 | E := A.Items[I].GetValue('end_time'); 235 | L := A.Items[I].GetValue('speaker_label'); 236 | J := Transcript.ItemAt(S); 237 | if J>=0 then 238 | repeat 239 | O := Transcript.Items[J]; 240 | if (O.StartTime=S) and (O.EndTime=E) and (O.Segment=nil) then 241 | begin 242 | O.Segment := Self; 243 | FItems.Add(O); 244 | if (J+1=Transcript.ItemCount) or (Transcript.Items[J].StartTime>S); 257 | end; 258 | 259 | end; 260 | 261 | destructor TTranscriptSegment.Destroy; 262 | begin 263 | FItems.Free; 264 | inherited; 265 | end; 266 | 267 | { TTranscript } 268 | 269 | constructor TTranscript.Create(const AJson: string); 270 | begin 271 | inherited Create; 272 | FSegments := nil; 273 | FItems := TObjectList.Create(True); 274 | LoadTranscript(AJson); 275 | end; 276 | 277 | destructor TTranscript.Destroy; 278 | begin 279 | SetLength(FTexts, 0); 280 | if Assigned(FSegments) then 281 | FSegments.Free; 282 | FItems.Free; 283 | inherited; 284 | end; 285 | 286 | function TTranscript.GetTextCount: Integer; 287 | begin 288 | Result := Length(FTexts); 289 | end; 290 | 291 | function TTranscript.GetItemCount: Integer; 292 | begin 293 | Result := FItems.Count; 294 | end; 295 | 296 | function TTranscript.GetSegmentCount: Integer; 297 | begin 298 | if Assigned(FSegments) then 299 | Result := FSegments.Count 300 | else 301 | Result := 0; // not applied 302 | end; 303 | 304 | function TTranscript.GetTexts(const AIndex: Integer): string; 305 | begin 306 | if (AIndex<0) or (AIndex>=TextCount) then 307 | Result := '' 308 | else 309 | Result := FTexts[AIndex]; 310 | end; 311 | 312 | function TTranscript.GetItems(const AIndex: Integer): TTranscriptItem; 313 | begin 314 | Result := FItems[AIndex]; 315 | end; 316 | 317 | function TTranscript.GetSegments(const AIndex: Integer): TTranscriptSegment; 318 | begin 319 | if SegmentCount>0 then 320 | Result := FSegments[AIndex] 321 | else 322 | Result := nil; 323 | end; 324 | 325 | function TTranscript.ItemAt(const AStartTime: Single): Integer; {not optimal} 326 | var 327 | I: Integer; 328 | begin 329 | Result := -1; 330 | for I := 0 to ItemCount-1 do 331 | if Items[I].StartTime>=AStartTime then 332 | Exit(I); 333 | end; 334 | 335 | procedure TTranscript.LoadTranscript(const AJson: string); 336 | var 337 | I: Integer; 338 | O: TJSONObject; 339 | L: TJSONValue; 340 | A: TJsonArray; 341 | begin 342 | O := TJSONValue.ParseJSONValue(AJson, True) as TJsonObject; 343 | try 344 | FJobName := O.GetValue('jobName'); 345 | if not O.TryGetValue('isRedacted', FIsRedacted) then 346 | FIsRedacted := False; 347 | FSpeakers := 0; // not applied 348 | 349 | { transcripts } 350 | A := O.FindValue('results.transcripts') as TJsonArray; 351 | if (A<>nil) and (A.Count>0) then 352 | begin 353 | SetLength(FTexts, A.Count); 354 | for I := 0 to A.Count-1 do 355 | FTexts[I] := A.Items[I].GetValue('transcript'); 356 | end else 357 | raise Exception.Create('Empty transcript file'); 358 | 359 | { items } 360 | A := O.FindValue('results.items') as TJsonArray; 361 | if (A<>nil) and (A.Count>0) then 362 | begin 363 | for I := 0 to A.Count-1 do 364 | FItems.Add(TTranscriptItem.Create(Self, A.Items[I] as TJSONObject)); 365 | end else 366 | raise Exception.Create('Empty transcript file'); 367 | 368 | { segments } 369 | L := O.FindValue('results.speaker_labels'); 370 | if L<>nil then 371 | begin 372 | FSpeakers := L.GetValue('speakers'); 373 | A := L.FindValue('segments') as TJsonArray; 374 | if (A<>nil) and (A.Count>0) then 375 | begin 376 | FSegments := TObjectList.Create(True); 377 | for I := 0 to A.Count-1 do 378 | FSegments.Add(TTranscriptSegment.Create(Self, A.Items[I] as TJSONObject)); 379 | end; 380 | end; 381 | 382 | finally 383 | O.Free; 384 | end; 385 | end; 386 | 387 | end. 388 | -------------------------------------------------------------------------------- /Source/Transcribe/Forms.TranscriptionJob.pas: -------------------------------------------------------------------------------- 1 | unit Forms.TranscriptionJob; 2 | 3 | interface 4 | 5 | uses 6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, 7 | Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, 8 | Vcl.ComCtrls, Vcl.Buttons, AWS.Transcribe, AWS.Transcribe.Transcript; 9 | 10 | type 11 | TTranscriptOption = (Raw, Segmented); 12 | 13 | TTranscriptionJobForm = class(TForm) 14 | PageControl: TPageControl; 15 | TranscriptTab: TTabSheet; 16 | TranscriptMemo: TMemo; 17 | ViewTranscriptOption: TRadioGroup; 18 | RedactedTranscriptTab: TTabSheet; 19 | RedactedTranscriptMemo: TMemo; 20 | ViewRedactedTranscriptOption: TRadioGroup; 21 | JobDetailsTab: TTabSheet; 22 | Panel1: TPanel; 23 | Panel2: TPanel; 24 | Label1: TLabel; 25 | JobNameEdit: TEdit; 26 | Label2: TLabel; 27 | LanguageCodeEdit: TComboBox; 28 | Label6: TLabel; 29 | MediaUriEdit: TEdit; 30 | Label3: TLabel; 31 | Label4: TLabel; 32 | VocabularyFilterEdit: TComboBox; 33 | Label5: TLabel; 34 | ContentRedactionEdit: TComboBox; 35 | ConfirmButton: TBitBtn; 36 | CancelButton: TBitBtn; 37 | procedure ViewRedactedTranscriptOptionClick(Sender: TObject); 38 | procedure ViewTranscriptOptionClick(Sender: TObject); 39 | procedure FormShow(Sender: TObject); 40 | procedure FormCreate(Sender: TObject); 41 | procedure OnEditChange(Sender: TObject); 42 | procedure PageControlChange(Sender: TObject); 43 | private 44 | FTranscriptionJob: TTranscriptionJob; 45 | FTranscript: TTranscript; 46 | FRedactedTranscript: TTranscript; 47 | function GetJobName: string; 48 | function GetLanguageCode: string; 49 | function GetMediaUri: string; 50 | function GetVocabularyFilter: string; 51 | function GetContentRedaction: string; 52 | procedure SetTranscript(const AValue: TTranscript); 53 | procedure SetRedactedTranscript(const AValue: TTranscript); 54 | private 55 | function InsertMode: Boolean; 56 | procedure ValidateForm; 57 | procedure FillFilterOprions; 58 | procedure FillLanguageOptions; 59 | private 60 | function GetTranscriptPayload(const AUri: string): string; 61 | procedure DisplayTranscript; 62 | procedure DisplayRedactedTranscript; 63 | procedure LoadTranscriptText(const ATranscript: TTranscript; 64 | const AText: TStrings; AOption: TTranscriptOption); 65 | property Transcript: TTranscript read FTranscript write SetTranscript; 66 | property RedactedTranscript: TTranscript read FRedactedTranscript write SetRedactedTranscript; 67 | public 68 | constructor Create(const ATranscriptionJob: TTranscriptionJob); reintroduce; overload; 69 | destructor Destroy; override; 70 | procedure SetTranscriptionJob(const ATranscriptionJob: TTranscriptionJob); 71 | procedure SetAvailableFilter(const AFilterName: string); 72 | property JobName: string read GetJobName; 73 | property LanguageCode: string read GetLanguageCode; 74 | property MediaUri: string read GetMediaUri; 75 | property VocabularyFilter: string read GetVocabularyFilter; 76 | property ContentRedaction: string read GetContentRedaction; 77 | end; 78 | 79 | implementation 80 | 81 | {$R *.dfm} 82 | 83 | uses 84 | Sparkle.Http.Client; 85 | 86 | const 87 | SAMPLE_MEDIA_URI = 'https://aws-ml-blog.s3.amazonaws.com/artifacts/transcribe_audio_processing/medical-diarization.wav'; 88 | VALID_LANG_CODES = 'af-ZA,ar-AE,ar-SA,cy-GB,da-DK,de-CH,de-DE,en-AB,en-AU,en-GB,en-IE,en-IN,en-US,en-WL,es-ES,es-US,fa-IR,fr-CA,fr-FR,ga-IE,gd-GB,he-IL,hi-IN,id-ID,it-IT,ja-JP,ko-KR,ms-MY,nl-NL,pt-BR,pt-PT,ru-RU,ta-IN,te-IN,tr-TR,zh-CN,zh-TW,th-TH,en-ZA,en-NZ'; 89 | 90 | { TTranscriptsForm } 91 | 92 | constructor TTranscriptionJobForm.Create(const ATranscriptionJob: TTranscriptionJob); 93 | begin 94 | inherited Create(nil); 95 | SetTranscriptionJob(ATranscriptionJob); 96 | end; 97 | 98 | destructor TTranscriptionJobForm.Destroy; 99 | begin 100 | Transcript := nil; 101 | RedactedTranscript := nil; 102 | inherited; 103 | end; 104 | 105 | procedure TTranscriptionJobForm.FillLanguageOptions; 106 | begin 107 | LanguageCodeEdit.Items.Clear; 108 | LanguageCodeEdit.Items.CommaText := VALID_LANG_CODES; 109 | LanguageCodeEdit.Items.Insert(0, 'Automatically identify language'); 110 | end; 111 | 112 | procedure TTranscriptionJobForm.FillFilterOprions; 113 | begin 114 | VocabularyFilterEdit.Items.Clear; 115 | VocabularyFilterEdit.Items.Add('None'); 116 | end; 117 | 118 | procedure TTranscriptionJobForm.SetAvailableFilter(const AFilterName: string); 119 | begin 120 | VocabularyFilterEdit.Items.Add(AFilterName); 121 | end; 122 | 123 | function TTranscriptionJobForm.GetJobName: string; 124 | begin 125 | Result := Trim(JobNameEdit.Text); 126 | end; 127 | 128 | function TTranscriptionJobForm.GetLanguageCode: string; 129 | begin 130 | if LanguageCodeEdit.ItemIndex>0 then 131 | Result := LanguageCodeEdit.Text 132 | else 133 | Result := ''; // identify language 134 | end; 135 | 136 | function TTranscriptionJobForm.GetMediaUri: string; 137 | begin 138 | Result := MediaUriEdit.Text; 139 | end; 140 | 141 | function TTranscriptionJobForm.GetVocabularyFilter: string; 142 | begin 143 | if VocabularyFilterEdit.ItemIndex>0 then 144 | Result := VocabularyFilterEdit.Text 145 | else 146 | Result := ''; // do not apply a vocabulary filter 147 | end; 148 | 149 | function TTranscriptionJobForm.GetContentRedaction: string; 150 | begin 151 | case ContentRedactionEdit.ItemIndex of 152 | 1: Result := TRedactionOutput.Redacted.Value; 153 | 2: Result := TRedactionOutput.Redacted_and_unredacted.Value; 154 | else 155 | Result := ''; // do not apply content redaction 156 | end; 157 | end; 158 | 159 | function TTranscriptionJobForm.InsertMode: Boolean; 160 | begin 161 | Result := FTranscriptionJob = nil; 162 | end; 163 | 164 | procedure TTranscriptionJobForm.OnEditChange(Sender: TObject); 165 | begin 166 | ValidateForm; 167 | end; 168 | 169 | procedure TTranscriptionJobForm.PageControlChange(Sender: TObject); 170 | begin 171 | if PageControl.ActivePage=TranscriptTab then 172 | begin 173 | if TranscriptMemo.Lines.Text='' then 174 | DisplayTranscript; 175 | end else 176 | if PageControl.ActivePage=RedactedTranscriptTab then 177 | begin 178 | if RedactedTranscriptMemo.Lines.Text='' then 179 | DisplayRedactedTranscript; 180 | end; 181 | end; 182 | 183 | procedure TTranscriptionJobForm.ValidateForm; 184 | begin 185 | ConfirmButton.Enabled := (JobName<>'') and (Pos(' ', JobName)=0) and (MediaUri<>''); 186 | end; 187 | 188 | procedure TTranscriptionJobForm.SetTranscriptionJob(const ATranscriptionJob: TTranscriptionJob); 189 | var 190 | Json: string; 191 | begin 192 | FTranscriptionJob := ATranscriptionJob; 193 | if ATranscriptionJob.Transcript.IsSetTranscriptFileUri then 194 | begin 195 | Json := GetTranscriptPayload(ATranscriptionJob.Transcript.TranscriptFileUri); 196 | Transcript := TTranscript.Create(Json); 197 | end else 198 | Transcript := nil; 199 | if ATranscriptionJob.Transcript.IsSetRedactedTranscriptFileUri then 200 | begin 201 | Json := GetTranscriptPayload(ATranscriptionJob.Transcript.RedactedTranscriptFileUri); 202 | RedactedTranscript := TTranscript.Create(Json); 203 | end else 204 | RedactedTranscript := nil; 205 | end; 206 | 207 | function TTranscriptionJobForm.GetTranscriptPayload(const AUri: string): string; 208 | var 209 | CLient: THttpClient; 210 | Response: THttpResponse; 211 | begin 212 | Client := THttpClient.Create; 213 | try 214 | Response := Client.Get(AUri); 215 | try 216 | Result := TEncoding.UTF8.GetString(Response.ContentAsBytes); 217 | finally 218 | Response.Free; 219 | end; 220 | finally 221 | Client.Free; 222 | end; 223 | end; 224 | 225 | procedure TTranscriptionJobForm.SetTranscript(const AValue: TTranscript); 226 | begin 227 | if FTranscript<>nil then 228 | FTranscript.Free; 229 | FTranscript := AValue; 230 | end; 231 | 232 | procedure TTranscriptionJobForm.SetRedactedTranscript(const AValue: TTranscript); 233 | begin 234 | if FRedactedTranscript<>nil then 235 | FRedactedTranscript.Free; 236 | FRedactedTranscript := AValue; 237 | end; 238 | 239 | procedure TTranscriptionJobForm.FormCreate(Sender: TObject); 240 | begin 241 | TranscriptTab.TabVisible := False; 242 | RedactedTranscriptTab.TabVisible := False; 243 | FillLanguageOptions; 244 | FillFilterOprions; 245 | end; 246 | 247 | procedure TTranscriptionJobForm.FormShow(Sender: TObject); 248 | begin 249 | ViewTranscriptOption.ItemIndex := 0; 250 | ViewRedactedTranscriptOption.ItemIndex := 0; 251 | if InsertMode then 252 | begin 253 | MediaUriEdit.Text := SAMPLE_MEDIA_URI; 254 | LanguageCodeEdit.ItemIndex := LanguageCodeEdit.Items.IndexOf(TLanguageCode.EnUS.Value); // since sample media is en-US 255 | VocabularyFilterEdit.ItemIndex := 0; 256 | ContentRedactionEdit.ItemIndex := 0; 257 | end else 258 | begin 259 | JobNameEdit.Text := FTranscriptionJob.TranscriptionJobName; 260 | if (FTranscriptionJob.IsSetIdentifyLanguage=False) or (FTranscriptionJob.IdentifyLanguage=False) then 261 | begin 262 | LanguageCodeEdit.Style := csDropDown; 263 | LanguageCodeEdit.Text := FTranscriptionJob.LanguageCode.Value; 264 | end else 265 | LanguageCodeEdit.ItemIndex := 0; 266 | MediaUriEdit.Text := FTranscriptionJob.Media.MediaFileUri; 267 | if FTranscriptionJob.Settings.IsSetVocabularyFilterName then 268 | begin 269 | VocabularyFilterEdit.Style := csDropDown; 270 | VocabularyFilterEdit.Text := FTranscriptionJob.Settings.VocabularyFilterName; 271 | end else 272 | VocabularyFilterEdit.ItemIndex := 0; 273 | if FTranscriptionJob.IsSetContentRedaction then 274 | begin 275 | if FTranscriptionJob.ContentRedaction.RedactionOutput=TRedactionOutput.Redacted then 276 | ContentRedactionEdit.ItemIndex := 1 277 | else 278 | ContentRedactionEdit.ItemIndex := 2; 279 | end else 280 | ContentRedactionEdit.ItemIndex := 0; 281 | if (FTranscriptionJob.TranscriptionJobStatus=TTranscriptionJobStatus.COMPLETED) and 282 | (FTranscriptionJob.IsSetTranscript) then 283 | begin 284 | TranscriptTab.TabVisible := (FTranscriptionJob.Transcript.IsSetTranscriptFileUri); 285 | RedactedTranscriptTab.TabVisible := (FTranscriptionJob.Transcript.IsSetRedactedTranscriptFileUri); 286 | end; 287 | end; 288 | PageControl.ActivePageIndex := 0; 289 | JobNameEdit.Enabled := InsertMode; 290 | LanguageCodeEdit.Enabled := InsertMode; 291 | MediaUriEdit.Enabled := InsertMode; 292 | ConfirmButton.Visible := InsertMode; 293 | VocabularyFilterEdit.Enabled := InsertMode; 294 | ContentRedactionEdit.Enabled := InsertMode; 295 | end; 296 | 297 | procedure TTranscriptionJobForm.DisplayTranscript; 298 | begin 299 | if Transcript<>nil then 300 | begin 301 | TranscriptTab.TabVisible := True; 302 | LoadTranscriptText(Transcript, TranscriptMemo.Lines, 303 | TTranscriptOption(ViewTranscriptOption.ItemIndex)); 304 | end else 305 | TranscriptTab.TabVisible := False; 306 | end; 307 | 308 | procedure TTranscriptionJobForm.DisplayRedactedTranscript; 309 | begin 310 | if RedactedTranscript<>nil then 311 | begin 312 | RedactedTranscriptTab.TabVisible := True; 313 | LoadTranscriptText(RedactedTranscript, RedactedTranscriptMemo.Lines, 314 | TTranscriptOption(ViewRedactedTranscriptOption.ItemIndex)); 315 | end else 316 | RedactedTranscriptTab.TabVisible := False; 317 | end; 318 | 319 | procedure TTranscriptionJobForm.ViewTranscriptOptionClick(Sender: TObject); 320 | begin 321 | if Transcript<>nil then 322 | DisplayTranscript; 323 | end; 324 | 325 | procedure TTranscriptionJobForm.ViewRedactedTranscriptOptionClick(Sender: TObject); 326 | begin 327 | if RedactedTranscript<>nil then 328 | DisplayRedactedTranscript; 329 | end; 330 | 331 | procedure TTranscriptionJobForm.LoadTranscriptText(const ATranscript: TTranscript; 332 | const AText: TStrings; AOption: TTranscriptOption); 333 | var 334 | I: Integer; 335 | S: string; 336 | TranscriptItem: TTranscriptItem; 337 | begin 338 | AText.Clear; 339 | if ATranscript<>nil then 340 | begin 341 | if (AOption=TTranscriptOption.Segmented) and (ATranscript.SegmentCount>1) then 342 | begin 343 | for I := 0 to ATranscript.SegmentCount-1 do 344 | begin 345 | S := Format('[%s]', [ATranscript.Segments[I].SpeakerLabel]); 346 | for TranscriptItem in ATranscript.Segments[I].Items do 347 | begin 348 | if TranscriptItem.ItemType=TTrancriptType.pronunciation then 349 | S := S + ' '; 350 | S := S + TranscriptItem.Alternatives[0].Content; // use the first alternative 351 | end; 352 | AText.Add(S); 353 | AText.Add(''); 354 | end; 355 | end else 356 | begin 357 | for I := 0 to ATranscript.TextCount-1 do 358 | begin 359 | AText.Add(ATranscript[I]); 360 | AText.Add(''); 361 | end; 362 | end; 363 | AText.Delete(AText.Count-1); 364 | end; 365 | end; 366 | 367 | end. 368 | -------------------------------------------------------------------------------- /Source/Transcribe/Forms.Main.pas: -------------------------------------------------------------------------------- 1 | unit Forms.Main; 2 | 3 | interface 4 | 5 | uses 6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, System.UITypes, 7 | Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, 8 | Vcl.ExtCtrls, Vcl.Buttons, Generics.Collections, AWS.Transcribe, AWS.Transcribe.Transcript, 9 | AWS.Transcribe.VocabularyFilter; 10 | 11 | type 12 | TJobStatus = (COMPLETED, FAILED, IN_PROGRESS, QUEUED); 13 | 14 | TJobParams = record 15 | JobName: string; 16 | LanguageCode: string; 17 | MediaUri: string; 18 | VocabularyFilter: string; 19 | ContentRedaction: string; 20 | end; 21 | 22 | TFilterParams = record 23 | FilterName: string; 24 | LanguageCode: string; 25 | Words: TArray; 26 | end; 27 | 28 | TMainForm = class(TForm) 29 | PageControl: TPageControl; 30 | JobsTab: TTabSheet; 31 | FiltersTab: TTabSheet; 32 | Panel2: TPanel; 33 | Label2: TLabel; 34 | ListJobsButton: TSpeedButton; 35 | DeleteJobButton: TSpeedButton; 36 | ViewJobButton: TSpeedButton; 37 | CreateJobButton: TSpeedButton; 38 | JobsView: TListView; 39 | Panel3: TPanel; 40 | Label3: TLabel; 41 | ListFiltersButton: TSpeedButton; 42 | DeleteFilterButton: TSpeedButton; 43 | ViewFilterButton: TSpeedButton; 44 | CreateFilterButton: TSpeedButton; 45 | FiltersView: TListView; 46 | procedure FormCreate(Sender: TObject); 47 | procedure FormShow(Sender: TObject); 48 | procedure ListFiltersButtonClick(Sender: TObject); 49 | procedure FormDestroy(Sender: TObject); 50 | procedure CreateFilterButtonClick(Sender: TObject); 51 | procedure ListJobsButtonClick(Sender: TObject); 52 | procedure CreateJobButtonClick(Sender: TObject); 53 | procedure DeleteJobButtonClick(Sender: TObject); 54 | procedure DeleteFilterButtonClick(Sender: TObject); 55 | procedure ViewJobButtonClick(Sender: TObject); 56 | procedure JobsViewData(Sender: TObject; Item: TListItem); 57 | procedure JobsViewChange(Sender: TObject; Item: TListItem; Change: TItemChange); 58 | procedure JobsViewCustomDrawSubItem(Sender: TCustomListView; Item: TListItem; 59 | SubItem: Integer; State: TCustomDrawState; var DefaultDraw: Boolean); 60 | procedure ViewFilterButtonClick(Sender: TObject); 61 | procedure FiltersViewData(Sender: TObject; Item: TListItem); 62 | procedure PageControlChange(Sender: TObject); 63 | procedure FiltersViewChange(Sender: TObject; Item: TListItem; Change: TItemChange); 64 | private 65 | FJobs: TObjectList; 66 | FFilters: TObjectList; 67 | FLoadedFilters: Boolean; 68 | procedure SetJobs(const AValue: TObjectList); 69 | procedure SetFilters(const AValue: TObjectList); 70 | function GetSelectedJob: TTranscriptionJobSummary; 71 | function GetSelectedFilter: TVocabularyFilterInfo; 72 | private 73 | function JobStatus(const AValue: string): TJobStatus; 74 | function BuildTranscriptionJobRequest(const AParams: TJobParams): IStartTranscriptionJobRequest; 75 | public 76 | procedure CreateTrancriptionJob(const AParams: TJobParams); 77 | procedure ListTrancriptionsJobs; 78 | function GetTranscriptionJob(const AName: string): TTranscriptionJob; 79 | procedure DeleteTrancriptionJob(const AName: string); 80 | procedure CreateVocabularyFilter(const AParams: TFilterParams); 81 | procedure ListVocabularyFilters; 82 | function GetVocabularyFilter(const AName: string): TVocabularyFilter; 83 | procedure DeleteVocabularyFilter(const AName: string); 84 | public 85 | property Jobs: TObjectList read FJobs write SetJobs; 86 | property SelectedJob: TTranscriptionJobSummary read GetSelectedJob; 87 | property Filters: TObjectList read FFilters write SetFilters; 88 | property SelectedFilter: TVocabularyFilterInfo read GetSelectedFilter; 89 | end; 90 | 91 | var 92 | MainForm: TMainForm; 93 | 94 | implementation 95 | 96 | uses 97 | System.TypInfo, 98 | AWS.Internal.WebResponseData, 99 | Forms.TranscriptionJob, 100 | Forms.VocabularyFilter; 101 | 102 | {$R *.dfm} 103 | 104 | { TMainForm } 105 | 106 | procedure TMainForm.FormCreate(Sender: TObject); 107 | begin 108 | FJobs := TObjectList.Create(True); 109 | FFilters := TObjectList.Create(True); 110 | FLoadedFilters := False; 111 | end; 112 | 113 | procedure TMainForm.FormDestroy(Sender: TObject); 114 | begin 115 | Filters := nil; 116 | Jobs := nil; 117 | end; 118 | 119 | procedure TMainForm.FormShow(Sender: TObject); 120 | begin 121 | PageControl.ActivePageIndex := 0; 122 | ListJobsButton.Click; 123 | end; 124 | 125 | procedure TMainForm.PageControlChange(Sender: TObject); 126 | begin 127 | if (PageControl.ActivePage=FiltersTab) and (not FLoadedFilters) then 128 | begin 129 | FLoadedFilters := True; 130 | ListVocabularyFilters; 131 | end; 132 | end; 133 | 134 | { Transcription Jobs Tab } 135 | 136 | procedure TMainForm.ListJobsButtonClick(Sender: TObject); 137 | begin 138 | Screen.Cursor := crHourGlass; 139 | try 140 | ListTrancriptionsJobs; 141 | finally 142 | Screen.Cursor := crDefault; 143 | end; 144 | end; 145 | 146 | procedure TMainForm.CreateJobButtonClick(Sender: TObject); 147 | var 148 | I: Integer; 149 | JobParams: TJobParams; 150 | begin 151 | { get available filters } 152 | if FFilters.Count=0 then 153 | ListFiltersButton.Click; 154 | { create job } 155 | with TTranscriptionJobForm.Create(Self) do 156 | try 157 | for I := 0 to FFilters.Count-1 do 158 | SetAvailableFilter(FFilters[I].VocabularyFilterName); 159 | if ShowModal=mrOk then 160 | begin 161 | Screen.Cursor := crHourGlass; 162 | try 163 | JobParams.JobName := JobName; 164 | JobParams.LanguageCode := LanguageCode; 165 | JobParams.MediaUri := MediaUri; 166 | JobParams.VocabularyFilter := VocabularyFilter; 167 | JobParams.ContentRedaction := ContentRedaction; 168 | CreateTrancriptionJob(JobParams); 169 | ListTrancriptionsJobs; 170 | finally 171 | Screen.Cursor := crDefault; 172 | end; 173 | end; 174 | finally 175 | Free; 176 | end; 177 | end; 178 | 179 | procedure TMainForm.ViewJobButtonClick(Sender: TObject); 180 | var 181 | Job: TTranscriptionJob; 182 | begin 183 | if (SelectedJob<>nil) {and (SelectedJob.TranscriptionJobStatus=TTranscriptionJobStatus.COMPLETED)} then 184 | begin 185 | Screen.Cursor := crHourGlass; 186 | try 187 | Job := GetTranscriptionJob(SelectedJob.TranscriptionJobName); 188 | finally 189 | Screen.Cursor := crDefault; 190 | end; 191 | with TTranscriptionJobForm.Create(Job) do 192 | try 193 | ShowModal; 194 | finally 195 | Job.Free; 196 | Free; 197 | end; 198 | end else 199 | MessageDlg('Select a Job to view details', TMsgDlgType.mtInformation, [mbOK], 0); 200 | end; 201 | 202 | procedure TMainForm.DeleteJobButtonClick(Sender: TObject); 203 | begin 204 | if SelectedJob<>nil then 205 | begin 206 | if MessageDlg(Format('Delete job %s?', [SelectedJob.TranscriptionJobName]), 207 | TMsgDlgType.mtConfirmation, mbYesNo, 0) = mrYes then 208 | try 209 | Screen.Cursor := crHourGlass; 210 | DeleteTrancriptionJob(SelectedJob.TranscriptionJobName); 211 | ListTrancriptionsJobs; 212 | finally 213 | Screen.Cursor := crDefault; 214 | end; 215 | end else 216 | MessageDlg('Select a Job to delete', TMsgDlgType.mtInformation, [mbOK], 0); 217 | end; 218 | 219 | procedure TMainForm.JobsViewData(Sender: TObject; Item: TListItem); 220 | var 221 | lJob: TTranscriptionJobSummary; 222 | begin 223 | lJob := Jobs[Item.Index]; 224 | Item.Caption := lJob.TranscriptionJobName; 225 | Item.SubItems.Add(lJob.LanguageCode.Value); 226 | Item.SubItems.Add(DateTimeToStr(lJob.CreationTime)); 227 | Item.SubItems.Add(lJob.TranscriptionJobStatus.Value); 228 | end; 229 | 230 | procedure TMainForm.JobsViewCustomDrawSubItem(Sender: TCustomListView; Item: TListItem; 231 | SubItem: Integer; State: TCustomDrawState; var DefaultDraw: Boolean); 232 | var 233 | lStatus: TJobStatus; 234 | lFColor: TColor; 235 | begin 236 | DefaultDraw := True; 237 | lFColor := clBlack; 238 | if (SubItem=3) then // status column 239 | begin 240 | lStatus := JobStatus(Jobs[Item.Index].TranscriptionJobStatus.Value); 241 | case lStatus of 242 | QUEUED: lFColor := clGray; 243 | IN_PROGRESS: lFColor := clBlue; 244 | COMPLETED: lFColor := clGreen; 245 | FAILED: lFColor := clRed; 246 | end; 247 | end; 248 | Sender.Canvas.Font.Color := lFColor; 249 | end; 250 | 251 | procedure TMainForm.JobsViewChange(Sender: TObject; Item: TListItem; Change: TItemChange); 252 | begin 253 | DeleteJobButton.Enabled := (JobsView.ItemIndex>=0); 254 | ViewJobButton.Enabled := (JobsView.ItemIndex>=0) 255 | and (Jobs[JobsView.ItemIndex].TranscriptionJobStatus = TTranscriptionJobStatus.COMPLETED); 256 | end; 257 | 258 | { Vocabulary Filters Tab } 259 | 260 | procedure TMainForm.ListFiltersButtonClick(Sender: TObject); 261 | begin 262 | Screen.Cursor := crHourGlass; 263 | try 264 | ListVocabularyFilters; 265 | finally 266 | Screen.Cursor := crDefault; 267 | end; 268 | end; 269 | 270 | procedure TMainForm.CreateFilterButtonClick(Sender: TObject); 271 | var 272 | FilterParams: TFilterParams; 273 | begin 274 | with TVocabularyFilterForm.Create(Self) do 275 | try 276 | if ShowModal=mrOk then 277 | begin 278 | Screen.Cursor := crHourGlass; 279 | try 280 | FilterParams.FilterName := FilterName; 281 | FilterParams.LanguageCode := LanguageCode; 282 | FilterParams.Words := Words; 283 | CreateVocabularyFilter(FilterParams); 284 | ListVocabularyFilters; 285 | finally 286 | Screen.Cursor := crDefault; 287 | end; 288 | end; 289 | finally 290 | Free; 291 | end; 292 | end; 293 | 294 | procedure TMainForm.ViewFilterButtonClick(Sender: TObject); 295 | var 296 | Filter: TVocabularyFilter; 297 | begin 298 | if (SelectedFilter<>nil) then 299 | begin 300 | Screen.Cursor := crHourGlass; 301 | try 302 | Filter := GetVocabularyFilter(SelectedFilter.VocabularyFilterName); 303 | finally 304 | Screen.Cursor := crDefault; 305 | end; 306 | with TVocabularyFilterForm.Create(Filter) do 307 | try 308 | ShowModal; 309 | finally 310 | Filter.Free; 311 | Free; 312 | end; 313 | end else 314 | MessageDlg('Select a Filter to view details', TMsgDlgType.mtInformation, [mbOK], 0); 315 | end; 316 | 317 | procedure TMainForm.DeleteFilterButtonClick(Sender: TObject); 318 | begin 319 | if SelectedFilter<>nil then 320 | begin 321 | if MessageDlg(Format('Delete filter %s?', [SelectedFilter.VocabularyFilterName]), 322 | TMsgDlgType.mtConfirmation, mbYesNo, 0) = mrYes then 323 | try 324 | Screen.Cursor := crHourGlass; 325 | DeleteVocabularyFilter(SelectedFilter.VocabularyFilterName); 326 | ListVocabularyFilters; 327 | finally 328 | Screen.Cursor := crDefault; 329 | end; 330 | end else 331 | MessageDlg('Select a Filter to delete', TMsgDlgType.mtInformation, [mbOK], 0); 332 | end; 333 | 334 | procedure TMainForm.FiltersViewData(Sender: TObject; Item: TListItem); 335 | var 336 | lFilter: TVocabularyFilterInfo; 337 | begin 338 | lFilter := Filters[Item.Index]; 339 | Item.Caption := lFilter.VocabularyFilterName; 340 | Item.SubItems.Add(lFilter.LanguageCode.Value); 341 | Item.SubItems.Add(DateTimeToStr(lFilter.LastModifiedTime)); 342 | end; 343 | 344 | procedure TMainForm.FiltersViewChange(Sender: TObject; Item: TListItem; Change: TItemChange); 345 | begin 346 | DeleteFilterButton.Enabled := (FiltersView.ItemIndex>=0); 347 | ViewFilterButton.Enabled := (FiltersView.ItemIndex>=0); 348 | end; 349 | 350 | { Getters and Setters } 351 | 352 | function TMainForm.GetSelectedJob: TTranscriptionJobSummary; 353 | begin 354 | if (JobsView.Items.Count>0) and (JobsView.ItemIndex>=0) then 355 | Result := Jobs[JobsView.ItemIndex] 356 | else 357 | Result := nil; 358 | end; 359 | 360 | function TMainForm.GetSelectedFilter: TVocabularyFilterInfo; 361 | begin 362 | if (FiltersView.Items.Count>0) and (FiltersView.ItemIndex>=0) then 363 | Result := Filters[FiltersView.ItemIndex] 364 | else 365 | Result := nil; 366 | end; 367 | 368 | procedure TMainForm.SetJobs(const AValue: TObjectList); 369 | begin 370 | if FJobs<>nil then 371 | FJobs.Free; 372 | FJobs := AValue; 373 | if FJobs<>nil then 374 | begin 375 | JobsView.Items.Count := FJobs.Count; 376 | JobsView.Invalidate; 377 | end else 378 | JobsView.Items.Count := 0; 379 | end; 380 | 381 | procedure TMainForm.SetFilters(const AValue: TObjectList); 382 | begin 383 | if FFilters<>nil then 384 | FFilters.Free; 385 | FFilters := AValue; 386 | if FFilters<>nil then 387 | begin 388 | FiltersView.Items.Count := FFilters.Count; 389 | FiltersView.Invalidate; 390 | end else 391 | FiltersView.Items.Count := 0; 392 | end; 393 | 394 | { helper functions } 395 | 396 | function TMainForm.JobStatus(const AValue: string): TJobStatus; 397 | begin 398 | Result := TJobStatus(GetEnumValue(TypeInfo(TJobStatus), AValue)); 399 | end; 400 | 401 | { AWS actions for Jobs } 402 | 403 | procedure TMainForm.ListTrancriptionsJobs; 404 | var 405 | Client: IAmazonTranscribeService; 406 | Request: IListTranscriptionJobsRequest; 407 | Response: IListTranscriptionJobsResponse; 408 | begin 409 | // Create client 410 | Client := TAmazonTranscribeServiceClient.Create; 411 | 412 | // Setup request 413 | Request := TListTranscriptionJobsRequest.Create; 414 | Request.MaxResults := 20; 415 | 416 | // Execute 417 | Response := Client.ListTranscriptionJobs(Request); 418 | 419 | if Response.HttpStatusCode=200 then 420 | begin 421 | Response.KeepTranscriptionJobSummaries := True; 422 | Jobs := Response.TranscriptionJobSummaries; 423 | end; 424 | end; 425 | 426 | procedure TMainForm.CreateTrancriptionJob(const AParams: TJobParams); 427 | var 428 | Client: IAmazonTranscribeService; 429 | Request: IStartTranscriptionJobRequest; 430 | Response: IStartTranscriptionJobResponse; 431 | begin 432 | // Create client 433 | Client := TAmazonTranscribeServiceClient.Create; 434 | 435 | // Setup request 436 | Request := BuildTranscriptionJobRequest(AParams); 437 | 438 | // Execute 439 | Response := Client.StartTranscriptionJob(Request); 440 | end; 441 | 442 | function TMainForm.BuildTranscriptionJobRequest(const AParams: TJobParams): IStartTranscriptionJobRequest; 443 | 444 | function GetMediaFormat(const AUri: string): string; 445 | begin 446 | Result := StringReplace(ExtractFileExt(AUri), '.', '', []); 447 | end; 448 | 449 | var 450 | Media: TMedia; 451 | Redaction: TContentRedaction; 452 | Settings: TSettings; 453 | begin 454 | Media := TMedia.Create; 455 | Media.MediaFileUri := AParams.MediaUri; 456 | 457 | Redaction := nil; 458 | if AParams.ContentRedaction<>'' then 459 | begin 460 | Redaction := TContentRedaction.Create; 461 | with Redaction do 462 | begin 463 | RedactionType := TRedactionType.PII; 464 | RedactionOutput := AParams.ContentRedaction; 465 | PiiEntityTypes := TList.Create(['NAME']); // suppress people's names 466 | end; 467 | end; 468 | 469 | Settings := TSettings.Create; 470 | with Settings do 471 | begin 472 | ShowAlternatives := True; 473 | MaxAlternatives := 2; 474 | ShowSpeakerLabels := True; 475 | MaxSpeakerLabels := 2; 476 | if AParams.VocabularyFilter<>'' then 477 | begin 478 | VocabularyFilterMethod := TVocabularyFilterMethod.Mask; // mask filtered words 479 | VocabularyFilterName := AParams.VocabularyFilter; 480 | end; 481 | end; 482 | 483 | Result := TStartTranscriptionJobRequest.Create; 484 | Result.TranscriptionJobName := AParams.JobName; { required } 485 | if AParams.LanguageCode<>'' then 486 | Result.LanguageCode := AParams.LanguageCode { eg. TLanguageCode.EnUS } 487 | else 488 | Result.IdentifyLanguage := True; { required: LanguageCode or IdentifyLanguage } 489 | Result.Media := Media; { required } 490 | Result.MediaFormat := GetMediaFormat(AParams.MediaUri); { not required; eg. TMediaFormat.Wav } 491 | Result.Settings := Settings; 492 | if AParams.ContentRedaction<>'' then 493 | Result.ContentRedaction := Redaction; 494 | end; 495 | 496 | function TMainForm.GetTranscriptionJob(const AName: string): TTranscriptionJob; 497 | var 498 | Client: IAmazonTranscribeService; 499 | Request: IGetTranscriptionJobRequest; 500 | Response: IGetTranscriptionJobResponse; 501 | begin 502 | // Create client 503 | Client := TAmazonTranscribeServiceClient.Create; 504 | 505 | // Setup request 506 | Request := TGetTranscriptionJobRequest.Create; 507 | Request.TranscriptionJobName := AName; 508 | 509 | // Execute 510 | Response := Client.GetTranscriptionJob(Request); 511 | 512 | if (Response.HttpStatusCode=200) then 513 | begin 514 | Result := Response.TranscriptionJob; 515 | Response.KeepTranscriptionJob := True; 516 | end else 517 | Result := nil; 518 | 519 | end; 520 | 521 | procedure TMainForm.DeleteTrancriptionJob(const AName: string); 522 | var 523 | Client: IAmazonTranscribeService; 524 | Request: IDeleteTranscriptionJobRequest; 525 | Response: IDeleteTranscriptionJobResponse; 526 | begin 527 | // Create client 528 | Client := TAmazonTranscribeServiceClient.Create; 529 | 530 | // Setup request 531 | Request := TDeleteTranscriptionJobRequest.Create; 532 | Request.TranscriptionJobName := AName; 533 | 534 | // Execute 535 | Response := Client.DeleteTranscriptionJob(Request); 536 | if Response.HttpStatusCode=200 then 537 | ShowMessage('Job successfully deleted'); 538 | end; 539 | 540 | { AWS actions for Filters } 541 | 542 | procedure TMainForm.ListVocabularyFilters; 543 | var 544 | Client: IAmazonTranscribeService; 545 | Request: IListVocabularyFiltersRequest; 546 | Response: IListVocabularyFiltersResponse; 547 | begin 548 | // Create client 549 | Client := TAmazonTranscribeServiceClient.Create; 550 | 551 | // Setup request 552 | Request := TListVocabularyFiltersRequest.Create; 553 | 554 | // Execute 555 | Response := Client.ListVocabularyFilters(Request); 556 | 557 | if Response.HttpStatusCode=200 then 558 | begin 559 | Response.KeepVocabularyFilters := True; 560 | Filters := Response.VocabularyFilters; 561 | end; 562 | end; 563 | 564 | procedure TMainForm.CreateVocabularyFilter(const AParams: TFilterParams); 565 | var 566 | Client: IAmazonTranscribeService; 567 | Request: ICreateVocabularyFilterRequest; 568 | Response: ICreateVocabularyFilterResponse; 569 | begin 570 | // Create client 571 | Client := TAmazonTranscribeServiceClient.Create; 572 | 573 | // Setup request 574 | Request := TCreateVocabularyFilterRequest.Create; 575 | Request.VocabularyFilterName := AParams.FilterName; 576 | Request.LanguageCode := AParams.LanguageCode; 577 | Request.Words := TList.Create(AParams.Words); // some words to the vocabulary filter 578 | 579 | try 580 | Response := Client.CreateVocabularyFilter(Request); 581 | if Response.HttpStatusCode=200 then 582 | ShowMessage(Format('Vocabulary filter "%s" successfully created.', [AParams.FilterName])); 583 | except 584 | on E: EHttpErrorResponseException do 585 | ShowMessage(E.Message); // do something with E 586 | end; 587 | end; 588 | 589 | function TMainForm.GetVocabularyFilter(const AName: string): TVocabularyFilter; 590 | var 591 | Client: IAmazonTranscribeService; 592 | Request: IGetVocabularyFilterRequest; 593 | Response: IGetVocabularyFilterResponse; 594 | begin 595 | // Create client 596 | Client := TAmazonTranscribeServiceClient.Create; 597 | 598 | // Setup request 599 | Request := TGetVocabularyFilterRequest.Create; 600 | Request.VocabularyFilterName := AName; 601 | 602 | // Execute 603 | Response := Client.GetVocabularyFilter(Request); 604 | 605 | if (Response.HttpStatusCode=200) then 606 | begin 607 | Result := TVocabularyFilter.Create; 608 | if Response.IsSetDownloadUri then 609 | Result.DownloadUri := Response.DownloadUri; 610 | if Response.IsSetLanguageCode then 611 | Result.LanguageCode := Response.LanguageCode; 612 | if Response.IsSetLastModifiedTime then 613 | Result.LastModifiedTime := Response.LastModifiedTime; 614 | if Response.IsSetVocabularyFilterName then 615 | Result.VocabularyFilterName := Response.VocabularyFilterName; 616 | end else 617 | Result := nil; 618 | 619 | end; 620 | 621 | procedure TMainForm.DeleteVocabularyFilter(const AName: string); 622 | var 623 | Client: IAmazonTranscribeService; 624 | Request: IDeleteVocabularyFilterRequest; 625 | Response: IDeleteVocabularyFilterResponse; 626 | begin 627 | // Create client 628 | Client := TAmazonTranscribeServiceClient.Create; 629 | 630 | // Setup request 631 | Request := TDeleteVocabularyFilterRequest.Create; 632 | Request.VocabularyFilterName := AName; 633 | 634 | // Execute 635 | Response := Client.DeleteVocabularyFilter(Request); 636 | if Response.HttpStatusCode=200 then 637 | ShowMessage('Filter successfully deleted'); 638 | end; 639 | 640 | end. 641 | 642 | -------------------------------------------------------------------------------- /Source/Lex/AWSLexSample.dproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | {6E8EECD8-458A-44C2-AB96-91A9013671F2} 4 | 20.1 5 | VCL 6 | True 7 | Debug 8 | Win32 9 | 1 10 | Application 11 | AWSLexSample.dpr 12 | 13 | 14 | true 15 | 16 | 17 | true 18 | Base 19 | true 20 | 21 | 22 | true 23 | Base 24 | true 25 | 26 | 27 | true 28 | Base 29 | true 30 | 31 | 32 | true 33 | Cfg_1 34 | true 35 | true 36 | 37 | 38 | true 39 | Base 40 | true 41 | 42 | 43 | true 44 | Cfg_2 45 | true 46 | true 47 | 48 | 49 | .\$(Platform)\$(Config) 50 | .\$(Platform)\$(Config) 51 | false 52 | false 53 | false 54 | false 55 | false 56 | System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) 57 | $(BDS)\bin\delphi_PROJECTICON.ico 58 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png 59 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png 60 | AWSLexSample 61 | 62 | 63 | DBXSqliteDriver;RESTComponents;fmxase;DBXDb2Driver;DBXInterBaseDriver;ZComponent;FlexCel_Pdf;vclactnband;ZCore;vclFireDAC;FMX_FlexCel_Core;bindcompvclsmp;emsclientfiredac;tethering;svnui;DataSnapFireDAC;FireDACADSDriver;DBXMSSQLDriver;TMSScripter;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;svn;SKIA_FlexCel_Core;DBXOracleDriver;FlexCel_Report;inetdb;FmxTeeUI;emsedge;TMSScripter_Memo;fmx;FireDACIBDriver;fmxdae;VCL_FlexCel_Components;TMSVCLUIPackPkgWizDXE13;vcledge;vclib;TMSCryptoPkgDEDXE13;FireDACDBXDriver;dbexpress;IndyCore;TMSVCLUIPackPkgXlsDXE13;xdata;vclx;ZParseSql;dsnap;emsclient;DataSnapCommon;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLTMSFNCCorePkgDXE13;VCLRESTComponents;soapserver;TMSScripter_Legacy;FMXTMSFNCUIPackPkgDXE13;VCLTMSFNCUIPackPkgDXE13;TMSScripter_VCL;vclie;remotedb;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;TMSVCLUIPackPkgDXE13;FireDACCommonODBC;FireDACCommonDriver;TMSWEBCorePkgLibDXE13;DataSnapClient;TMSCryptoPkgDXE13;inet;TMSVCLUIPackPkgExDXE13;IndyIPCommon;bindcompdbx;vcl;IndyIPServer;DBXSybaseASEDriver;sparkle;tmsbcl;IndySystem;FireDACDb2Driver;VCLTMSFNCMapsPkgDXE13;bindcompvclwinx;dsnapcon;VirtualTreesR;TMSWorkflow;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;ZDbc;TeeDB;FireDAC;FMXTMSFNCCorePkgDXE13;FlexCel_XlsAdapter;emshosting;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;TMSWEBCorePkgDXE13;DBXOdbcDriver;FireDACTDataDriver;FMXTee;TMSDiagram;xauth;soaprtl;DbxCommonDriver;FMXTMSFNCMapsPkgDXE13;FlexCel_Core;ibxpress;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;emsserverresource;DbxClientDriver;ibxbindings;DBXSybaseASADriver;TMSScripter_IDE;CustomIPTransport;vcldsnap;bindcomp;appanalytics;ZPlain;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;FMX_FlexCel_Components;dbxcds;VclSmp;VCL_FlexCel_Core;adortl;FireDACODBCDriver;FlexCel_Render;DataSnapIndy10ServerTransport;aurelius;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage) 64 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 65 | Debug 66 | true 67 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 68 | 1033 69 | $(BDS)\bin\default_app.manifest 70 | 71 | 72 | DBXSqliteDriver;RESTComponents;fmxase;DBXDb2Driver;DBXInterBaseDriver;ZComponent;FlexCel_Pdf;vclactnband;ZCore;vclFireDAC;FMX_FlexCel_Core;bindcompvclsmp;emsclientfiredac;tethering;DataSnapFireDAC;FireDACADSDriver;DBXMSSQLDriver;TMSScripter;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;DBXOracleDriver;FlexCel_Report;inetdb;FmxTeeUI;emsedge;TMSScripter_Memo;fmx;FireDACIBDriver;fmxdae;VCL_FlexCel_Components;vcledge;vclib;FireDACDBXDriver;dbexpress;IndyCore;TMSVCLUIPackPkgXlsDXE13;xdata;vclx;ZParseSql;dsnap;emsclient;DataSnapCommon;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLTMSFNCCorePkgDXE13;VCLRESTComponents;soapserver;TMSScripter_Legacy;FMXTMSFNCUIPackPkgDXE13;VCLTMSFNCUIPackPkgDXE13;TMSScripter_VCL;vclie;remotedb;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;TMSVCLUIPackPkgDXE13;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;TMSVCLUIPackPkgExDXE13;IndyIPCommon;bindcompdbx;vcl;IndyIPServer;DBXSybaseASEDriver;sparkle;tmsbcl;IndySystem;FireDACDb2Driver;VCLTMSFNCMapsPkgDXE13;bindcompvclwinx;dsnapcon;VirtualTreesR;TMSWorkflow;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;ZDbc;TeeDB;FireDAC;FMXTMSFNCCorePkgDXE13;FlexCel_XlsAdapter;emshosting;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;TMSDiagram;xauth;soaprtl;DbxCommonDriver;FMXTMSFNCMapsPkgDXE13;FlexCel_Core;ibxpress;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;emsserverresource;DbxClientDriver;ibxbindings;DBXSybaseASADriver;TMSScripter_IDE;CustomIPTransport;vcldsnap;bindcomp;appanalytics;ZPlain;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;FMX_FlexCel_Components;dbxcds;VclSmp;VCL_FlexCel_Core;adortl;FireDACODBCDriver;FlexCel_Render;DataSnapIndy10ServerTransport;aurelius;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage) 73 | 74 | 75 | DEBUG;$(DCC_Define) 76 | true 77 | false 78 | true 79 | true 80 | true 81 | 82 | 83 | false 84 | true 85 | PerMonitorV2 86 | 87 | 88 | false 89 | RELEASE;$(DCC_Define) 90 | 0 91 | 0 92 | 93 | 94 | true 95 | PerMonitorV2 96 | 97 | 98 | 99 | MainSource 100 | 101 | 102 |
Form1
103 | dfm 104 |
105 | 106 | Base 107 | 108 | 109 | Cfg_1 110 | Base 111 | 112 | 113 | Cfg_2 114 | Base 115 | 116 |
117 | 118 | Delphi.Personality.12 119 | Application 120 | 121 | 122 | 123 | AWSLexSample.dpr 124 | 125 | 126 | 127 | 128 | 129 | 130 | 1 131 | 132 | 133 | Contents\MacOS 134 | 1 135 | 136 | 137 | 0 138 | 139 | 140 | 141 | 142 | classes 143 | 64 144 | 145 | 146 | classes 147 | 64 148 | 149 | 150 | 151 | 152 | res\xml 153 | 1 154 | 155 | 156 | res\xml 157 | 1 158 | 159 | 160 | 161 | 162 | library\lib\armeabi 163 | 1 164 | 165 | 166 | library\lib\armeabi 167 | 1 168 | 169 | 170 | 171 | 172 | library\lib\armeabi-v7a 173 | 1 174 | 175 | 176 | 177 | 178 | library\lib\mips 179 | 1 180 | 181 | 182 | library\lib\mips 183 | 1 184 | 185 | 186 | 187 | 188 | library\lib\armeabi-v7a 189 | 1 190 | 191 | 192 | library\lib\arm64-v8a 193 | 1 194 | 195 | 196 | 197 | 198 | library\lib\armeabi-v7a 199 | 1 200 | 201 | 202 | 203 | 204 | res\drawable 205 | 1 206 | 207 | 208 | res\drawable 209 | 1 210 | 211 | 212 | 213 | 214 | res\drawable-anydpi-v21 215 | 1 216 | 217 | 218 | res\drawable-anydpi-v21 219 | 1 220 | 221 | 222 | 223 | 224 | res\values 225 | 1 226 | 227 | 228 | res\values 229 | 1 230 | 231 | 232 | 233 | 234 | res\values-v21 235 | 1 236 | 237 | 238 | res\values-v21 239 | 1 240 | 241 | 242 | 243 | 244 | res\values-v31 245 | 1 246 | 247 | 248 | res\values-v31 249 | 1 250 | 251 | 252 | 253 | 254 | res\drawable-anydpi-v26 255 | 1 256 | 257 | 258 | res\drawable-anydpi-v26 259 | 1 260 | 261 | 262 | 263 | 264 | res\drawable 265 | 1 266 | 267 | 268 | res\drawable 269 | 1 270 | 271 | 272 | 273 | 274 | res\drawable 275 | 1 276 | 277 | 278 | res\drawable 279 | 1 280 | 281 | 282 | 283 | 284 | res\drawable 285 | 1 286 | 287 | 288 | res\drawable 289 | 1 290 | 291 | 292 | 293 | 294 | res\drawable-anydpi-v33 295 | 1 296 | 297 | 298 | res\drawable-anydpi-v33 299 | 1 300 | 301 | 302 | 303 | 304 | res\values 305 | 1 306 | 307 | 308 | res\values 309 | 1 310 | 311 | 312 | 313 | 314 | res\values-night-v21 315 | 1 316 | 317 | 318 | res\values-night-v21 319 | 1 320 | 321 | 322 | 323 | 324 | res\drawable 325 | 1 326 | 327 | 328 | res\drawable 329 | 1 330 | 331 | 332 | 333 | 334 | res\drawable-xxhdpi 335 | 1 336 | 337 | 338 | res\drawable-xxhdpi 339 | 1 340 | 341 | 342 | 343 | 344 | res\drawable-xxxhdpi 345 | 1 346 | 347 | 348 | res\drawable-xxxhdpi 349 | 1 350 | 351 | 352 | 353 | 354 | res\drawable-ldpi 355 | 1 356 | 357 | 358 | res\drawable-ldpi 359 | 1 360 | 361 | 362 | 363 | 364 | res\drawable-mdpi 365 | 1 366 | 367 | 368 | res\drawable-mdpi 369 | 1 370 | 371 | 372 | 373 | 374 | res\drawable-hdpi 375 | 1 376 | 377 | 378 | res\drawable-hdpi 379 | 1 380 | 381 | 382 | 383 | 384 | res\drawable-xhdpi 385 | 1 386 | 387 | 388 | res\drawable-xhdpi 389 | 1 390 | 391 | 392 | 393 | 394 | res\drawable-mdpi 395 | 1 396 | 397 | 398 | res\drawable-mdpi 399 | 1 400 | 401 | 402 | 403 | 404 | res\drawable-hdpi 405 | 1 406 | 407 | 408 | res\drawable-hdpi 409 | 1 410 | 411 | 412 | 413 | 414 | res\drawable-xhdpi 415 | 1 416 | 417 | 418 | res\drawable-xhdpi 419 | 1 420 | 421 | 422 | 423 | 424 | res\drawable-xxhdpi 425 | 1 426 | 427 | 428 | res\drawable-xxhdpi 429 | 1 430 | 431 | 432 | 433 | 434 | res\drawable-xxxhdpi 435 | 1 436 | 437 | 438 | res\drawable-xxxhdpi 439 | 1 440 | 441 | 442 | 443 | 444 | res\drawable-small 445 | 1 446 | 447 | 448 | res\drawable-small 449 | 1 450 | 451 | 452 | 453 | 454 | res\drawable-normal 455 | 1 456 | 457 | 458 | res\drawable-normal 459 | 1 460 | 461 | 462 | 463 | 464 | res\drawable-large 465 | 1 466 | 467 | 468 | res\drawable-large 469 | 1 470 | 471 | 472 | 473 | 474 | res\drawable-xlarge 475 | 1 476 | 477 | 478 | res\drawable-xlarge 479 | 1 480 | 481 | 482 | 483 | 484 | res\values 485 | 1 486 | 487 | 488 | res\values 489 | 1 490 | 491 | 492 | 493 | 494 | res\drawable-anydpi-v24 495 | 1 496 | 497 | 498 | res\drawable-anydpi-v24 499 | 1 500 | 501 | 502 | 503 | 504 | res\drawable 505 | 1 506 | 507 | 508 | res\drawable 509 | 1 510 | 511 | 512 | 513 | 514 | res\drawable-night-anydpi-v21 515 | 1 516 | 517 | 518 | res\drawable-night-anydpi-v21 519 | 1 520 | 521 | 522 | 523 | 524 | res\drawable-anydpi-v31 525 | 1 526 | 527 | 528 | res\drawable-anydpi-v31 529 | 1 530 | 531 | 532 | 533 | 534 | res\drawable-night-anydpi-v31 535 | 1 536 | 537 | 538 | res\drawable-night-anydpi-v31 539 | 1 540 | 541 | 542 | 543 | 544 | 1 545 | 546 | 547 | Contents\MacOS 548 | 1 549 | 550 | 551 | 0 552 | 553 | 554 | 555 | 556 | Contents\MacOS 557 | 1 558 | .framework 559 | 560 | 561 | Contents\MacOS 562 | 1 563 | .framework 564 | 565 | 566 | Contents\MacOS 567 | 1 568 | .framework 569 | 570 | 571 | 0 572 | 573 | 574 | 575 | 576 | 1 577 | .dylib 578 | 579 | 580 | 1 581 | .dylib 582 | 583 | 584 | 1 585 | .dylib 586 | 587 | 588 | Contents\MacOS 589 | 1 590 | .dylib 591 | 592 | 593 | Contents\MacOS 594 | 1 595 | .dylib 596 | 597 | 598 | Contents\MacOS 599 | 1 600 | .dylib 601 | 602 | 603 | 0 604 | .dll;.bpl 605 | 606 | 607 | 608 | 609 | 1 610 | .dylib 611 | 612 | 613 | 1 614 | .dylib 615 | 616 | 617 | 1 618 | .dylib 619 | 620 | 621 | Contents\MacOS 622 | 1 623 | .dylib 624 | 625 | 626 | Contents\MacOS 627 | 1 628 | .dylib 629 | 630 | 631 | Contents\MacOS 632 | 1 633 | .dylib 634 | 635 | 636 | 0 637 | .bpl 638 | 639 | 640 | 641 | 642 | 0 643 | 644 | 645 | 0 646 | 647 | 648 | 0 649 | 650 | 651 | 0 652 | 653 | 654 | 0 655 | 656 | 657 | Contents\Resources\StartUp\ 658 | 0 659 | 660 | 661 | Contents\Resources\StartUp\ 662 | 0 663 | 664 | 665 | Contents\Resources\StartUp\ 666 | 0 667 | 668 | 669 | 0 670 | 671 | 672 | 673 | 674 | 1 675 | 676 | 677 | 1 678 | 679 | 680 | 681 | 682 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 683 | 1 684 | 685 | 686 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 687 | 1 688 | 689 | 690 | 691 | 692 | ..\ 693 | 1 694 | 695 | 696 | ..\ 697 | 1 698 | 699 | 700 | ..\ 701 | 1 702 | 703 | 704 | 705 | 706 | Contents 707 | 1 708 | 709 | 710 | Contents 711 | 1 712 | 713 | 714 | Contents 715 | 1 716 | 717 | 718 | 719 | 720 | Contents\Resources 721 | 1 722 | 723 | 724 | Contents\Resources 725 | 1 726 | 727 | 728 | Contents\Resources 729 | 1 730 | 731 | 732 | 733 | 734 | library\lib\armeabi-v7a 735 | 1 736 | 737 | 738 | library\lib\arm64-v8a 739 | 1 740 | 741 | 742 | 1 743 | 744 | 745 | 1 746 | 747 | 748 | 1 749 | 750 | 751 | 1 752 | 753 | 754 | Contents\MacOS 755 | 1 756 | 757 | 758 | Contents\MacOS 759 | 1 760 | 761 | 762 | Contents\MacOS 763 | 1 764 | 765 | 766 | 0 767 | 768 | 769 | 770 | 771 | library\lib\armeabi-v7a 772 | 1 773 | 774 | 775 | 776 | 777 | 1 778 | 779 | 780 | 1 781 | 782 | 783 | 784 | 785 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 786 | 1 787 | 788 | 789 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 790 | 1 791 | 792 | 793 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 794 | 1 795 | 796 | 797 | 798 | 799 | ..\ 800 | 1 801 | 802 | 803 | ..\ 804 | 1 805 | 806 | 807 | ..\ 808 | 1 809 | 810 | 811 | 812 | 813 | 1 814 | 815 | 816 | 1 817 | 818 | 819 | 1 820 | 821 | 822 | 823 | 824 | ..\$(PROJECTNAME).launchscreen 825 | 64 826 | 827 | 828 | ..\$(PROJECTNAME).launchscreen 829 | 64 830 | 831 | 832 | 833 | 834 | 1 835 | 836 | 837 | 1 838 | 839 | 840 | 1 841 | 842 | 843 | 844 | 845 | Assets 846 | 1 847 | 848 | 849 | Assets 850 | 1 851 | 852 | 853 | 854 | 855 | Assets 856 | 1 857 | 858 | 859 | Assets 860 | 1 861 | 862 | 863 | 864 | 865 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 866 | 1 867 | 868 | 869 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 870 | 1 871 | 872 | 873 | 874 | 875 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 876 | 1 877 | 878 | 879 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 880 | 1 881 | 882 | 883 | 884 | 885 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 886 | 1 887 | 888 | 889 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 890 | 1 891 | 892 | 893 | 894 | 895 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 896 | 1 897 | 898 | 899 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 900 | 1 901 | 902 | 903 | 904 | 905 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 906 | 1 907 | 908 | 909 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 910 | 1 911 | 912 | 913 | 914 | 915 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 916 | 1 917 | 918 | 919 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 920 | 1 921 | 922 | 923 | 924 | 925 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 926 | 1 927 | 928 | 929 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 930 | 1 931 | 932 | 933 | 934 | 935 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 936 | 1 937 | 938 | 939 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 940 | 1 941 | 942 | 943 | 944 | 945 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 946 | 1 947 | 948 | 949 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 950 | 1 951 | 952 | 953 | 954 | 955 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 956 | 1 957 | 958 | 959 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 960 | 1 961 | 962 | 963 | 964 | 965 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 966 | 1 967 | 968 | 969 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 970 | 1 971 | 972 | 973 | 974 | 975 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 976 | 1 977 | 978 | 979 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 980 | 1 981 | 982 | 983 | 984 | 985 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 986 | 1 987 | 988 | 989 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 990 | 1 991 | 992 | 993 | 994 | 995 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 996 | 1 997 | 998 | 999 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1000 | 1 1001 | 1002 | 1003 | 1004 | 1005 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1006 | 1 1007 | 1008 | 1009 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1010 | 1 1011 | 1012 | 1013 | 1014 | 1015 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1016 | 1 1017 | 1018 | 1019 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1020 | 1 1021 | 1022 | 1023 | 1024 | 1025 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1026 | 1 1027 | 1028 | 1029 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1030 | 1 1031 | 1032 | 1033 | 1034 | 1035 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1036 | 1 1037 | 1038 | 1039 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1040 | 1 1041 | 1042 | 1043 | 1044 | 1045 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1046 | 1 1047 | 1048 | 1049 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1050 | 1 1051 | 1052 | 1053 | 1054 | 1055 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1056 | 1 1057 | 1058 | 1059 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1060 | 1 1061 | 1062 | 1063 | 1064 | 1065 | 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | 1075 | 1076 | 1077 | True 1078 | False 1079 | 1080 | 1081 | 12 1082 | 1083 | 1084 | 1085 | 1086 |
1087 | --------------------------------------------------------------------------------