Skip to content

Commit 3dfffbf

Browse files
Fixed video size issue and now read the file directly from the file system
1 parent c6dbd81 commit 3dfffbf

File tree

7 files changed

+119
-32
lines changed

7 files changed

+119
-32
lines changed

src/main/main.ts

Lines changed: 70 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*/
1111
import path from 'path';
1212
import fs from 'fs';
13-
import { app, BrowserWindow, dialog, shell, ipcMain } from 'electron';
13+
import { app, BrowserWindow, dialog, shell, ipcMain, protocol } from 'electron';
1414
import { autoUpdater } from 'electron-updater';
1515
import log from 'electron-log';
1616
import MenuBuilder from './menu';
@@ -43,7 +43,8 @@ const HOME: string =
4343
const CONFIG_FILE: string = `${HOME}/.dub-editor-config.json`;
4444
const COLLECTIONS_FILE: string = `${HOME}/.dub-editor-collections.json`;
4545
const BATCH_CACHE_FILE: string = `${HOME}/.dub-editor-batch-cache.json`;
46-
const BATCH_VIDEO_TEMP_FILE: string = `${HOME}/dub-editor-tmp.mp4`;
46+
const BATCH_VIDEO_TEMP_FILE: string = `${HOME}/dub-editor-batch-tmp.mp4`;
47+
const CLIP_VIDEO_TEMP_FILE: string = `${HOME}/dub-editor-clip-tmp.mp4`;
4748

4849
export default class AppUpdater {
4950
constructor() {
@@ -556,9 +557,48 @@ const createWindow = async () => {
556557
return { action: 'deny' };
557558
});
558559

559-
// Remove this if your app does not use auto updates
560-
// eslint-disable-next-line
561-
new AppUpdater();
560+
protocol.interceptFileProtocol('app', (request, callback) => {
561+
let url = request.url.substring(6);
562+
let pattern = /^(rifftrax|whatthedub)\/(.+)\.(mp4|srt)$/;
563+
564+
if (url === "batch.tmp.mp4") {
565+
return callback(BATCH_VIDEO_TEMP_FILE);
566+
} else if (url === "clip.tmp.mp4") {
567+
return callback(CLIP_VIDEO_TEMP_FILE);
568+
}
569+
570+
let match : any = url.match(pattern);
571+
572+
if (!match) {
573+
return null;
574+
}
575+
576+
let game = match[1];
577+
let id = match[2];
578+
let ext = match[3];
579+
580+
let directory = null;
581+
if (game === 'rifftrax') {
582+
directory = config.rifftraxDirectory;
583+
} else if (game === 'whatthedub') {
584+
directory = config.whatTheDubDirectory;
585+
}
586+
587+
let subdirectory;
588+
if (ext === 'mp4') {
589+
subdirectory = 'VideoClips';
590+
} else if (ext = 'srt') {
591+
subdirectory = 'Subtitles';
592+
} else {
593+
subdirectory = 'VideoClips';
594+
}
595+
596+
const assetDirectory: string =
597+
`${directory}/StreamingAssets/${subdirectory}`.replace('~', HOME);
598+
const filePath: string = `${assetDirectory}/${id}.${ext}`;
599+
600+
callback(filePath);
601+
});
562602
};
563603

