do I advance the complexity clock and make a whole-ass language?
This commit is contained in:
adam 2024-07-23 18:42:50 -04:00
parent bc9d4f8119
commit ba86337756
4 changed files with 216 additions and 131 deletions

2
.vscode/launch.json vendored
View File

@ -9,7 +9,7 @@
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "build",
"program": "${workspaceFolder}/bin/Debug/net8.0/placeholder-VO.dll", "program": "${workspaceFolder}/bin/Debug/net8.0/script-splitter.dll",
"args": [], "args": [],
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",
"console": "internalConsole", "console": "internalConsole",

6
.vscode/tasks.json vendored
View File

@ -7,7 +7,7 @@
"type": "process", "type": "process",
"args": [ "args": [
"build", "build",
"${workspaceFolder}/placeholder-VO.csproj", "${workspaceFolder}/script-splitter.csproj",
"/property:GenerateFullPaths=true", "/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary;ForceNoAlign" "/consoleloggerparameters:NoSummary;ForceNoAlign"
], ],
@ -19,7 +19,7 @@
"type": "process", "type": "process",
"args": [ "args": [
"publish", "publish",
"${workspaceFolder}/placeholder-VO.csproj", "${workspaceFolder}/script-splitter.csproj",
"/property:GenerateFullPaths=true", "/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary;ForceNoAlign" "/consoleloggerparameters:NoSummary;ForceNoAlign"
], ],
@ -33,7 +33,7 @@
"watch", "watch",
"run", "run",
"--project", "--project",
"${workspaceFolder}/placeholder-VO.csproj" "${workspaceFolder}/script-splitter.csproj"
], ],
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
} }

View File

