works mostly, depends on powershell speech service
This commit is contained in:
parent
d2c2da6808
commit
bc9d4f8119
2
.gitignore
vendored
2
.gitignore
vendored
@ -377,3 +377,5 @@ FodyWeavers.xsd
|
|||||||
.history/
|
.history/
|
||||||
|
|
||||||
tmp/
|
tmp/
|
||||||
|
uploadcache/*
|
||||||
|
spoken/*
|
||||||
|
7
Config.cs
Normal file
7
Config.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class Config
|
||||||
|
{
|
||||||
|
public string speech_service { get; set; } = "http://eligos.lan:5400";
|
||||||
|
public string sync_dropoff { get; set; } = "/home/adam/Sync/eligos documents/";
|
||||||
|
}
|
187
Program.cs
187
Program.cs
@ -1,24 +1,185 @@
|
|||||||
using System;
|
using System.Collections.Concurrent;
|
||||||
using franz;
|
using System.Data;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Net;
|
||||||
|
using System.Reflection.Metadata.Ecma335;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Timers;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace PlaceholderVO
|
|
||||||
|
namespace placeholdervo
|
||||||
{
|
{
|
||||||
internal class Program
|
public partial class Program
|
||||||
{
|
{
|
||||||
public static Telefranz telefranz;
|
|
||||||
|
|
||||||
static async Task Main(string[] args)
|
[GeneratedRegex("^[^a-zA-Z0-9'\"]")]
|
||||||
|
private static partial Regex TextLine();
|
||||||
|
public static Config conf;
|
||||||
|
private static string workingDir = "./";
|
||||||
|
|
||||||
|
private static ConcurrentQueue<string> scriptFragmentFiles = new ConcurrentQueue<string>();
|
||||||
|
private static CancellationToken scriptFileCancellationToken;
|
||||||
|
|
||||||
|
private static async void webcall()
|
||||||
{
|
{
|
||||||
Telefranz.Configure(name: "balaam placeholder VO", bootstrap_servers: "alloces:9092",
|
var hc = new HttpClient(){ BaseAddress = new Uri(conf.speech_service)};
|
||||||
commands: ["speak"]);
|
while(true)
|
||||||
telefranz = Telefranz.Instance;
|
{
|
||||||
|
while(!scriptFragmentFiles.IsEmpty)
|
||||||
|
{
|
||||||
|
string scriptFragment;
|
||||||
|
scriptFragmentFiles.TryDequeue(out scriptFragment);
|
||||||
|
if(scriptFragment == null) continue;
|
||||||
|
Console.WriteLine(scriptFragment);
|
||||||
|
|
||||||
await Task.Delay(1000);
|
HttpContent fileStreamContent = new StreamContent(File.OpenRead(scriptFragment));
|
||||||
telefranz.ProduceMessage(new gray_messages.global.sound_off());
|
using (var formData = new MultipartFormDataContent())
|
||||||
Console.WriteLine("Hello World!");
|
{
|
||||||
|
formData.Add(fileStreamContent, "file1", "file1");
|
||||||
|
|
||||||
await Task.Delay(-1);
|
var response = await hc.PostAsync("/speak", formData);
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine($"{response.StatusCode} - {response.ReasonPhrase} - {await response.Content.ReadAsStringAsync()}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var resp = string.Join(", ", JsonConvert.DeserializeObject<string[]>(await response.Content.ReadAsStringAsync()));
|
||||||
|
Console.WriteLine($"success; {resp}.");
|
||||||
|
if(resp != null)
|
||||||
|
{
|
||||||
|
scriptFragmentVoiceFiles[resp] = scriptFragment;
|
||||||
|
Console.WriteLine("Ditching script fragment file.");
|
||||||
|
File.Delete(scriptFragment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(scriptFileCancellationToken.IsCancellationRequested && scriptFragmentFiles.IsEmpty)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ConcurrentDictionary<string, string> scriptFragmentVoiceFiles = new ConcurrentDictionary<string, string>();
|
||||||
|
|
||||||
|
private static async void filePickup()
|
||||||
|
{
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
while(!scriptFragmentVoiceFiles.IsEmpty)
|
||||||
|
{
|
||||||
|
var files = Directory.GetFiles(conf.sync_dropoff);
|
||||||
|
Console.WriteLine($"files listed: {string.Join(", ", files)}");
|
||||||
|
Console.WriteLine($"hoping for: {string.Join(", ", scriptFragmentVoiceFiles.Keys)}");
|
||||||
|
// Console.WriteLine($"sanity check: first listed file: {Path.GetFileName(files.FirstOrDefault())}");
|
||||||
|
// Console.WriteLine($"sanity check: first key: {scriptFragmentVoiceFiles.Keys.FirstOrDefault()}");
|
||||||
|
// Console.WriteLine($"sanity check: first value: {scriptFragmentVoiceFiles[scriptFragmentVoiceFiles.Keys.FirstOrDefault()]}");
|
||||||
|
var audioFile = files.FirstOrDefault(f => scriptFragmentVoiceFiles.ContainsKey(Path.GetFileName(f)));
|
||||||
|
if(!string.IsNullOrWhiteSpace(audioFile))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"found {audioFile}");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var bareAudioFile = Path.GetFileName(audioFile);
|
||||||
|
var destFile = scriptFragmentVoiceFiles[bareAudioFile];
|
||||||
|
destFile = Path.GetFileNameWithoutExtension(destFile) + ".wav";
|
||||||
|
destFile = Path.Combine(workingDir, destFile);
|
||||||
|
File.Move(audioFile, destFile);
|
||||||
|
|
||||||
|
if(!scriptFragmentVoiceFiles.Remove(bareAudioFile, out string throwaway))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"failed to remove {bareAudioFile}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine(e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
|
||||||
|
}
|
||||||
|
if(scriptFileCancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
conf = JsonConvert.DeserializeObject<Config>(
|
||||||
|
File.ReadAllText(
|
||||||
|
AppDomain.CurrentDomain.BaseDirectory + "appsettings.json"))
|
||||||
|
?? new Config();
|
||||||
|
|
||||||
|
var scriptPath = args?.FirstOrDefault();
|
||||||
|
if(string.IsNullOrWhiteSpace(scriptPath))
|
||||||
|
scriptPath = "./script.txt";
|
||||||
|
workingDir = Path.GetDirectoryName(scriptPath);
|
||||||
|
|
||||||
|
var cancelSource = new CancellationTokenSource();
|
||||||
|
scriptFileCancellationToken = cancelSource.Token;
|
||||||
|
var apiCallThread = new Thread(new ThreadStart(webcall));
|
||||||
|
apiCallThread.Start();
|
||||||
|
var fileRetrieveThread = new Thread(new ThreadStart(filePickup));
|
||||||
|
fileRetrieveThread.Start();
|
||||||
|
|
||||||
|
var lines = File.ReadAllLines(scriptPath).Where(l => !TextLine().IsMatch(l))
|
||||||
|
.Append("\n").Append("\n"); //pad out file so my tactic for separating doesn't fall off the end of the file
|
||||||
|
var lineCountMagnitude = (int)Math.Log10(lines.Count());
|
||||||
|
|
||||||
|
var runningSavedLines = new List<string>();
|
||||||
|
var completeSavedLines = new List<string>();
|
||||||
|
var iteration = 0;
|
||||||
|
|
||||||
|
foreach(var l in lines)
|
||||||
|
{
|
||||||
|
if(string.IsNullOrWhiteSpace(l))
|
||||||
|
{
|
||||||
|
if(runningSavedLines.Any(line => !string.IsNullOrWhiteSpace(line)))
|
||||||
|
{
|
||||||
|
++iteration;
|
||||||
|
//x.ToString("D2") should format x with minimum 2 digits, padded left
|
||||||
|
var scriptFragment = $"script{iteration.ToString($"D{lineCountMagnitude}")}.txt";
|
||||||
|
File.WriteAllLines(scriptFragment, runningSavedLines);
|
||||||
|
scriptFragmentFiles.Enqueue(scriptFragment);
|
||||||
|
completeSavedLines.AddRange(runningSavedLines);
|
||||||
|
}
|
||||||
|
runningSavedLines = [];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
runningSavedLines.Add(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var scriptStripped = $"script{0.ToString($"D{lineCountMagnitude}")}.txt";
|
||||||
|
File.WriteAllLines(scriptStripped, completeSavedLines);
|
||||||
|
scriptFragmentFiles.Enqueue(scriptStripped);
|
||||||
|
cancelSource.Cancel();
|
||||||
|
Console.WriteLine("http client \"cancelled\".");
|
||||||
|
while(apiCallThread.ThreadState != System.Threading.ThreadState.Stopped)
|
||||||
|
{
|
||||||
|
Console.WriteLine("thread still running. waiting.");
|
||||||
|
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
|
||||||
|
}
|
||||||
|
Console.WriteLine($"api call thread done ({apiCallThread.ThreadState}).");
|
||||||
|
|
||||||
|
while(fileRetrieveThread.ThreadState != System.Threading.ThreadState.Stopped)
|
||||||
|
{
|
||||||
|
Console.WriteLine("fileRetrieveThread still running. waiting.");
|
||||||
|
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
|
||||||
|
}
|
||||||
|
Console.WriteLine($"fileRetrieveThread done ({fileRetrieveThread.ThreadState}). kbai");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
appsettings.json
Normal file
4
appsettings.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"speech_service": "http://eligos.lan:5400",
|
||||||
|
"sync_dropoff": "/home/adam/Sync/eligos documents/"
|
||||||
|
}
|
@ -5,11 +5,11 @@
|
|||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<RootNamespace>placeholder_VO</RootNamespace>
|
<RootNamespace>placeholder_VO</RootNamespace>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>disable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="greyn.franz" Version="2.1.0" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
Loading…
Reference in New Issue
Block a user