564604
/**
@@ -630,24 +670,13 @@ ipcMain.handle('storeBatch', async (event, { clips, video, title }) => {
630670
title,
631671
clipNumber: 1,
632672
clips,
633-
video,
634673
};
635674

636675
// Write cache file
637676
fs.writeFileSync(
638677
BATCH_CACHE_FILE,
639678
Buffer.from(JSON.stringify(batchCache, null, 5))
640679
);
641-
642-
// Write temporary video file
643-
let videoByteStream : any = batchCache.video;
644-
videoByteStream = videoByteStream.substring(videoByteStream.indexOf(','));
645-
let buffer = Buffer.from(videoByteStream, "base64");
646-
try {
647-
await fs.writeFileSync(BATCH_VIDEO_TEMP_FILE, buffer);
648-
} catch (err) {
649-
throw new Error("Unable to trim video: " + err);
650-
}
651680
});
652681

653682
ipcMain.handle('hasBatch', (event) => {
@@ -830,6 +859,31 @@ ipcMain.handle(
830859
}
831860
);
832861

862+
ipcMain.handle(
863+
'storeTempVideo',
864+
(event, {videoArrayBuffer, type}) => {
865+
console.log(
866+
`STORING TEMP CLIP VIDEO`
867+
);
868+
869+
if (type === "clip") {
870+
fs.writeFileSync(
871+
CLIP_VIDEO_TEMP_FILE,
872+
Buffer.from(videoArrayBuffer)
873+
);
874+
return `app://clip.tmp.mp4`;
875+
} else if (type === "batch") {
876+
fs.writeFileSync(
877+
BATCH_VIDEO_TEMP_FILE,
878+
Buffer.from(videoArrayBuffer)
879+
);
880+
return `app://batch.tmp.mp4`;
881+
}
882+
883+
return null;
884+
}
885+
);
886+
833887
ipcMain.handle('deleteVideo', (event, { id, game }) => {
834888
deleteClip(id, game);
835889
});

src/main/preload.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ contextBridge.exposeInMainWorld('api', {
1919
'getVideos',
2020
'getVideo',
2121
'storeVideo',
22+
'storeTempVideo',
2223
'deleteVideo',
2324
'disableVideos',
2425
'createCollection',

src/renderer/api/VideoAPI.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const storeTempVideo = async (videoArrayBuffer, type) => {
2+
return await window.api.send('storeTempVideo', {videoArrayBuffer , type});
3+
};
4+
5+
export default {
6+
storeTempVideo
7+
};

src/renderer/routes/VideoView.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ let VideoView = (props) => {
2727
<div>Name: {videoDetails.name}</div>
2828
<div>
2929
<WhatTheDubPlayer
30-
videoSource={videoDetails.videoUrl}
30+
videoSource={`app://${params.game}/${params.id}.mp4`}
3131
isPlaying={false}
3232
videoPosition={0}
3333
subs={convertSrtToSubtitles(videoDetails.srtBase64)}

src/renderer/routes/editor/AdvancedEditor.jsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import BatchAPI from 'renderer/api/BatchAPI';
1414
import { useAtom } from 'jotai';
1515
import { interstitialAtom } from 'renderer/atoms/interstitial.atom';
1616
import { handleInterstitial } from 'renderer/components/interstitial/Interstitial';
17+
import VideoAPI from 'renderer/api/VideoAPI';
1718

1819
let AdvancedEditor = () => {
1920
const [searchParams] = useSearchParams();
@@ -76,7 +77,7 @@ let AdvancedEditor = () => {
7677
}
7778
);
7879
let { clip, video, title, clipNumber } = batchClip;
79-
setVideoSource(video);
80+
setVideoSource("app://batch.tmp.mp4");
8081
setVideoLength((clip.endTime - clip.startTime) / 1000);
8182
setBatchClip(batchClip);
8283
setStartTime(clip.startTime);
@@ -89,11 +90,20 @@ let AdvancedEditor = () => {
8990
let onFileOpen = (e) => {
9091
let f = e.target.files[0];
9192
let fr = new FileReader();
92-
fr.onload = () => {
93-
setVideoSource(fr.result);
94-
};
93+
handleInterstitial(
94+
new Promise((resolve, reject) => {
95+
fr.onload = async () => {
96+
let url = await VideoAPI.storeTempVideo(fr.result, "clip");
97+
console.log("URL: " + url);
98+
setVideoSource(url);
99+
resolve();
100+
};
101+
}),
102+
(isOpen) => {
103+
setInterstitialState({ isOpen, message: 'Loading Video...' });
104+
})
95105

96-
fr.readAsDataURL(f);
106+
fr.readAsArrayBuffer(f);
97107
};
98108

99109
let convertSecondsToTimestamp = (seconds) => {
@@ -245,10 +255,10 @@ let AdvancedEditor = () => {
245255
<WhatTheDubPlayer
246256
videoSource={videoSource}
247257
isPlaying={
248-
isPlaying &&
258+
isPlaying && (!batchClip ||
249259
currentSliderPosition >=
250260
batchClip.clip.startTime &&
251-
currentSliderPosition <= batchClip.clip.endTime
261+
currentSliderPosition <= batchClip.clip.endTime)
252262
}
253263
videoPosition={currentPosition}
254264
subs={subs}
@@ -263,7 +273,6 @@ let AdvancedEditor = () => {
263273
onVideoPositionChange={(position) => {
264274
setCurrentSliderPosition(position * 1000);
265275
}}
266-
onIndexChange={setCurrentSub}
267276
onVideoLoaded={(video) => {
268277
if (!isBatch) {
269278
setEndTime(video.duration * 1000);

src/renderer/routes/editor/ClipCutter.jsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import ClipList from 'renderer/components/ClipList';
1616
import { interstitialAtom } from 'renderer/atoms/interstitial.atom';
1717
import { handleInterstitial } from 'renderer/components/interstitial/Interstitial';
1818
import { useAtom } from 'jotai';
19+
import VideoAPI from 'renderer/api/VideoAPI';
1920

2021
let ClipCutter = () => {
2122
const params = useParams();
@@ -58,8 +59,9 @@ let ClipCutter = () => {
5859

5960
handleInterstitial(
6061
new Promise((resolve, reject) => {
61-
fr.onload = () => {
62-
setVideoSource(fr.result);
62+
fr.onload = async () => {
63+
let url = await VideoAPI.storeTempVideo(fr.result, "batch");
64+
setVideoSource(url);
6365
resolve();
6466
};
6567
}),
@@ -68,7 +70,7 @@ let ClipCutter = () => {
6870
}
6971
);
7072

71-
fr.readAsDataURL(f);
73+
fr.readAsArrayBuffer(f);
7274
};
7375

7476
let convertSecondsToTimestamp = (seconds) => {

src/renderer/routes/editor/SimpleEditor.jsx

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@ import { addVideo } from '../../util/VideoTools';
55
import { useParams, useNavigate } from 'react-router';
66
import { Link } from 'react-router-dom';
77
import CollectionAPI from '../../api/CollectionAPI';
8+
import VideoAPI from 'renderer/api/VideoAPI';
9+
import { useAtom } from 'jotai';
10+
import { interstitialAtom } from 'renderer/atoms/interstitial.atom';
11+
import { handleInterstitial } from 'renderer/components/interstitial/Interstitial';
812

913
let SimpleEditor = () => {
1014
const params = useParams();
1115
const navigate = useNavigate();
1216

17+
const [, setInterstitialState] = useAtom(interstitialAtom);
18+
1319
const [error, setError] = useState(null);
1420
const [clipNumber, setClipNumber] = useState(1);
1521
const [videoSource, setVideoSource] = useState('');
@@ -81,11 +87,19 @@ let SimpleEditor = () => {
8187
let onFileOpen = (e) => {
8288
let f = e.target.files[0];
8389
let fr = new FileReader();
84-
fr.onload = () => {
85-
setVideoSource(fr.result);
86-
};
90+
handleInterstitial(
91+
new Promise((resolve, reject) => {
92+
fr.onload = async () => {
93+
let url = await VideoAPI.storeTempVideo(fr.result, "clip");
94+
setVideoSource(url);
95+
resolve();
96+
};
97+
}),
98+
(isOpen) => {setInterstitialState({isOpen, message: "Loading video..."})}
99+
);
100+
87101

88-
fr.readAsDataURL(f);
102+
fr.readAsArrayBuffer(f);
89103
};
90104

91105
let convertSecondsToTimestamp = (seconds) => {

0 commit comments

Comments
 (0)