@ -7,6 +7,7 @@ using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Timers; using System.Timers;
using System.Xml.Schema;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -15,104 +16,103 @@ namespace placeholdervo
public partial class Program public partial class Program
{ {
[GeneratedRegex("^[^a-zA-Z0-9'\"]")] [GeneratedRegex("^(\\[|#)")]
private static partial Regex TextLine(); private static partial Regex NonTextLine();
public static Config conf; public static Config conf;
private static string workingDir = "./"; private static string workingDir = "./";
private static ConcurrentQueue<string> scriptFragmentFiles = new ConcurrentQueue<string>(); private static ConcurrentQueue<string> scriptFragmentFiles = new ConcurrentQueue<string>();
private static ConcurrentQueue<string> titleCardLines = new ConcurrentQueue<string>();
private static CancellationToken scriptFileCancellationToken; private static CancellationToken scriptFileCancellationToken;
private static async void webcall() // private static async void webcall()
{ // {
var hc = new HttpClient(){ BaseAddress = new Uri(conf.speech_service)}; // var hc = new HttpClient(){ BaseAddress = new Uri(conf.speech_service)};
while(true) // while(true)
{ // {
while(!scriptFragmentFiles.IsEmpty) // while(!scriptFragmentFiles.IsEmpty)
{ // {
string scriptFragment; // string scriptFragment;
scriptFragmentFiles.TryDequeue(out scriptFragment); // scriptFragmentFiles.TryDequeue(out scriptFragment);
if(scriptFragment == null) continue; // if(scriptFragment == null) continue;
Console.WriteLine(scriptFragment); // Console.WriteLine(scriptFragment);
HttpContent fileStreamContent = new StreamContent(File.OpenRead(scriptFragment)); // HttpContent fileStreamContent = new StreamContent(File.OpenRead(scriptFragment));
using (var formData = new MultipartFormDataContent()) // using (var formData = new MultipartFormDataContent())
{ // {
formData.Add(fileStreamContent, "file1", "file1"); // formData.Add(fileStreamContent, "file1", "file1");
var response = await hc.PostAsync("/speak", formData); // var response = await hc.PostAsync("/speak", formData);
if (!response.IsSuccessStatusCode) // if (!response.IsSuccessStatusCode)
{ // {
Console.Error.WriteLine($"{response.StatusCode} - {response.ReasonPhrase} - {await response.Content.ReadAsStringAsync()}"); // Console.Error.WriteLine($"{response.StatusCode} - {response.ReasonPhrase} - {await response.Content.ReadAsStringAsync()}");
} // }
else // else
{ // {
var resp = string.Join(", ", JsonConvert.DeserializeObject<string[]>(await response.Content.ReadAsStringAsync())); // var resp = string.Join(", ", JsonConvert.DeserializeObject<string[]>(await response.Content.ReadAsStringAsync()));
Console.WriteLine($"success; {resp}."); // Console.WriteLine($"success; {resp}.");
if(resp != null) // if(resp != null)
{ // {
scriptFragmentVoiceFiles[resp] = scriptFragment; // scriptFragmentVoiceFiles[resp] = scriptFragment;
Console.WriteLine("Ditching script fragment file."); // Console.WriteLine("Ditching script fragment file.");
File.Delete(scriptFragment); // File.Delete(scriptFragment);
} // }
} // }
} // }
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1)); // System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
} // }
if(scriptFileCancellationToken.IsCancellationRequested && scriptFragmentFiles.IsEmpty) // if(scriptFileCancellationToken.IsCancellationRequested && scriptFragmentFiles.IsEmpty)
{ // {
return; // 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);
private static async void filePickup() // if(!scriptFragmentVoiceFiles.Remove(bareAudioFile, out string throwaway))
{ // {
while(true) // Console.WriteLine($"failed to remove {bareAudioFile}");
{ // }
while(!scriptFragmentVoiceFiles.IsEmpty) // }
{ // catch(Exception e)
var files = Directory.GetFiles(conf.sync_dropoff); // {
Console.WriteLine($"files listed: {string.Join(", ", files)}"); // Console.Error.WriteLine(e.Message);
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()}"); // System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
// Console.WriteLine($"sanity check: first value: {scriptFragmentVoiceFiles[scriptFragmentVoiceFiles.Keys.FirstOrDefault()]}"); // }
var audioFile = files.FirstOrDefault(f => scriptFragmentVoiceFiles.ContainsKey(Path.GetFileName(f))); // if(scriptFileCancellationToken.IsCancellationRequested)
if(!string.IsNullOrWhiteSpace(audioFile)) // {
{ // return;
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)) // System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
{ // }
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) public static async Task Main(string[] args)
{ {
@ -123,63 +123,145 @@ namespace placeholdervo
var scriptPath = args?.FirstOrDefault(); var scriptPath = args?.FirstOrDefault();
if(string.IsNullOrWhiteSpace(scriptPath)) if(string.IsNullOrWhiteSpace(scriptPath))
{
scriptPath = "./script.md";
if(!File.Exists(scriptPath))
{
scriptPath = "./script.txt"; scriptPath = "./script.txt";
if(!File.Exists(scriptPath))
{
Console.Error.WriteLine("no script found.");
return;
}
}
}
var scriptBasename = Path.GetFileNameWithoutExtension(scriptPath);
workingDir = Path.GetDirectoryName(scriptPath); workingDir = Path.GetDirectoryName(scriptPath);
var cancelSource = new CancellationTokenSource(); var cancelSource = new CancellationTokenSource();
scriptFileCancellationToken = cancelSource.Token; scriptFileCancellationToken = cancelSource.Token;
var apiCallThread = new Thread(new ThreadStart(webcall)); // var apiCallThread = new Thread(new ThreadStart(webcall));
apiCallThread.Start(); // apiCallThread.Start();
var fileRetrieveThread = new Thread(new ThreadStart(filePickup)); // var fileRetrieveThread = new Thread(new ThreadStart(filePickup));
fileRetrieveThread.Start(); // 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;
var lines = File.ReadAllLines(scriptPath)
.Append("\n").Append("\n");
var primaryVOLines = new List<string>();
var titlecardLines = new List<string>();
var directiveLines = new List<string>();
foreach(var l in lines) foreach(var l in lines)
{ {
if(string.IsNullOrWhiteSpace(l)) if(l.StartsWith('#'))
{ {
if(runningSavedLines.Any(line => !string.IsNullOrWhiteSpace(line))) titlecardLines.Add(l);
{
++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 if (l.StartsWith('['))
{
directiveLines.Add(l);
} }
else else
{ {
runningSavedLines.Add(l); //as opposed to Environment.NewLine, which will be running on linux, and thus \n. ms speech api cooperates more with \r\n.
l.ReplaceLineEndings("\r\n");
primaryVOLines.Add(l);
} }
} }
var scriptStripped = $"script{0.ToString($"D{lineCountMagnitude}")}.txt"; var scriptStripped = $"{scriptBasename}-primaryVO.txt";
File.WriteAllLines(scriptStripped, completeSavedLines); File.WriteAllLines(scriptStripped, primaryVOLines);
scriptFragmentFiles.Enqueue(scriptStripped); var titleLevels = new List<int>(){0};
cancelSource.Cancel(); var titleIncrementDepth = 0;
Console.WriteLine("http client \"cancelled\"."); foreach(var l in titlecardLines)
while(apiCallThread.ThreadState != System.Threading.ThreadState.Stopped)
{ {
Console.WriteLine("thread still running. waiting."); titleIncrementDepth = 1;
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5)); var thisString = l;
while(thisString.StartsWith('#'))
{
thisString = thisString.Substring(1);
if(!thisString.StartsWith('#'))
{
if(titleLevels.Count < titleIncrementDepth)
{
titleLevels = [.. titleLevels, 0];
}
titleLevels[titleIncrementDepth-1]++;
if(titleLevels.Count > titleIncrementDepth)
{
titleLevels.RemoveRange(titleIncrementDepth, titleLevels.Count - titleIncrementDepth);
}
var TitleCardText = thisString.Trim();
if(titleLevels.Count > 1)
{
TitleCardText = string.Join('.', titleLevels[1..]) + ": " + TitleCardText;
}
Console.WriteLine($"title card: {TitleCardText}");
//tc command
}
else
{
titleIncrementDepth++;
}
}
} }
Console.WriteLine($"api call thread done ({apiCallThread.ThreadState}).");
while(fileRetrieveThread.ThreadState != System.Threading.ThreadState.Stopped) foreach(var l in directiveLines)
{ {
Console.WriteLine("fileRetrieveThread still running. waiting."); var thisLine = l.Trim();
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5)); if(!thisLine.Contains(']'))
{
Console.Error.WriteLine("malformed directive line: ");
Console.WriteLine(thisLine);
continue;
} }
Console.WriteLine($"fileRetrieveThread done ({fileRetrieveThread.ThreadState}). kbai"); if (thisLine.EndsWith(']'))
{
thisLine = thisLine.Trim('[', ']');
if (Uri.TryCreate(thisLine, UriKind.Absolute, out Uri asUri)
&& (asUri.Scheme == Uri.UriSchemeHttp || asUri.Scheme == Uri.UriSchemeHttps))
{
Console.WriteLine($"uri: {asUri}. ship off to yt-dlp or project Ose");
}
else
{
//just a directive, we can't do anything here
Console.WriteLine($"mere directive: {thisLine}");
}
}
else
{
thisLine = thisLine.TrimStart('[');
var directiveName = thisLine[..thisLine.IndexOf(']')];
var parameterText = thisLine[(thisLine.IndexOf(']') + 1) ..].Trim();
if(directiveName == "note")
{
//note command
Console.WriteLine($"on screen note: {parameterText}");
}
else
{
//alt va command
Console.WriteLine($"alt VA: {parameterText}");
}
}
}
// 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");
} }
} }
} }

View File

@ -3,13 +3,16 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<RootNamespace>placeholder_VO</RootNamespace> <RootNamespace>script-splitter</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup> </ItemGroup>
</Project> </Project>