Skip to content

Commit

Permalink
implement api calls taskmanager(incomplete), various misc bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
lobsterchan27 committed Jun 27, 2024
1 parent 3a69381 commit 5a4c856
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 70 deletions.
4 changes: 2 additions & 2 deletions public/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import { enableAutoResize, loadSliders, getFolders, withIndicators } from './scripts/utils.js';
import * as handlers from './scripts/handlers.js';

import './scripts/TaskManager/TaskManager.js';


export const state = {
controller: null,
Expand All @@ -16,8 +18,6 @@ export const assistantToken = '\n\n### Response:\n';

export const contextFolders = [];

import './scripts/TaskManager/TaskManager.js';

//On page load
document.addEventListener('DOMContentLoaded', function () {
enableAutoResize('prompt-input');
Expand Down
3 changes: 2 additions & 1 deletion public/scripts/TaskManager/Task.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
export class Task {
constructor(youtubeId) {
this.id = null; // This will be set by TaskStore when the task is added
this.id = null;
this.youtubeId = youtubeId;
this.status = 'pending';
this.folderPath = null;
this.steps = [
{ name: 'Transcribe', status: 'pending' },
{ name: 'Download', status: 'pending' },
Expand Down
88 changes: 63 additions & 25 deletions public/scripts/TaskManager/TaskManager.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import { TaskStore } from './TaskStore.js';
import { TaskManagerUI } from './TaskManagerUI.js';
import { collectSliderSettings } from '../utils.js';
import {
transcribeUrl,
downloadVideo,
processContext,
contextTTS,
combineAudio,
generateSubs,
live2d,
} from '../api.js';

export class TaskManager extends HTMLElement {
constructor() {
Expand All @@ -18,7 +28,7 @@ export class TaskManager extends HTMLElement {
this.processQueue();
}

addTask(youtubeId) {
async addTask(youtubeId) {
const newTask = this.store.addTask(youtubeId);
if (this.activeTasks.size === 0) {
this.processQueue();
Expand All @@ -33,7 +43,7 @@ export class TaskManager extends HTMLElement {
async processQueue() {
while (true) {
const pendingTasks = this.store.getPendingTasks();

while (this.activeTasks.size < this.maxConcurrentTasks && pendingTasks.length > 0) {
const task = pendingTasks.shift();
this.activeTasks.add(task.id);
Expand All @@ -56,11 +66,21 @@ export class TaskManager extends HTMLElement {

this.store.updateTask(taskId, { status: 'running' });

for (const step of task.steps) {
const steps = [
'Transcribe',
'Download',
'Process Context',
'Generate Audio',
'Combine Audio',
'Generate Subs',
'Live2D',
];

for (const step of steps) {
try {
await this.processStep(taskId, step.name, this.getStepFunction(step.name, task.youtubeId));
await this.processStep(taskId, step);
} catch (error) {
console.error(`Error in step ${step.name}:`, error);
console.error(`Error in step ${step}:`, error);
this.store.updateTask(taskId, { status: 'failed' });
return;
}
Expand All @@ -69,34 +89,52 @@ export class TaskManager extends HTMLElement {
this.store.updateTask(taskId, { status: 'completed' });
}

async processStep(taskId, stepName, stepFunction) {
// temporary implementation
async processStep(taskId, stepName) {
this.store.updateTaskStep(taskId, stepName, 'running');
try {
await stepFunction();
const task = this.store.getTaskById(taskId);
let api_server;
switch (stepName) {
case 'Transcribe':
api_server = document.getElementById('banana-api-server').value;
const url = `https://www.youtube.com/watch?v=${task.youtubeId}`;
await transcribeUrl({ api_server, url, minimum_interval: 2 });
break;
case 'Download':
await downloadVideo({ context: task.folderPath });
break;
case 'Process Context':
settings = collectSliderSettings();
await processContext(/* add necessary args */);
break;
case 'Generate Audio':
api_server = document.getElementById('banana-api-server').value;
const context = document.getElementById('context-input').value;
const voice = 'sky';
const backend = 'tortoise';
const voicefix = false;
const vc = true;
await contextTTS({ context, voice, backend, voicefix, vc, settings: { api_server } });
break;
case 'Combine Audio':
await combineAudio({ context: task.folderPath });
break;
case 'Generate Subs':
await generateSubs({ context: task.folderPath });
break;
case 'Live2D':
await live2d({ context: task.folderPath });
break;
default:
throw new Error(`Unknown step: ${stepName}`);
}
this.store.updateTaskStep(taskId, stepName, 'completed');
} catch (error) {
this.store.updateTaskStep(taskId, stepName, 'failed');
throw error;
}
}

getStepFunction(stepName, youtubeId) {
const simulateApiCall = (duration) => new Promise((resolve) => {
setTimeout(resolve, duration);
});

const stepFunctions = {
'Transcribe': () => simulateApiCall(3000),
'Download': () => simulateApiCall(2000),
'Process Context': () => simulateApiCall(2500),
'Generate Audio': () => simulateApiCall(4000),
'Combine Audio': () => simulateApiCall(1500),
'Generate Subs': () => simulateApiCall(2000),
'Live2D': () => simulateApiCall(5000)
};

return stepFunctions[stepName];
}
}

customElements.define('task-manager', TaskManager);
3 changes: 3 additions & 0 deletions public/scripts/TaskManager/TaskStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ export class TaskStore extends EventTarget {
task.steps = task.steps.map(step =>
step.name === stepName ? { ...step, status } : step
);
if (task.isCompleted()) {
task.status = 'completed';
}
this._save();
}
}
Expand Down
53 changes: 35 additions & 18 deletions public/scripts/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,17 +115,21 @@ async function text2speech(args) {
* @param {string} args.context - The URL to transcribe.
*/
async function downloadVideo(args) {
const payload = {
context: args.context,
}
try {
const payload = {
context: args.context,
}

return fetch('/youtube/download/context', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
return fetch('/youtube/download/context', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
} catch (error) {
console.error("Failed to download video:", error);
}
}

/**
Expand Down Expand Up @@ -267,16 +271,21 @@ async function contextTTS(args) {

/**
* Combines the audio files in the specified context folder.
* @param {string} contextName - The name of the folder containing the audio files to combine.
* @param {Object} args - An object containing the arguments for combining the audio.
* @param {string} args.context - The name of the folder containing the audio files to combine.
*/
async function combineAudio(contextName) {
async function combineAudio(args) {
const payload = {
context: args.context
}

try {
const response = await fetch('/audio/generate/final', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ contextName })
body: JSON.stringify(payload)
});

const data = await response.json();
Expand All @@ -288,16 +297,20 @@ async function combineAudio(contextName) {

/**
* Generates subtitles for the audio files in the specified context folder.
* @param {string} contextName - The name of the folder containing the audio files.
* @param {Object} args - An object containing the arguments for generating subtitles.
* @param {string} args.context - The name of the folder containing the audio files.
*/
async function generateSubs(contextName) {
async function generateSubs(args) {
const payload = {
context: args.context
}
try {
const response = await fetch('/video/generate/subs', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ contextName })
body: JSON.stringify(payload)
});

const data = await response.json();
Expand All @@ -309,9 +322,13 @@ async function generateSubs(contextName) {

/**
* Generates a live2d video using the specified context.
* @param {string} contextName - The name of the folder containing the context.
* @param {Object} args - An object containing the arguments for generating the live2d video.
* @param {string} context - The name of the folder containing the context.
*/
async function live2d(contextName) {
async function live2d(args) {
const payload = {
context: args.context
}
try {
const response = await fetch('/video/live2d', {
method: 'POST',
Expand Down
26 changes: 11 additions & 15 deletions public/scripts/handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,9 @@ async function handleDownloadVideoButtonClick(event, processingIndicator, comple

const args = {}
args.context = document.getElementById('context-input').value;
try {
await downloadVideo(args);
} catch (error) {
console.error("Failed to download video:", error);
} finally {
showCompletionIndicator(processingIndicator, completionIndicator);
}

await downloadVideo(args);
showCompletionIndicator(processingIndicator, completionIndicator);
}

async function handleTranscribeUrlButtonClick(event, processingIndicator, completionIndicator) {
Expand Down Expand Up @@ -126,10 +122,10 @@ async function handleContextTTSButtonClick(event, processingIndicator, completio

const api_server = document.getElementById('banana-api-server').value;
const context = document.getElementById('context-input').value;
const voice = 'sky'
const backend = 'tortoise'
const voicefix = true
const vc = true
const voice = 'sky';
const backend = 'tortoise';
const voicefix = false;
const vc = true;

await contextTTS({ context, voice, backend, voicefix, vc, settings: { api_server } })
.finally(() => showCompletionIndicator(processingIndicator, completionIndicator));
Expand All @@ -138,16 +134,16 @@ async function handleContextTTSButtonClick(event, processingIndicator, completio
async function handleCombineAudioButtonClick(event, processingIndicator, completionIndicator) {
showProcessingIndicator(processingIndicator, completionIndicator);

const contextName = document.getElementById('context-input').value;
await combineAudio(contextName)
const context = document.getElementById('context-input').value;
await combineAudio({ context })
.finally(() => showCompletionIndicator(processingIndicator, completionIndicator));
}

async function handleGenerateSubsButtonClick(event, processingIndicator, completionIndicator) {
showProcessingIndicator(processingIndicator, completionIndicator);

const contextName = document.getElementById('context-input').value;
await generateSubs(contextName)
const context = document.getElementById('context-input').value;
await generateSubs({ context })
.finally(() => showCompletionIndicator(processingIndicator, completionIndicator));
}

Expand Down
2 changes: 1 addition & 1 deletion src/audio.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const router = express.Router();

router.post('/generate/final', jsonParser, async function (request, response) {
console.log('Silence Stitching:');
const contextName = request.body.contextName;
const contextName = request.body.context;
console.log(contextName);
const savepath = await audioSilenceStitch(contextName);
response.json({ savepath });
Expand Down
6 changes: 3 additions & 3 deletions src/banana.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ const router = express.Router();
* @param {number} segment_length - The length of each segment in seconds.
* @param {boolean} translate - Whether to translate the transcription.
* @param {boolean} get_video - Whether to download the video.
* @returns {String} The savepath of the json and corresponding storyboards.
* The json(savepath/savepath.json) uses the image as the index with array of the corresponding transcription.
* @returns {Object} The savepath of the json and corresponding storyboards.
* - folderPath: {string} The save path of the folder.
*/
router.post('/transcribe/url', jsonParser, checkRequestBody, async function (request, response) {
console.log('Transcribing URL:', request.body);
Expand Down Expand Up @@ -96,7 +96,7 @@ router.post('/transcribe/url', jsonParser, checkRequestBody, async function (req

try {
await fs.promises.writeFile(saveTo, JSON.stringify(combinedData, null, 2));
response.json({ folderPath: base_filename });
response.json({ folderPath: saveFolder });
} catch (error) {
console.error('Error:', error);
return response.status(500).send('An error occurred');
Expand Down
8 changes: 4 additions & 4 deletions src/thumbnail.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ async function loadTemplates() {
async function overlayTemplate(originalPath, templatePath, outputPath) {
try {

const client = new vision.ImageAnnotatorClient({
keyFilename: 'vision-426819-7efb56f51d64.json'
});

// Load the original image to get its dimensions
const originalImage = sharp(originalPath);
const originalMetadata = await originalImage.metadata();
Expand Down Expand Up @@ -79,6 +75,10 @@ function pickTemplate(position, mood) {

async function analyzeImageForTemplateOverlay(imagePath) {
try {
const client = new vision.ImageAnnotatorClient({
keyFilename: 'vision-426819-7efb56f51d64.json'
});

// Perform object localization
const [objectResult] = await client.objectLocalization(imagePath);
const objects = objectResult.localizedObjectAnnotations;
Expand Down
2 changes: 1 addition & 1 deletion src/video.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const { PROJECT_ROOT } = require("../settings");
const router = express.Router();

router.post('/generate/subs', jsonParser, async function (req, res) {
const { contextName } = req.body;
const contextName = req.body.context;
const contextPath = path.join("public", "context", contextName);
const jsonPath = await getJson(contextPath);
const outputPath = path.join(contextPath, `${contextName}.ass`);
Expand Down

0 comments on commit 5a4c856

Please sign in to comment.