Skip to content

Commit

Permalink
Merge pull request #10 from tsubakimoto/classlib
Browse files Browse the repository at this point in the history
Create shared classlib
  • Loading branch information
tsubakimoto authored Jan 14, 2024
2 parents 80d7d6d + 1488ebd commit e6709c7
Show file tree
Hide file tree
Showing 12 changed files with 338 additions and 127 deletions.
19 changes: 19 additions & 0 deletions speech-translator.sln
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ソリューション項目
README.md = README.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpeechTranslatorShared", "src\Shared\SpeechTranslatorShared.csproj", "{FF0262A4-994A-4237-88E4-1049E03E85D3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{00192D0A-A300-4EA4-A6BA-D193D73004D5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpeechTranslatorShared.Tests", "tests\Shared.Tests\SpeechTranslatorShared.Tests.csproj", "{EA08923B-519F-40CB-B219-4826FE0954F2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -26,11 +32,24 @@ Global
{CFD1A73A-09D2-46F2-8E34-0247E0D19A5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CFD1A73A-09D2-46F2-8E34-0247E0D19A5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CFD1A73A-09D2-46F2-8E34-0247E0D19A5B}.Release|Any CPU.Build.0 = Release|Any CPU
{FF0262A4-994A-4237-88E4-1049E03E85D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FF0262A4-994A-4237-88E4-1049E03E85D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FF0262A4-994A-4237-88E4-1049E03E85D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FF0262A4-994A-4237-88E4-1049E03E85D3}.Release|Any CPU.Build.0 = Release|Any CPU
{EA08923B-519F-40CB-B219-4826FE0954F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EA08923B-519F-40CB-B219-4826FE0954F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EA08923B-519F-40CB-B219-4826FE0954F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA08923B-519F-40CB-B219-4826FE0954F2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{CFD1A73A-09D2-46F2-8E34-0247E0D19A5B} = {358DED3F-4540-44E2-993E-AA7BB7E61EE6}
{FF0262A4-994A-4237-88E4-1049E03E85D3} = {358DED3F-4540-44E2-993E-AA7BB7E61EE6}
{EA08923B-519F-40CB-B219-4826FE0954F2} = {00192D0A-A300-4EA4-A6BA-D193D73004D5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2C0686D0-47ED-4A5B-A104-962D1DA98B29}
EndGlobalSection
EndGlobal
3 changes: 3 additions & 0 deletions src/Shared/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
global using Microsoft.CognitiveServices.Speech;
global using Microsoft.CognitiveServices.Speech.Audio;
global using Microsoft.CognitiveServices.Speech.Translation;
13 changes: 13 additions & 0 deletions src/Shared/SpeechTranslatorShared.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CognitiveServices.Speech" Version="1.33.0" />
</ItemGroup>

</Project>
18 changes: 18 additions & 0 deletions src/Shared/TranslationRecognizerWorkerBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace SpeechTranslatorShared;

public abstract class TranslationRecognizerWorkerBase
{
public abstract void OnRecognizing(TranslationRecognitionEventArgs e);

public abstract void OnRecognized(TranslationRecognitionEventArgs e);

public abstract void OnCanceled(TranslationRecognitionCanceledEventArgs e);

public abstract void OnSpeechStartDetected(RecognitionEventArgs e);

public abstract void OnSpeechEndDetected(RecognitionEventArgs e);

public abstract void OnSessionStarted(SessionEventArgs e);

public abstract void OnSessionStopped(SessionEventArgs e);
}
77 changes: 77 additions & 0 deletions src/Shared/Translator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
namespace SpeechTranslatorShared;

public class Translator
{
private readonly SpeechTranslationConfig _speechTranslationConfig;

public Translator(Uri endpointUrl, string subscriptionKey, string recognitionLanguage = "en-US", string targetLanguage = "ja-JP")
{
if (endpointUrl is null)
{
throw new ArgumentNullException(nameof(endpointUrl));
}

if (string.IsNullOrWhiteSpace(subscriptionKey))
{
throw new ArgumentException($"'{nameof(subscriptionKey)}' を NULL または空にすることはできません。", nameof(subscriptionKey));
}

if (string.IsNullOrWhiteSpace(recognitionLanguage))
{
throw new ArgumentException($"'{nameof(recognitionLanguage)}' を NULL または空にすることはできません。", nameof(recognitionLanguage));
}

if (string.IsNullOrWhiteSpace(targetLanguage))
{
throw new ArgumentException($"'{nameof(targetLanguage)}' を NULL または空にすることはできません。", nameof(targetLanguage));
}

_speechTranslationConfig = SpeechTranslationConfig.FromEndpoint(endpointUrl, subscriptionKey);
_speechTranslationConfig.SpeechRecognitionLanguage = recognitionLanguage;
_speechTranslationConfig.AddTargetLanguage(targetLanguage);
_speechTranslationConfig.SetProperty(PropertyId.SpeechServiceConnection_TranslationVoice, "de-DE-Hedda");
}

public async Task MultiLingualTranslation(TranslationRecognizerWorkerBase worker)
{
if (worker is null)
{
throw new ArgumentNullException(nameof(worker));
}

var autoDetectSourceLanguageConfig = AutoDetectSourceLanguageConfig.FromLanguages([_speechTranslationConfig.SpeechRecognitionLanguage]);
var stopTranslation = new TaskCompletionSource<int>();

using (var audioInput = AudioConfig.FromDefaultMicrophoneInput())
using (var recognizer = new TranslationRecognizer(_speechTranslationConfig, autoDetectSourceLanguageConfig, audioInput))
{
recognizer.Recognizing += (s, e) => worker.OnRecognizing(e);

recognizer.Recognized += (s, e) => worker.OnRecognized(e);

recognizer.Canceled += (s, e) =>
{
stopTranslation.TrySetResult(0);
worker.OnCanceled(e);
};

recognizer.SpeechStartDetected += (s, e) => worker.OnSpeechStartDetected(e);

recognizer.SpeechEndDetected += (s, e) => worker.OnSpeechEndDetected(e);

recognizer.SessionStarted += (s, e) => worker.OnSessionStarted(e);

recognizer.SessionStopped += (s, e) =>
{
stopTranslation.TrySetResult(0);
worker.OnSessionStopped(e);
};

// Starts continuous recognition. Uses StopContinuousRecognitionAsync() to stop recognition.
await recognizer.StartContinuousRecognitionAsync().ConfigureAwait(false);

Task.WaitAny(new[] { stopTranslation.Task });
await recognizer.StopContinuousRecognitionAsync().ConfigureAwait(false);
}
}
}
9 changes: 9 additions & 0 deletions src/SpeechTranslatorConsole/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
global using System.Text;

global using Microsoft.CognitiveServices.Speech;
global using Microsoft.CognitiveServices.Speech.Translation;
global using Microsoft.Extensions.Configuration;

global using SpeechTranslatorConsole;

global using SpeechTranslatorShared;
133 changes: 6 additions & 127 deletions src/SpeechTranslatorConsole/Program.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
using System.Text;
using Microsoft.CognitiveServices.Speech;
using Microsoft.CognitiveServices.Speech.Audio;
using Microsoft.CognitiveServices.Speech.Translation;
using Microsoft.Extensions.Configuration;

using SpeechTranslatorConsole;

const string directoryName = "recordings";
const string directoryName = "recordings";

var environmentName = Environment.GetEnvironmentVariable("DOTNETCORE_ENVIRONMENT") ?? "Development";

Expand All @@ -18,6 +10,7 @@

Settings? settings = config.GetRequiredSection(nameof(Settings)).Get<Settings>();
var region = settings?.Region ?? throw new ArgumentNullException("region");
var endpointUrl = new Uri($"wss://{region}.stt.speech.microsoft.com/speech/universal/v2");
var subscriptionKey = settings?.SubscriptionKey ?? throw new ArgumentNullException("subscriptionKey");
var fromLanguage = DetermineLanguage("speaker") ?? throw new ArgumentNullException("fromLanguage");
Console.WriteLine();
Expand All @@ -26,23 +19,20 @@

Console.Write("Record file name: ");
var filePath = Console.ReadLine() ?? throw new ArgumentNullException("filePath");
Console.WriteLine();

if (!Directory.Exists(directoryName))
{
Directory.CreateDirectory(directoryName);
Console.WriteLine("The directory was created successfully at {0}.", Directory.GetCreationTime(directoryName));
}

var endpointString = $"wss://{region}.stt.speech.microsoft.com/speech/universal/v2";
var endpointUrl = new Uri(endpointString);
var speechTranslationConfig = SpeechTranslationConfig.FromEndpoint(endpointUrl, subscriptionKey);
speechTranslationConfig.SpeechRecognitionLanguage = fromLanguage;
speechTranslationConfig.AddTargetLanguage(targetLanguage);
speechTranslationConfig.SetProperty(PropertyId.SpeechServiceConnection_TranslationVoice, "de-DE-Hedda");
var translator = new Translator(endpointUrl, subscriptionKey, fromLanguage, targetLanguage);
var worker = new TranslationRecognizerWorker($"{directoryName}/{filePath}.txt");

try
{
await MultiLingualTranslation($"{directoryName}/{filePath}.txt", speechTranslationConfig);
await translator.MultiLingualTranslation(worker);
}
catch (Exception e)
{
Expand All @@ -66,114 +56,3 @@
_ => null
};
}

static async Task MultiLingualTranslation(string filepath, SpeechTranslationConfig config)
{
var autoDetectSourceLanguageConfig = AutoDetectSourceLanguageConfig.FromLanguages(new string[] { config.SpeechRecognitionLanguage });

var stopTranslation = new TaskCompletionSource<int>();
using (var audioInput = AudioConfig.FromDefaultMicrophoneInput())
{
using (var recognizer = new TranslationRecognizer(config, autoDetectSourceLanguageConfig, audioInput))
{
recognizer.Recognizing += (s, e) =>
{
Console.Write(".");
//var lidResult = e.Result.Properties.GetProperty(PropertyId.SpeechServiceConnection_AutoDetectSourceLanguageResult);
//Console.WriteLine($"RECOGNIZING in '{lidResult}': Text={e.Result.Text}");
//foreach (var element in e.Result.Translations)
//{
// Console.WriteLine($" TRANSLATING into '{element.Key}': {element.Value}");
//}
};

recognizer.Recognized += (s, e) =>
{
Console.WriteLine();
Console.WriteLine();
if (e.Result.Reason == ResultReason.TranslatedSpeech)
{
var sw = new StreamWriter(filepath, true, Encoding.UTF8);
var lidResult = e.Result.Properties.GetProperty(PropertyId.SpeechServiceConnection_AutoDetectSourceLanguageResult);
// Console.WriteLine($"RECOGNIZED in '{lidResult}': Text={e.Result.Text}");
Console.WriteLine($"{e.Result.Text}");
sw.WriteLine($"{e.Result.Text}");
foreach (var element in e.Result.Translations)
{
// Console.WriteLine($" TRANSLATED into '{element.Key}': {element.Value}");
Console.WriteLine($"{element.Value}");
sw.WriteLine($"{element.Value}");
}
sw.WriteLine();
sw.Close();
}
else if (e.Result.Reason == ResultReason.RecognizedSpeech)
{
Console.WriteLine($"RECOGNIZED: Text={e.Result.Text}");
Console.WriteLine($" Speech not translated.");
}
else if (e.Result.Reason == ResultReason.NoMatch)
{
Console.WriteLine($"NOMATCH: Speech could not be recognized.");
}
Console.WriteLine();
};

recognizer.Canceled += (s, e) =>
{
Console.WriteLine($"CANCELED: Reason={e.Reason}");
if (e.Reason == CancellationReason.Error)
{
Console.WriteLine($"CANCELED: ErrorCode={e.ErrorCode}");
Console.WriteLine($"CANCELED: ErrorDetails={e.ErrorDetails}");
Console.WriteLine($"CANCELED: Did you set the speech resource key and region values?");
}
stopTranslation.TrySetResult(0);
Console.WriteLine();
};

recognizer.SpeechStartDetected += (s, e) =>
{
Console.WriteLine("\nSpeech start detected event.");
Console.WriteLine();
};

recognizer.SpeechEndDetected += (s, e) =>
{
Console.WriteLine("\nSpeech end detected event.");
Console.WriteLine();
};

recognizer.SessionStarted += (s, e) =>
{
Console.WriteLine("\nSession started event.");
Console.WriteLine();
};

recognizer.SessionStopped += (s, e) =>
{
Console.WriteLine("\nSession stopped event.");
Console.WriteLine($"\nStop translation.");
Console.WriteLine();
stopTranslation.TrySetResult(0);
};

// Starts continuous recognition. Uses StopContinuousRecognitionAsync() to stop recognition.
Console.WriteLine("Start translation...");
Console.WriteLine();
await recognizer.StartContinuousRecognitionAsync().ConfigureAwait(false);

Task.WaitAny(new[] { stopTranslation.Task });
await recognizer.StopContinuousRecognitionAsync().ConfigureAwait(false);
}
}
}
4 changes: 4 additions & 0 deletions src/SpeechTranslatorConsole/SpeechTranslatorConsole.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Shared\SpeechTranslatorShared.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
Expand Down
Loading

0 comments on commit e6709c7

Please sign in to comment.