@editframe/vite-plugin 0.5.0-beta.2 → 0.5.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{assets → lib/assets}/tasks/generateTrack.mjs +1 -1
- package/dist/{assets → lib/assets}/tasks/generateTrackFragmentIndex.mjs +1 -1
- package/dist/{editor/util → lib/av}/MP4File.mjs +50 -51
- package/dist/{vite-plugin → packages/vite-plugin}/src/vite-plugin-editframe.mjs +5 -5
- package/package.json +4 -3
- package/docker-compose.yaml +0 -17
- package/src/forbidRelativePaths.ts +0 -7
- package/src/sendTaskResult.ts +0 -65
- package/src/vite-plugin-editframe.ts +0 -95
- package/tsconfig.json +0 -15
- package/vite.config.ts +0 -41
- /package/dist/{assets → lib/assets}/Probe.mjs +0 -0
- /package/dist/{assets → lib/assets}/idempotentTask.mjs +0 -0
- /package/dist/{assets → lib/assets}/md5.mjs +0 -0
- /package/dist/{assets → lib/assets}/mp4FileWritable.mjs +0 -0
- /package/dist/{assets → lib/assets}/tasks/cacheImage.mjs +0 -0
- /package/dist/{assets → lib/assets}/tasks/findOrCreateCaptions.mjs +0 -0
- /package/dist/{util → lib/util}/execPromise.mjs +0 -0
- /package/dist/{vite-plugin → packages/vite-plugin}/src/forbidRelativePaths.mjs +0 -0
- /package/dist/{vite-plugin → packages/vite-plugin}/src/sendTaskResult.mjs +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { idempotentTask } from "../idempotentTask.mjs";
|
|
2
|
-
import { MP4File } from "../../
|
|
2
|
+
import { MP4File } from "../../av/MP4File.mjs";
|
|
3
3
|
import debug from "debug";
|
|
4
4
|
import { mp4FileWritable } from "../mp4FileWritable.mjs";
|
|
5
5
|
import { PassThrough } from "stream";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { idempotentTask } from "../idempotentTask.mjs";
|
|
2
|
-
import { MP4File } from "../../
|
|
2
|
+
import { MP4File } from "../../av/MP4File.mjs";
|
|
3
3
|
import debug from "debug";
|
|
4
4
|
import { mp4FileWritable } from "../mp4FileWritable.mjs";
|
|
5
5
|
import { basename } from "path";
|
|
@@ -82,60 +82,59 @@ class MP4File extends MP4Box.ISOFile {
|
|
|
82
82
|
if (trak.samples === void 0) {
|
|
83
83
|
throw new Error("trak.samples is undefined");
|
|
84
84
|
}
|
|
85
|
-
eachSample:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
fragTrak.segmentStream
|
|
96
|
-
);
|
|
97
|
-
} catch (error) {
|
|
98
|
-
console.log("Failed to createFragment", error);
|
|
99
|
-
}
|
|
100
|
-
if (result) {
|
|
101
|
-
fragTrak.segmentStream = result;
|
|
102
|
-
trak.nextSample++;
|
|
103
|
-
} else {
|
|
104
|
-
finishedReading = await this.waitForMoreSamples();
|
|
105
|
-
break eachSample;
|
|
106
|
-
}
|
|
107
|
-
const nextSample = trak.samples[trak.nextSample];
|
|
108
|
-
const emitSegment = (
|
|
109
|
-
// if rapAlignement is true, we emit a fragment when we have a rap sample coming up next
|
|
110
|
-
fragTrak.rapAlignement === true && nextSample?.is_sync || // if rapAlignement is false, we emit a fragment when we have the required number of samples
|
|
111
|
-
!fragTrak.rapAlignement && trak.nextSample % fragTrak.nb_samples === 0 || // // if this is the last sample, we emit the fragment
|
|
112
|
-
// finished ||
|
|
113
|
-
// if we have more samples than the number of samples requested, we emit the fragment
|
|
114
|
-
trak.nextSample >= trak.samples.length
|
|
85
|
+
eachSample: while (trak.nextSample < trak.samples.length) {
|
|
86
|
+
let result = void 0;
|
|
87
|
+
if (trak?.samples[trak.nextSample]) {
|
|
88
|
+
fragmentStartSamples[fragTrak.id] ||= trak.samples[trak.nextSample];
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
result = this.createFragment(
|
|
92
|
+
fragTrak.id,
|
|
93
|
+
trak.nextSample,
|
|
94
|
+
fragTrak.segmentStream
|
|
115
95
|
);
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.log("Failed to createFragment", error);
|
|
98
|
+
}
|
|
99
|
+
if (result) {
|
|
100
|
+
fragTrak.segmentStream = result;
|
|
101
|
+
trak.nextSample++;
|
|
102
|
+
} else {
|
|
103
|
+
finishedReading = await this.waitForMoreSamples();
|
|
104
|
+
break eachSample;
|
|
105
|
+
}
|
|
106
|
+
const nextSample = trak.samples[trak.nextSample];
|
|
107
|
+
const emitSegment = (
|
|
108
|
+
// if rapAlignement is true, we emit a fragment when we have a rap sample coming up next
|
|
109
|
+
fragTrak.rapAlignement === true && nextSample?.is_sync || // if rapAlignement is false, we emit a fragment when we have the required number of samples
|
|
110
|
+
!fragTrak.rapAlignement && trak.nextSample % fragTrak.nb_samples === 0 || // // if this is the last sample, we emit the fragment
|
|
111
|
+
// finished ||
|
|
112
|
+
// if we have more samples than the number of samples requested, we emit the fragment
|
|
113
|
+
trak.nextSample >= trak.samples.length
|
|
114
|
+
);
|
|
115
|
+
if (emitSegment) {
|
|
116
|
+
if (trak.nextSample >= trak.samples.length) {
|
|
117
|
+
trackInfo[fragTrak.id].complete = true;
|
|
137
118
|
}
|
|
119
|
+
const startSample = fragmentStartSamples[fragTrak.id];
|
|
120
|
+
const endSample = trak.samples[trak.nextSample - 1];
|
|
121
|
+
if (!startSample || !endSample) {
|
|
122
|
+
throw new Error("startSample or endSample is undefined");
|
|
123
|
+
}
|
|
124
|
+
yield {
|
|
125
|
+
track: fragTrak.id,
|
|
126
|
+
segment: trackInfo[fragTrak.id].index,
|
|
127
|
+
data: fragTrak.segmentStream.buffer,
|
|
128
|
+
complete: trackInfo[fragTrak.id].complete,
|
|
129
|
+
cts: startSample.cts,
|
|
130
|
+
dts: startSample.dts,
|
|
131
|
+
duration: endSample.dts - startSample.dts + endSample.duration
|
|
132
|
+
};
|
|
133
|
+
trackInfo[fragTrak.id].index += 1;
|
|
134
|
+
fragTrak.segmentStream = null;
|
|
135
|
+
delete fragmentStartSamples[fragTrak.id];
|
|
138
136
|
}
|
|
137
|
+
}
|
|
139
138
|
}
|
|
140
139
|
finishedReading = await this.waitForMoreSamples();
|
|
141
140
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import debug from "debug";
|
|
3
|
-
import { findOrCreateCaptions } from "
|
|
4
|
-
import { generateTrackFragmentIndex } from "
|
|
5
|
-
import { generateTrack } from "
|
|
6
|
-
import { cacheImage } from "
|
|
7
|
-
import { md5FilePath } from "
|
|
3
|
+
import { findOrCreateCaptions } from "../../../lib/assets/tasks/findOrCreateCaptions.mjs";
|
|
4
|
+
import { generateTrackFragmentIndex } from "../../../lib/assets/tasks/generateTrackFragmentIndex.mjs";
|
|
5
|
+
import { generateTrack } from "../../../lib/assets/tasks/generateTrack.mjs";
|
|
6
|
+
import { cacheImage } from "../../../lib/assets/tasks/cacheImage.mjs";
|
|
7
|
+
import { md5FilePath } from "../../../lib/assets/md5.mjs";
|
|
8
8
|
import { forbidRelativePaths } from "./forbidRelativePaths.mjs";
|
|
9
9
|
import { sendTaskResult } from "./sendTaskResult.mjs";
|
|
10
10
|
const vitePluginEditframe = (options) => {
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@editframe/vite-plugin",
|
|
3
|
-
"version": "0.5.0-beta.
|
|
3
|
+
"version": "0.5.0-beta.9",
|
|
4
4
|
"description": "Editframe vite plugin",
|
|
5
5
|
"exports": {
|
|
6
|
-
".": "./dist/vite-plugin/src/vite-plugin-editframe.mjs"
|
|
6
|
+
".": "./dist/packages/vite-plugin/src/vite-plugin-editframe.mjs"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "vite build"
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"vite": "^5.2.11"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"connect": "^3.7.0"
|
|
20
|
+
"connect": "^3.7.0",
|
|
21
|
+
"vite-tsconfig-paths": "^4.3.2"
|
|
21
22
|
}
|
|
22
23
|
}
|
package/docker-compose.yaml
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
services:
|
|
3
|
-
build-vite-plugin:
|
|
4
|
-
image: telecine-runner
|
|
5
|
-
depends_on:
|
|
6
|
-
- runner
|
|
7
|
-
working_dir: /app
|
|
8
|
-
env_file:
|
|
9
|
-
- ${PWD}/.env
|
|
10
|
-
volumes_from:
|
|
11
|
-
- runner
|
|
12
|
-
stop_grace_period: 1s
|
|
13
|
-
init: true
|
|
14
|
-
scale: 1
|
|
15
|
-
environment:
|
|
16
|
-
- SHELL=/bin/sh
|
|
17
|
-
command: npx vite build --config lib/vite-plugin/vite.config.ts lib/vite-plugin/src/vite-plugin-editframe.ts --watch
|
package/src/sendTaskResult.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { createReadStream, statSync } from "fs";
|
|
2
|
-
import type { ServerResponse } from "http";
|
|
3
|
-
|
|
4
|
-
import mime from "mime";
|
|
5
|
-
import debug from "debug";
|
|
6
|
-
import type { IncomingMessage } from "connect";
|
|
7
|
-
|
|
8
|
-
import type { TaskResult } from "@/assets/idempotentTask";
|
|
9
|
-
|
|
10
|
-
export const sendTaskResult = (
|
|
11
|
-
req: IncomingMessage,
|
|
12
|
-
res: ServerResponse<IncomingMessage>,
|
|
13
|
-
taskResult: TaskResult,
|
|
14
|
-
) => {
|
|
15
|
-
const { cachePath, md5Sum } = taskResult;
|
|
16
|
-
const filePath = cachePath;
|
|
17
|
-
const headers = {
|
|
18
|
-
etag: md5Sum,
|
|
19
|
-
};
|
|
20
|
-
const log = debug("@ef:sendfile");
|
|
21
|
-
try {
|
|
22
|
-
log(`Sending file ${filePath}`);
|
|
23
|
-
const stats = statSync(filePath);
|
|
24
|
-
|
|
25
|
-
if (req.headers.range) {
|
|
26
|
-
let [x, y] = req.headers.range.replace("bytes=", "").split("-");
|
|
27
|
-
let end = parseInt(y ?? "0", 10) || stats.size - 1;
|
|
28
|
-
let start = parseInt(x ?? "0", 10) || 0;
|
|
29
|
-
|
|
30
|
-
if (end >= stats.size) {
|
|
31
|
-
end = stats.size - 1;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (start >= stats.size) {
|
|
35
|
-
log("Range start is greater than file size");
|
|
36
|
-
res.setHeader("Content-Range", `bytes */${stats.size}`);
|
|
37
|
-
res.statusCode = 416;
|
|
38
|
-
return res.end();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
res.writeHead(206, {
|
|
42
|
-
...headers,
|
|
43
|
-
"Content-Type": mime.getType(filePath) || "text/plain",
|
|
44
|
-
"Content-Range": `bytes ${start}-${end}/${stats.size}`,
|
|
45
|
-
"Content-Length": end - start + 1,
|
|
46
|
-
"Accept-Ranges": "bytes",
|
|
47
|
-
});
|
|
48
|
-
log(`Sending ${filePath} range ${start}-${end}/${stats.size}`);
|
|
49
|
-
const readStream = createReadStream(filePath, { start, end });
|
|
50
|
-
readStream.pipe(res);
|
|
51
|
-
} else {
|
|
52
|
-
res.writeHead(200, {
|
|
53
|
-
...headers,
|
|
54
|
-
"Content-Type": mime.getType(filePath) || "text/plain",
|
|
55
|
-
"Contetn-Length": stats.size,
|
|
56
|
-
});
|
|
57
|
-
log(`Sending ${filePath}`);
|
|
58
|
-
const readStream = createReadStream(filePath);
|
|
59
|
-
readStream.pipe(res);
|
|
60
|
-
}
|
|
61
|
-
} catch (error) {
|
|
62
|
-
log("Error sending file", error);
|
|
63
|
-
console.error(error);
|
|
64
|
-
}
|
|
65
|
-
};
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
|
|
3
|
-
import { Plugin } from "vite";
|
|
4
|
-
import debug from "debug";
|
|
5
|
-
|
|
6
|
-
import { findOrCreateCaptions } from "@/assets/tasks/findOrCreateCaptions";
|
|
7
|
-
import { generateTrackFragmentIndex } from "@/assets/tasks/generateTrackFragmentIndex";
|
|
8
|
-
import { generateTrack } from "@/assets/tasks/generateTrack";
|
|
9
|
-
import { cacheImage } from "@/assets/tasks/cacheImage";
|
|
10
|
-
import { md5FilePath } from "@/assets/md5";
|
|
11
|
-
|
|
12
|
-
import { forbidRelativePaths } from "./forbidRelativePaths";
|
|
13
|
-
import { sendTaskResult } from "./sendTaskResult";
|
|
14
|
-
|
|
15
|
-
interface VitePluginEditframeOptions {
|
|
16
|
-
root: string;
|
|
17
|
-
cacheRoot: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const vitePluginEditframe = (options: VitePluginEditframeOptions) => {
|
|
21
|
-
return {
|
|
22
|
-
name: "vite-plugin-editframe",
|
|
23
|
-
|
|
24
|
-
configureServer(server) {
|
|
25
|
-
server.middlewares.use(async (req, res, next) => {
|
|
26
|
-
const log = debug("@ef:vite-plugin");
|
|
27
|
-
// Forbid relative paths in any request
|
|
28
|
-
if (req.url?.startsWith("/@ef")) {
|
|
29
|
-
forbidRelativePaths(req);
|
|
30
|
-
} else {
|
|
31
|
-
return next();
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
log(`Handling ${req.url}`);
|
|
35
|
-
|
|
36
|
-
const requestPath = req.url.replace(new RegExp("^/@ef-[^/]+/"), "");
|
|
37
|
-
const assetPath = requestPath.replace(/\?.*$/, "");
|
|
38
|
-
const absolutePath = path
|
|
39
|
-
.join(options.root, assetPath)
|
|
40
|
-
.replace("dist/", "src/");
|
|
41
|
-
|
|
42
|
-
options.cacheRoot = options.cacheRoot.replace("dist/", "src/");
|
|
43
|
-
|
|
44
|
-
const efPrefix = req.url.split("/")[1];
|
|
45
|
-
|
|
46
|
-
switch (efPrefix) {
|
|
47
|
-
case "@ef-asset": {
|
|
48
|
-
if (req.method !== "HEAD") {
|
|
49
|
-
res.writeHead(405, { Allow: "HEAD" });
|
|
50
|
-
res.end();
|
|
51
|
-
}
|
|
52
|
-
md5FilePath(absolutePath)
|
|
53
|
-
.then((md5) => {
|
|
54
|
-
res.writeHead(200, {
|
|
55
|
-
etag: md5,
|
|
56
|
-
});
|
|
57
|
-
res.end();
|
|
58
|
-
})
|
|
59
|
-
.catch(next);
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
case "@ef-track-fragment-index": {
|
|
63
|
-
log(`Serving track fragment index for ${absolutePath}`);
|
|
64
|
-
generateTrackFragmentIndex(options.cacheRoot, absolutePath)
|
|
65
|
-
.then((taskResult) => sendTaskResult(req, res, taskResult))
|
|
66
|
-
.catch(next);
|
|
67
|
-
break;
|
|
68
|
-
}
|
|
69
|
-
case "@ef-track": {
|
|
70
|
-
log(`Serving track for ${absolutePath}`);
|
|
71
|
-
generateTrack(options.cacheRoot, absolutePath, req.url)
|
|
72
|
-
.then((taskResult) => sendTaskResult(req, res, taskResult))
|
|
73
|
-
.catch(next);
|
|
74
|
-
break;
|
|
75
|
-
}
|
|
76
|
-
case "@ef-captions":
|
|
77
|
-
log(`Serving captions for ${absolutePath}`);
|
|
78
|
-
findOrCreateCaptions(options.cacheRoot, absolutePath)
|
|
79
|
-
.then((taskResult) => sendTaskResult(req, res, taskResult))
|
|
80
|
-
.catch(next);
|
|
81
|
-
break;
|
|
82
|
-
case "@ef-image":
|
|
83
|
-
log(`Serving image file ${absolutePath}`);
|
|
84
|
-
cacheImage(options.cacheRoot, absolutePath)
|
|
85
|
-
.then((taskResult) => sendTaskResult(req, res, taskResult))
|
|
86
|
-
.catch(next);
|
|
87
|
-
break;
|
|
88
|
-
default:
|
|
89
|
-
log(`Unknown asset type ${efPrefix}`);
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
},
|
|
94
|
-
} satisfies Plugin;
|
|
95
|
-
};
|
package/tsconfig.json
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "esnext",
|
|
4
|
-
"module": "ES2015",
|
|
5
|
-
"outDir": "./dist",
|
|
6
|
-
"strict": true,
|
|
7
|
-
"esModuleInterop": true,
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
"forceConsistentCasingInFileNames": true,
|
|
10
|
-
"moduleResolution": "node"
|
|
11
|
-
},
|
|
12
|
-
"include": ["src/**/*.ts"],
|
|
13
|
-
"exclude": ["node_modules"],
|
|
14
|
-
"extends": "../../tsconfig.json"
|
|
15
|
-
}
|
package/vite.config.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
import { defineConfig } from "vite";
|
|
3
|
-
import tsconfigPaths from "vite-tsconfig-paths";
|
|
4
|
-
import rollupTsConfigPaths from "rollup-plugin-tsconfig-paths";
|
|
5
|
-
|
|
6
|
-
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
7
|
-
|
|
8
|
-
export default defineConfig({
|
|
9
|
-
esbuild: {
|
|
10
|
-
target: "es2022",
|
|
11
|
-
platform: "browser",
|
|
12
|
-
include: /\.(m?[jt]s|[jt]sx)$/,
|
|
13
|
-
exclude: [],
|
|
14
|
-
},
|
|
15
|
-
plugins: [tsconfigPaths()],
|
|
16
|
-
appType: "custom",
|
|
17
|
-
root: __dirname,
|
|
18
|
-
css: {
|
|
19
|
-
postcss: __dirname,
|
|
20
|
-
},
|
|
21
|
-
build: {
|
|
22
|
-
ssr: true,
|
|
23
|
-
target: "es2022",
|
|
24
|
-
rollupOptions: {
|
|
25
|
-
treeshake: "recommended",
|
|
26
|
-
output: {
|
|
27
|
-
inlineDynamicImports: false,
|
|
28
|
-
preserveModules: true,
|
|
29
|
-
},
|
|
30
|
-
plugins: [rollupTsConfigPaths({})],
|
|
31
|
-
},
|
|
32
|
-
emptyOutDir: true,
|
|
33
|
-
outDir: path.join(__dirname, "dist/"),
|
|
34
|
-
lib: {
|
|
35
|
-
entry: path.join(__dirname, "src", "vite-plugin-editframe.ts"),
|
|
36
|
-
name: "vite-plugin-editframe",
|
|
37
|
-
fileName: "vite-plugin-editframe",
|
|
38
|
-
formats: ["es"],
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|