feat: it works 🥳
This commit is contained in:
@@ -1,6 +1,9 @@
|
|||||||
using System.Globalization;
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
using System.Resources;
|
using System.Resources;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
using FFMpegCore;
|
using FFMpegCore;
|
||||||
using FFMpegCore.Enums;
|
using FFMpegCore.Enums;
|
||||||
@@ -11,6 +14,9 @@ using NAudio.Wave;
|
|||||||
using Whisper.net;
|
using Whisper.net;
|
||||||
using Whisper.net.Ggml;
|
using Whisper.net.Ggml;
|
||||||
|
|
||||||
|
|
||||||
|
var stopwatch = new Stopwatch();
|
||||||
|
stopwatch.Start();
|
||||||
var resourceManager = new ResourceManager("StreamShorts.Console.Resources.Resources", typeof(Program).Assembly);
|
var resourceManager = new ResourceManager("StreamShorts.Console.Resources.Resources", typeof(Program).Assembly);
|
||||||
|
|
||||||
Console.WriteLine(resourceManager.GetString("WelcomeMessage", CultureInfo.CurrentCulture));
|
Console.WriteLine(resourceManager.GetString("WelcomeMessage", CultureInfo.CurrentCulture));
|
||||||
@@ -79,6 +85,8 @@ using var whisperProcessor = whisperFactory.CreateBuilder()
|
|||||||
.WithLanguage("en")
|
.WithLanguage("en")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
var completeTranscription = new StringBuilder();
|
||||||
|
|
||||||
foreach (var (i, segment) in segments.Select((s, index) => (index, s)))
|
foreach (var (i, segment) in segments.Select((s, index) => (index, s)))
|
||||||
{
|
{
|
||||||
var durationOffset = TimeSpan.FromMilliseconds(i * segmentDuration.TotalMilliseconds);
|
var durationOffset = TimeSpan.FromMilliseconds(i * segmentDuration.TotalMilliseconds);
|
||||||
@@ -91,9 +99,88 @@ foreach (var (i, segment) in segments.Select((s, index) => (index, s)))
|
|||||||
segmentTranscription.AppendLine(CultureInfo.CurrentCulture, $"[{startTime:hh\\:mm\\:ss} - {endTime:hh\\:mm\\:ss}] {result.Text}");
|
segmentTranscription.AppendLine(CultureInfo.CurrentCulture, $"[{startTime:hh\\:mm\\:ss} - {endTime:hh\\:mm\\:ss}] {result.Text}");
|
||||||
}
|
}
|
||||||
|
|
||||||
await File.AppendAllTextAsync("transcription.txt", segmentTranscription.ToString());
|
completeTranscription.Append(segmentTranscription);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 5: Send the transcription to LLM for analysis
|
// Step 5: Send the transcription to LLM for analysis
|
||||||
|
// TODO: Explore this prompt further...seems break
|
||||||
|
// when transcription is long
|
||||||
|
var prompt = $"""
|
||||||
|
You are an expert in identifying engaging segments from YouTube live stream transcriptions that are suitable for creating short videos. You will be provided with a transcription of a YouTube live stream. Your task is to analyze the transcription and identify potential segments that would make compelling short videos.
|
||||||
|
|
||||||
// Step 6: Use analysis to generate a short video
|
For each segment you identify, you should create an object with the following attributes:
|
||||||
|
|
||||||
|
title: A concise and catchy title for the short video.
|
||||||
|
description: A brief description of the short video's content.
|
||||||
|
explanation: Explain why this segment would make a good short video (e.g., it's funny, informative, controversial, etc.).
|
||||||
|
start_time: The timestamp in the format HH:MM:SS where the segment begins in the original live stream.
|
||||||
|
end_time: The timestamp in the format HH:MM:SS where the segment ends in the original live stream.
|
||||||
|
Your response must be a JSON array of these objects. The JSON array should be the only output. Do not include any introductory or explanatory text outside of the JSON array.
|
||||||
|
|
||||||
|
Here is the transcription of the YouTube live stream:
|
||||||
|
|
||||||
|
{completeTranscription}
|
||||||
|
""";
|
||||||
|
|
||||||
|
using var client = new HttpClient()
|
||||||
|
{
|
||||||
|
Timeout = TimeSpan.FromMinutes(30)
|
||||||
|
};
|
||||||
|
using var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost:11434/api/generate")
|
||||||
|
{
|
||||||
|
Content = new StringContent(
|
||||||
|
JsonSerializer.Serialize(new
|
||||||
|
{
|
||||||
|
model = "llama3.1:latest",
|
||||||
|
prompt,
|
||||||
|
stream = false
|
||||||
|
}),
|
||||||
|
Encoding.UTF8,
|
||||||
|
"application/json"
|
||||||
|
)
|
||||||
|
};
|
||||||
|
var response = await client.SendAsync(request);
|
||||||
|
var responseContent = await response.Content.ReadAsStringAsync();
|
||||||
|
var responseJson = JsonSerializer.Deserialize<LLMResponse>(responseContent);
|
||||||
|
var analysis = JsonSerializer.Deserialize<List<LLMAnalysis>>(responseJson?.Response ?? string.Empty);
|
||||||
|
|
||||||
|
if (analysis is null)
|
||||||
|
{
|
||||||
|
Console.WriteLine(resourceManager.GetString("LLMAnalysisFailed", CultureInfo.CurrentCulture));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var result in analysis)
|
||||||
|
{
|
||||||
|
var fileName = string.Concat(result.Title.Split(Path.GetInvalidFileNameChars()));
|
||||||
|
await FFMpeg.SubVideoAsync(
|
||||||
|
args[0],
|
||||||
|
$"{fileName}.mp4",
|
||||||
|
result.StartTime,
|
||||||
|
result.EndTime
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
stopwatch.Stop();
|
||||||
|
Console.WriteLine(stopwatch.Elapsed.Minutes);
|
||||||
|
|
||||||
|
// Step 6: Use analysis to generate a short video
|
||||||
|
|
||||||
|
record LLMAnalysis(
|
||||||
|
[property: JsonPropertyName("title")]
|
||||||
|
string Title,
|
||||||
|
[property: JsonPropertyName("description")]
|
||||||
|
string Description,
|
||||||
|
[property: JsonPropertyName("explanation")]
|
||||||
|
string Explanation,
|
||||||
|
[property: JsonPropertyName("start_time")]
|
||||||
|
TimeSpan StartTime,
|
||||||
|
[property: JsonPropertyName("end_time")]
|
||||||
|
TimeSpan EndTime
|
||||||
|
);
|
||||||
|
|
||||||
|
record LLMResponse(
|
||||||
|
[property: JsonPropertyName("response")]
|
||||||
|
string Response
|
||||||
|
);
|
||||||
Reference in New Issue
Block a user