aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/Network.ts9
-rw-r--r--src/client/views/nodes/LoadingBox.tsx16
-rw-r--r--src/server/ApiManagers/UploadManager.ts15
-rw-r--r--src/server/DashUploadUtils.ts35
4 files changed, 48 insertions, 27 deletions
diff --git a/src/client/Network.ts b/src/client/Network.ts
index 996eb35d8..19eff3b3b 100644
--- a/src/client/Network.ts
+++ b/src/client/Network.ts
@@ -62,4 +62,13 @@ export namespace Networking {
const response = await fetch('/uploadYoutubeVideo', parameters);
return response.json();
}
+ export async function QueryYoutubeProgress(videoId: string): Promise<{ progress: string }> {
+ const parameters = {
+ method: 'POST',
+ body: JSON.stringify({ videoId }),
+ json: true,
+ };
+ const response = await fetch('/queryYoutubeProgress', parameters);
+ return response.json();
+ }
}
diff --git a/src/client/views/nodes/LoadingBox.tsx b/src/client/views/nodes/LoadingBox.tsx
index 53390328f..8c5255f80 100644
--- a/src/client/views/nodes/LoadingBox.tsx
+++ b/src/client/views/nodes/LoadingBox.tsx
@@ -1,8 +1,10 @@
+import { action, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import ReactLoading from 'react-loading';
import { Doc } from '../../../fields/Doc';
import { StrCast } from '../../../fields/Types';
+import { Networking } from '../../Network';
import { ViewBoxAnnotatableComponent } from '../DocComponent';
import { FieldView, FieldViewProps } from './FieldView';
import './LoadingBox.scss';
@@ -34,17 +36,29 @@ export class LoadingBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return FieldView.LayoutString(LoadingBox, fieldKey);
}
+ _timer: any;
+ @observable progress = '';
componentDidMount() {
if (!Doc.CurrentlyLoading?.includes(this.rootDoc)) {
this.rootDoc.loadingError = 'Upload interrupted, please try again';
+ } else {
+ const updateFunc = async () => {
+ const result = await Networking.QueryYoutubeProgress(StrCast(this.rootDoc.title));
+ runInAction(() => (this.progress = result.progress));
+ this._timer = setTimeout(updateFunc, 1000);
+ };
+ this._timer = setTimeout(updateFunc, 1000);
}
}
+ componentWillUnmount() {
+ clearTimeout(this._timer);
+ }
render() {
return (
<div className="loadingBoxContainer" style={{ background: !this.rootDoc.loadingError ? '' : 'red' }}>
<div className="textContainer">
- <p className="headerText">{StrCast(this.rootDoc.loadingError, 'Loading (can take several minutes):')}</p>
+ <p className="headerText">{StrCast(this.rootDoc.loadingError, 'Loading ' + (this.progress.replace('[download]', '') || '(can take several minutes)'))}</p>
<span className="text">{StrCast(this.rootDoc.title)}</span>
{this.rootDoc.loadingError ? null : <ReactLoading type={'spinningBubbles'} color={'blue'} height={100} width={100} />}
</div>
diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts
index 76cf36d44..fe4c475c9 100644
--- a/src/server/ApiManagers/UploadManager.ts
+++ b/src/server/ApiManagers/UploadManager.ts
@@ -108,6 +108,21 @@ export default class UploadManager extends ApiManager {
register({
method: Method.POST,
+ subscription: '/queryYoutubeProgress',
+ secureHandler: async ({ req, res }) => {
+ return new Promise<void>(async resolve => {
+ req.addListener('data', args => {
+ const payload = String.fromCharCode.apply(String, args);
+ const videoId = JSON.parse(payload).videoId;
+ _success(res, { progress: DashUploadUtils.QueryYoutubeProgress(videoId) });
+ resolve();
+ });
+ });
+ },
+ });
+
+ register({
+ method: Method.POST,
subscription: new RouteSubscriber('youtubeScreenshot'),
secureHandler: async ({ req, res }) => {
const { id, timecode } = req.body;
diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts
index 2c549cc9f..45e88d8cc 100644
--- a/src/server/DashUploadUtils.ts
+++ b/src/server/DashUploadUtils.ts
@@ -117,6 +117,12 @@ export namespace DashUploadUtils {
};
}
+ export function QueryYoutubeProgress(videoId: string) {
+ return uploadProgress.get(videoId) ?? 'failed';
+ }
+
+ let uploadProgress = new Map<string, string>();
+
export function uploadYoutube(videoId: string): Promise<Upload.FileResponse> {
return new Promise<Upload.FileResponse<Upload.FileInformation>>((res, rej) => {
console.log('Uploading YouTube video: ' + videoId);
@@ -124,6 +130,7 @@ export namespace DashUploadUtils {
const path = name.replace(/^-/, '__') + '.mp4';
const finalPath = serverPathToFile(Directory.videos, path);
if (existsSync(finalPath)) {
+ uploadProgress.set(videoId, 'computing duration');
exec(`yt-dlp -o ${finalPath} "https://www.youtube.com/watch?v=${videoId}" --get-duration`, (error: any, stdout: any, stderr: any) => {
const time = Array.from(stdout.trim().split(':')).reverse();
const duration = (time.length > 2 ? Number(time[2]) * 1000 * 60 : 0) + (time.length > 1 ? Number(time[1]) * 60 : 0) + (time.length > 0 ? Number(time[0]) : 0);
@@ -132,9 +139,7 @@ export namespace DashUploadUtils {
} else {
const ytdlp = spawn(`yt-dlp`, ['-o', path, videoId, '-f', 'mp4']);
- ytdlp.stdout.on('data', function (data: any) {
- console.log('stdout: ' + data.toString()); // bcz: somehow channel this back to the client...
- });
+ ytdlp.stdout.on('data', (data: any) => uploadProgress.set(videoId, data.toString()));
let errors = '';
ytdlp.stderr.on('data', (data: any) => (errors = data.toString()));
@@ -153,6 +158,7 @@ export namespace DashUploadUtils {
result: { name: 'failed youtube query', message: `Could not upload video. ${errors}` },
});
} else {
+ uploadProgress.set(videoId, 'computing duration');
exec(`yt-dlp-o ${path} "https://www.youtube.com/watch?v=${videoId}" --get-duration`, (error: any, stdout: any, stderr: any) => {
const time = Array.from(stdout.trim().split(':')).reverse();
const duration = (time.length > 2 ? Number(time[2]) * 1000 * 60 : 0) + (time.length > 1 ? Number(time[1]) * 60 : 0) + (time.length > 0 ? Number(time[0]) : 0);
@@ -162,29 +168,6 @@ export namespace DashUploadUtils {
});
}
});
- // exec(`yt-dlp -o ${path} "https://www.youtube.com/watch?v=${videoId}" -f "mp4"`, (error: any, stdout: any, stderr: any) => {
- // if (error) {
- // console.log(`error: Error: ${error.message}`);
- // res({
- // source: {
- // size: 0,
- // path,
- // name,
- // type: '',
- // toJSON: () => ({ name, path }),
- // },
- // result: { name: 'failed youtube query', message: `Could not upload YouTube video (${videoId}). Error: ${error.message}` },
- // });
- // } else {
- // exec(`yt-dlp-o ${path} "https://www.youtube.com/watch?v=${videoId}" --get-duration`, (error: any, stdout: any, stderr: any) => {
- // const time = Array.from(stdout.trim().split(':')).reverse();
- // const duration = (time.length > 2 ? Number(time[2]) * 1000 * 60 : 0) + (time.length > 1 ? Number(time[1]) * 60 : 0) + (time.length > 0 ? Number(time[0]) : 0);
- // const data = { size: 0, path, name, type: 'video/mp4' };
- // const file = { ...data, toJSON: () => ({ ...data, filename: data.path.replace(/.*\//, ''), mtime: duration.toString(), mime: '', toJson: () => undefined as any }) };
- // res(MoveParsedFile(file, Directory.videos));
- // });
- // }
- // });
}
});
}