-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
2,580 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<Application x:Class="Protonox.App" | ||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> | ||
<Application.Resources> | ||
|
||
</Application.Resources> | ||
</Application> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
using System; | ||
using System.Windows; | ||
using System.CommandLine; | ||
|
||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
using Protonox.Labs.Api; | ||
|
||
using Tesseract; | ||
using Protonox.CommandLine; | ||
using System.CommandLine.Builder; | ||
using System.CommandLine.Parsing; | ||
|
||
using Serilog; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace Protonox | ||
{ | ||
public sealed partial class App : Application | ||
{ | ||
public App() | ||
{ | ||
Log.Logger = new LoggerConfiguration() | ||
.MinimumLevel.Debug() | ||
.WriteTo.File("log_.txt", | ||
rollingInterval: RollingInterval.Day, | ||
rollOnFileSizeLimit: true) | ||
.CreateLogger(); | ||
|
||
Log.Logger.Information("[Startup]"); | ||
} | ||
|
||
private static void ConfigureServices(ServiceCollection services) | ||
{ | ||
ILoggerFactory loggerFactory = LoggerFactory.Create(builder => | ||
{ | ||
builder.ClearProviders().AddSerilog(); | ||
}); | ||
services.AddSingleton(loggerFactory.CreateLogger(nameof(App))); | ||
|
||
services.AddSingleton<ElevenLabs>(); | ||
|
||
services.AddSingleton<VoiceSettings>(); | ||
|
||
services.AddSingleton<TesseractEngine>(x => | ||
CreateTesseractEngine(x.GetRequiredService<TesseractCLIArgs>())); | ||
|
||
services.AddSingleton<AudioSettings>(); | ||
|
||
services.AddSingleton<Controller>(); | ||
services.AddSingleton<Window1>(); | ||
} | ||
|
||
public static TesseractEngine CreateTesseractEngine(TesseractCLIArgs args) | ||
{ | ||
Log.Logger.Information($"[Startup] Tesseract Path: `{args.Path}` | Lang: `{args.Lang}`"); | ||
return new TesseractEngine(args.Path, args.Lang, EngineMode.Default); | ||
} | ||
|
||
protected override void OnStartup(StartupEventArgs e) | ||
{ | ||
ServiceCollection services = new(); | ||
|
||
int errorCount = ProcessCLI(services, e.Args); | ||
if (errorCount > 0) | ||
{ | ||
Current.Shutdown(); | ||
return; | ||
} | ||
|
||
ConfigureServices(services); | ||
|
||
var serviceProvider = services.BuildServiceProvider(); | ||
|
||
var mainWindow = serviceProvider.GetRequiredService<Window1>(); | ||
mainWindow.Show(); | ||
} | ||
|
||
private int ProcessCLI(ServiceCollection services, string[] args) | ||
{ | ||
var apiKey = new Argument<string>("apikey", "ElevenLabs API key"); | ||
|
||
var userAgent = new Option<string>( | ||
new[] { "--userAgent", "-ua" }, | ||
() => { return null; }, "Either: 'rand' or UserAgent"); | ||
|
||
var proxy = new Option<string>( | ||
new[] { "--proxy", "-p" }, | ||
() => { return null; }, "Either: 'rand' or Proxy as format PROTOCOL://ADDRESS:PORT"); | ||
|
||
var lang = new Option<string>( | ||
new[] { "--lang", "-l" }, | ||
() => { return "eng"; }, "Tesseract Language model file name without extension."); | ||
|
||
var tessPath = new Option<string>( | ||
new[] { "--tpath", "-t" }, | ||
() => { return @".\tessdata"; }, "Tesseract Language model path."); | ||
|
||
var rootCommand = new RootCommand() { | ||
apiKey, | ||
userAgent, | ||
proxy, | ||
lang, | ||
tessPath | ||
}; | ||
|
||
rootCommand.SetHandler( | ||
ProcessArgs, | ||
apiKey, | ||
proxy, | ||
userAgent, | ||
lang, | ||
tessPath | ||
); | ||
|
||
var parser = new CommandLineBuilder(rootCommand) | ||
.UseDefaults() | ||
.Build(); | ||
|
||
var result = parser.Parse(args); | ||
|
||
if (result.Errors.Count == 0) | ||
parser.Invoke(args); | ||
|
||
foreach (var error in result.Errors) | ||
Log.Logger.Error(error.Message); | ||
|
||
return result.Errors.Count; | ||
|
||
void ProcessArgs(string apiKey, string proxy, string userAgent, string lang, string tPath) | ||
{ | ||
services.AddScoped((x) => new ElevenLabsCLIArgs | ||
{ | ||
ApiKey = apiKey, | ||
Proxy = proxy, | ||
UserAgent = userAgent | ||
}); | ||
|
||
services.AddScoped((x) => new TesseractCLIArgs | ||
{ | ||
Lang = lang, | ||
Path = tPath | ||
}); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
namespace Protonox | ||
{ | ||
public sealed class AudioSettings | ||
{ | ||
public float Volume { get; set; } | ||
public string Voice { get; set; } | ||
|
||
public float Similarity { get; set; } | ||
public float Stability { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace Protonox.CommandLine | ||
{ | ||
public sealed class ElevenLabsCLIArgs | ||
{ | ||
public required string ApiKey { get; set; } | ||
public required string UserAgent { get; set; } | ||
public required string Proxy { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Protonox.CommandLine | ||
{ | ||
public sealed class TesseractCLIArgs | ||
{ | ||
public required string Lang { get; set; } | ||
public required string Path { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
using System; | ||
using System.Drawing; | ||
using System.IO; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
using Microsoft.Extensions.Logging; | ||
|
||
using NAudio.Wave; | ||
|
||
using Protonox.Labs.Api; | ||
|
||
using Serilog.Core; | ||
|
||
using Tesseract; | ||
|
||
namespace Protonox | ||
{ | ||
public sealed class Controller | ||
{ | ||
private readonly ILogger logger; | ||
private readonly ElevenLabs labs; | ||
private readonly VoiceSettings voiceSettings; | ||
private readonly AudioSettings audioSettings; | ||
|
||
private readonly TesseractEngine ocr; | ||
|
||
public Controller(ILogger logger, ElevenLabs labs, VoiceSettings settings, | ||
AudioSettings audioSettings, TesseractEngine ocr) | ||
{ | ||
this.logger = logger; | ||
this.labs = labs; | ||
this.voiceSettings = settings; | ||
|
||
this.audioSettings = audioSettings; | ||
|
||
this.ocr = ocr; | ||
} | ||
|
||
public static void Shutdown() | ||
{ | ||
System.Windows.Application.Current.Shutdown(); | ||
} | ||
|
||
public int GenAudioHash(string text) => | ||
HashCode.Combine(audioSettings.Voice.DetHashGen(), | ||
text.DetHashGen(), | ||
voiceSettings.GetHashCode()); | ||
|
||
public string AudioOutput(string text) | ||
{ | ||
UpdateVoiceSettings(); | ||
return Path.Combine(labs.Output, | ||
GenAudioHash(text).ToString() + ElevenLabs.EXT); | ||
} | ||
|
||
public string StartOCRThread(Rectangle rect) | ||
{ | ||
string text = string.Empty; | ||
|
||
Thread thread = new(process); | ||
thread.Start(); | ||
thread.Join(); | ||
|
||
logger.LogInformation($"[OCR] {text}"); | ||
|
||
return text; | ||
void process() => text = Extract(rect); | ||
} | ||
|
||
private string Extract(Rectangle rect) | ||
{ | ||
using Bitmap bitmap = Screenshot.Get(rect.Location, rect); | ||
|
||
using var page = ocr.Process(bitmap); | ||
|
||
return page.GetText().Trim(); | ||
} | ||
|
||
public void Playback(string filePath) | ||
{ | ||
AudioFileReader reader = new(filePath) | ||
{ | ||
Volume = audioSettings.Volume | ||
}; | ||
|
||
WaveOut wavePlayer = new(); | ||
wavePlayer.Init(reader); | ||
wavePlayer.Play(); | ||
} | ||
|
||
public Task<Voices[]> GetInitVoices() | ||
{ | ||
return labs.GetInitVoices(); | ||
} | ||
|
||
public async Task<bool> PostTTS(string text) | ||
{ | ||
UpdateVoiceSettings(); | ||
|
||
Voices voice = labs.Voices[audioSettings.Voice]; | ||
|
||
return await labs.PostTTS(voice.voice_id, | ||
text, voiceSettings, GenAudioHash(text)); | ||
} | ||
|
||
public void UpdateVoiceSettings() | ||
{ | ||
voiceSettings.similarity_boost = audioSettings.Similarity; | ||
voiceSettings.stability = audioSettings.Stability; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using System.Drawing; | ||
|
||
namespace Protonox | ||
{ | ||
public static class Screenshot | ||
{ | ||
public static Bitmap Get(Point source, Rectangle targetRectangle) | ||
{ | ||
Bitmap bitmap = new(targetRectangle.Width, targetRectangle.Height); | ||
using Graphics graphics = Graphics.FromImage(bitmap); | ||
graphics.CopyFromScreen(source, Point.Empty, targetRectangle.Size); | ||
|
||
return bitmap; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
namespace Protonox | ||
{ | ||
public static class StringExtension | ||
{ | ||
public static int DetHashGen(this string text) | ||
{ | ||
unchecked | ||
{ | ||
int hash = 23; | ||
foreach (char c in text) | ||
{ | ||
hash = hash * 31 + c; | ||
} | ||
return hash; | ||
} | ||
} | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
using System; | ||
|
||
namespace Protonox.Labs.Api | ||
{ | ||
public sealed class VoicesArray | ||
{ | ||
public Voices[] voices { get; set; } | ||
} | ||
|
||
public sealed class Voices | ||
{ | ||
public string voice_id { get; set; } | ||
public string name { get; set; } | ||
public object samples { get; set; } | ||
public string category { get; set; } | ||
public Fine_Tuning fine_tuning { get; set; } | ||
public Labels labels { get; set; } | ||
public string description { get; set; } | ||
public string preview_url { get; set; } | ||
public object[] available_for_tiers { get; set; } | ||
public VoiceSettings settings { get; set; } | ||
} | ||
|
||
public sealed class Fine_Tuning | ||
{ | ||
public object model_id { get; set; } | ||
public bool is_allowed_to_fine_tune { get; set; } | ||
public bool fine_tuning_requested { get; set; } | ||
public string finetuning_state { get; set; } | ||
public object verification_attempts { get; set; } | ||
public object[] verification_failures { get; set; } | ||
public int verification_attempts_count { get; set; } | ||
public object slice_ids { get; set; } | ||
} | ||
|
||
public sealed class Labels | ||
{ | ||
} | ||
|
||
public sealed class VoiceSettings | ||
{ | ||
public float stability { get; set; } = 0.75f; | ||
public float similarity_boost { get; set; } = 0.75f; | ||
|
||
public override int GetHashCode() | ||
{ | ||
return HashCode.Combine(stability, similarity_boost); | ||
} | ||
} | ||
|
||
public sealed class TTS_Body | ||
{ | ||
public string text { get; set; } | ||
public VoiceSettings voice_settings { get; set; } | ||
} | ||
} |
Oops, something went wrong.