m4k 0.1.1 → 0.2.0

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/README.md CHANGED
@@ -3,27 +3,41 @@
3
3
  A media conversion toolkit based on [ffmpeg](https://ffmpeg.org/) and [sharp](https://sharp.pixelplumbing.com/)/[libvips](https://github.com/libvips/libvips).
4
4
  It provides queueing and progress reporting via async iterables.
5
5
 
6
+ The API is unified for audio, images and videos.
7
+
6
8
  ## Usage
7
9
 
8
- Image optimization happens completely in memory.
10
+ ### Processing audio
11
+
12
+ ```ts
13
+ import { processAudio, ProcessedFile } from "m4k";
14
+ // input is a file path or an async iterable of Uint8Arrays or a Blob
15
+ for await (const value of processAudio(input, opts)) {
16
+ if (value instanceof ProcessedFile) {
17
+ // do something with the file
18
+ }
19
+ }
20
+ ```
21
+
22
+ ### Processing images
9
23
 
10
24
  ```ts
11
- import { optimizeImage, ConvertedFile } from "m4k";
12
- // input is a ReadableStream or Blob
13
- for await (const value of optimizeImage(input, opts)) {
14
- if (value instanceof ConvertedFile) {
25
+ import { processImage, ProcessedFile } from "m4k";
26
+ // input is a file path or an async iterable of Uint8Arrays or a Blob
27
+ for await (const value of processImage(input, opts)) {
28
+ if (value instanceof ProcessedFile) {
15
29
  // do something with the file
16
30
  }
17
31
  }
18
32
  ```
19
33
 
20
- For lower memory usage, video optimization happens with files.
34
+ ### Processing videos
21
35
 
22
36
  ```ts
23
- import { optimizeVideo, ConvertedFile } from "m4k";
24
- // input is a file path
25
- for await (const value of optimizeVideo(input, opts)) {
26
- if (value instanceof ConvertedFile) {
37
+ import { processVideo, ProcessedFile } from "m4k";
38
+ // input is a file path or an async iterable of Uint8Arrays or a Blob
39
+ for await (const value of processVideo(input, opts)) {
40
+ if (value instanceof ProcessedFile) {
27
41
  // do something with the file
28
42
  }
29
43
  }
@@ -0,0 +1,20 @@
1
+ import { type AudioOptions } from "@m4k/common";
2
+ /**
3
+ * Process a video.
4
+ * @param input - The input video. Can be a file path, a stream or a blob.
5
+ * @param opts - The options for the video processing.
6
+ * @param signal - An optional abort signal.
7
+ * @returns An iterable of the processed videos.
8
+ */
9
+ export declare function processAudio(input: string | AsyncIterable<Uint8Array> | Blob, opts: AudioOptions, { signal }?: {
10
+ signal?: AbortSignal;
11
+ }): AsyncGenerator<import("@m4k/common").ProcessedFile | {
12
+ progress: number;
13
+ } | {
14
+ position: number;
15
+ }, void, unknown> | null;
16
+ /**
17
+ * The queue for video processing.
18
+ */
19
+ export declare const audioQueue: import("tasque").Tasque;
20
+ //# sourceMappingURL=audio-processor.d.ts.map
@@ -0,0 +1,47 @@
1
+ import {} from "@m4k/common";
2
+ import { mkdir } from "node:fs/promises";
3
+ import { createQueue } from "tasque";
4
+ import { processFfmpeg } from "../util/ffmpeg-processor";
5
+ /**
6
+ * Process a video.
7
+ * @param input - The input video. Can be a file path, a stream or a blob.
8
+ * @param opts - The options for the video processing.
9
+ * @param signal - An optional abort signal.
10
+ * @returns An iterable of the processed videos.
11
+ */
12
+ export function processAudio(input, opts, { signal } = {}) {
13
+ return processFfmpeg(input, () => {
14
+ const inArgs = [];
15
+ if (opts.inputFormat)
16
+ inArgs.push("-f", opts.inputFormat);
17
+ if (opts.seek)
18
+ inArgs.push("-ss", opts.seek.toString());
19
+ if (opts.duration)
20
+ inArgs.push("-t", opts.duration.toString());
21
+ const outArgs = [];
22
+ if (opts.format)
23
+ outArgs.push("-f", opts.format);
24
+ if (opts.bitrate)
25
+ outArgs.push("-b:a", opts.bitrate.toString());
26
+ if (opts.filters)
27
+ outArgs.push("-af", opts.filters);
28
+ if (opts.complexFilters)
29
+ outArgs.push("-filter_complex", opts.complexFilters);
30
+ outArgs.push("-c:a", opts.codec ?? "copy");
31
+ return {
32
+ input: inArgs,
33
+ out: outArgs,
34
+ format: opts.format ?? "mp4",
35
+ };
36
+ }, { signal, queue: audioQueue, tmpDir });
37
+ }
38
+ /**
39
+ * The queue for video processing.
40
+ */
41
+ export const audioQueue = createQueue({
42
+ parallelize: Number(process.env.AUDIO_PARALLELIZE ?? 1),
43
+ max: Number(process.env.AUDIO_QUEUE_SIZE ?? 5),
44
+ });
45
+ const tmpDir = `${process.env.M4K_TMP_DIR ?? "/tmp/m4k"}/audio`;
46
+ await mkdir(tmpDir, { recursive: true });
47
+ //# sourceMappingURL=audio-processor.js.map
@@ -0,0 +1,22 @@
1
+ import { type ImageOptions, ProcessedFile } from "@m4k/common";
2
+ export type Format = Required<ImageOptions>["format"];
3
+ export type Fit = Required<Required<ImageOptions>["resize"]>["fit"];
4
+ /**
5
+ * Process an image.
6
+ * @param input - The input image. Can be a file path, a stream or a blob.
7
+ * @param opts - The options for the image processing.
8
+ * @param signal - An optional abort signal.
9
+ * @returns An iterable of the processed images.
10
+ */
11
+ export declare function processImage(input: string | AsyncIterable<Uint8Array> | Blob, opts: ImageOptions | ImageOptions[], { signal }?: {
12
+ signal?: AbortSignal;
13
+ }): AsyncGenerator<ProcessedFile | {
14
+ progress: number;
15
+ } | {
16
+ position: number;
17
+ }, void, unknown> | null;
18
+ /**
19
+ * The queue for image processing.
20
+ */
21
+ export declare const imageQueue: import("tasque").Tasque;
22
+ //# sourceMappingURL=image-processor.d.ts.map
@@ -1,13 +1,25 @@
1
- import { ConvertedFile } from "@m4k/types";
1
+ import { ProcessedFile } from "@m4k/common";
2
+ import { createReadStream } from "node:fs";
2
3
  import sharp from "sharp";
3
4
  import { createQueue } from "tasque";
4
- import { readableFromWeb, readableToWeb } from "../util/streams";
5
- export function optimizeImage(input, opts, signal) {
5
+ import { exhaustAsyncIterableToWritable } from "../util/streams";
6
+ /**
7
+ * Process an image.
8
+ * @param input - The input image. Can be a file path, a stream or a blob.
9
+ * @param opts - The options for the image processing.
10
+ * @param signal - An optional abort signal.
11
+ * @returns An iterable of the processed images.
12
+ */
13
+ export function processImage(input, opts, { signal } = {}) {
6
14
  const sharpInstance = sharp();
7
15
  const iterable = imageQueue.iterate(async function* () {
8
16
  opts = Array.isArray(opts) ? opts : [opts];
9
- readableFromWeb("stream" in input ? input.stream() : input).pipe(sharpInstance);
10
- const files = await Promise.all(opts.map(async ({ colorspace, crop, format = "avif", keepExif, keepIcc, keepMetadata, quality, resize, rotate, }, idx) => {
17
+ void exhaustAsyncIterableToWritable(typeof input === "string"
18
+ ? createReadStream(input)
19
+ : "stream" in input
20
+ ? input.stream()
21
+ : input, sharpInstance);
22
+ const files = opts.map(async ({ colorspace, crop, format = "avif", keepExif, keepIcc, keepMetadata, quality, resize, rotate, }, idx) => {
11
23
  let s = sharpInstance.clone();
12
24
  s = s.rotate(rotate);
13
25
  if (resize)
@@ -31,12 +43,12 @@ export function optimizeImage(input, opts, signal) {
31
43
  });
32
44
  }
33
45
  s = s.toFormat(format, { quality });
34
- return new ConvertedFile(`file${idx + 1}.${format}`, `image/${format}`, readableToWeb(s));
35
- }));
46
+ return new ProcessedFile(`file${idx + 1}.${format}`, `image/${format}`, s);
47
+ });
36
48
  let done = 0;
37
49
  yield { progress: 0 };
38
50
  for (const file of files) {
39
- yield file;
51
+ yield await file;
40
52
  done++;
41
53
  yield { progress: Math.round((done / files.length) * 100) };
42
54
  }
@@ -52,7 +64,11 @@ export function optimizeImage(input, opts, signal) {
52
64
  }
53
65
  })();
54
66
  }
67
+ /**
68
+ * The queue for image processing.
69
+ */
55
70
  export const imageQueue = createQueue({
56
71
  parallelize: Number(process.env.IMAGE_PARALLELIZE ?? 5),
57
72
  max: Number(process.env.IMAGE_QUEUE_SIZE ?? 100),
58
73
  });
74
+ //# sourceMappingURL=image-processor.js.map
package/lib/index.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export * from "@m4k/common";
2
+ export { audioQueue, processAudio } from "./audio/audio-processor";
3
+ export { imageQueue, processImage } from "./images/image-processor";
4
+ export { getExtension } from "./util/ffmpeg-processor";
5
+ export { processVideo, videoQueue } from "./videos/video-processor";
6
+ //# sourceMappingURL=index.d.ts.map
package/lib/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export * from "@m4k/common";
2
+ export { audioQueue, processAudio } from "./audio/audio-processor";
3
+ export { imageQueue, processImage } from "./images/image-processor";
4
+ export { getExtension } from "./util/ffmpeg-processor";
5
+ export { processVideo, videoQueue } from "./videos/video-processor";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,30 @@
1
+ import { ProcessedFile } from "@m4k/common";
2
+ import { type Tasque } from "tasque";
3
+ /**
4
+ * Process a video.
5
+ * @param input - The input video. Can be a file path, a stream or a blob.
6
+ * @param opts - The options for the video processing.
7
+ * @param signal - An optional abort signal.
8
+ * @returns An iterable of the processed videos.
9
+ */
10
+ export declare function processFfmpeg(input: string | AsyncIterable<Uint8Array> | Blob, buildArgs: () => {
11
+ input: string[];
12
+ out: string[];
13
+ format: string;
14
+ }, { signal, queue, tmpDir, }: {
15
+ signal?: AbortSignal;
16
+ queue: Tasque;
17
+ tmpDir: string;
18
+ }): AsyncGenerator<ProcessedFile | {
19
+ progress: number;
20
+ } | {
21
+ position: number;
22
+ }, void, unknown> | null;
23
+ /**
24
+ * Get the extension for a given format.
25
+ * May not be complete yet. Most of the time, the format will be the same as the extension.
26
+ * @param format - The format to get the extension for.
27
+ * @returns The extension for the given format.
28
+ */
29
+ export declare function getExtension(format: string): string;
30
+ //# sourceMappingURL=ffmpeg-processor.d.ts.map
@@ -1,45 +1,26 @@
1
- import { ConvertedFile } from "@m4k/types";
1
+ import { ProcessedFile } from "@m4k/common";
2
2
  import { spawn } from "node:child_process";
3
3
  import { getRandomValues } from "node:crypto";
4
- import { mkdir, rm } from "node:fs/promises";
5
- import { createQueue } from "tasque";
4
+ import { createWriteStream } from "node:fs";
5
+ import { rm } from "node:fs/promises";
6
+ import {} from "tasque";
6
7
  import { mimeTypes } from "../util/mime";
7
- export function optimizeVideo(inputPath, opts, signal) {
8
- const iterable = videoQueue.iterate(async function* () {
9
- await mkdir(tmpVideoDir, { recursive: true });
10
- const outputPath = `${tmpVideoDir}/out-${Buffer.from(getRandomValues(new Uint8Array(16))).toString("base64url")}.${getExtension(opts.format ?? "mp4")}`;
11
- const inArgs = [];
12
- if (opts.inputFormat)
13
- inArgs.push("-f", opts.inputFormat);
14
- if (opts.seek)
15
- inArgs.push("-ss", opts.seek.toString());
16
- if (opts.duration)
17
- inArgs.push("-t", opts.duration.toString());
18
- const outArgs = [];
19
- if (opts.format)
20
- outArgs.push("-f", opts.format);
21
- if (opts.audioBitrate)
22
- outArgs.push("-b:a", opts.audioBitrate.toString());
23
- if (opts.videoBitrate)
24
- outArgs.push("-b:v", opts.videoBitrate.toString());
25
- if (opts.audioFilters)
26
- outArgs.push("-af", opts.audioFilters);
27
- if (opts.videoFilters)
28
- outArgs.push("-vf", opts.videoFilters);
29
- if (opts.complexFilters)
30
- outArgs.push("-filter_complex", opts.complexFilters);
31
- if (opts.aspect)
32
- outArgs.push("-aspect", opts.aspect.toString());
33
- if (opts.pad)
34
- outArgs.push("-pad", opts.pad);
35
- if (opts.fps)
36
- outArgs.push("-r", opts.fps.toString());
37
- if (opts.size)
38
- outArgs.push("-scale", opts.size);
39
- outArgs.push("-c:v", opts.videoCodec ?? "copy");
40
- outArgs.push("-c:a", opts.audioCodec ?? "copy");
8
+ import { exhaustAsyncIterableToWritable } from "../util/streams";
9
+ /**
10
+ * Process a video.
11
+ * @param input - The input video. Can be a file path, a stream or a blob.
12
+ * @param opts - The options for the video processing.
13
+ * @param signal - An optional abort signal.
14
+ * @returns An iterable of the processed videos.
15
+ */
16
+ export function processFfmpeg(input, buildArgs, { signal, queue, tmpDir, }) {
17
+ const id = randomId();
18
+ const inputPath = typeof input === "string" ? input : createTmp(tmpDir, id, input);
19
+ const iterable = queue.iterate(async function* () {
20
+ const { input: inArgs, out: outArgs, format } = buildArgs();
21
+ const outputPath = `${tmpDir}/out-${id}.${getExtension(format)}`;
41
22
  try {
42
- const child = spawn(ffmpeg, ["-y", ...inArgs, "-i", inputPath, ...outArgs, outputPath], { stdio: ["pipe", "pipe", "pipe"], signal });
23
+ const child = spawn(ffmpeg, ["-y", ...inArgs, "-i", await inputPath, ...outArgs, outputPath], { stdio: ["pipe", "pipe", "pipe"], signal });
43
24
  const decoder = new TextDecoder();
44
25
  let metadataStr = "";
45
26
  let duration = null;
@@ -77,10 +58,13 @@ export function optimizeVideo(inputPath, opts, signal) {
77
58
  if (code !== 0) {
78
59
  throw new Error(`ffmpeg exited with code ${code}: ${errStr}`);
79
60
  }
80
- yield new ConvertedFile(outputPath, mimeTypes[opts.format ?? "mp4"]);
61
+ yield new ProcessedFile(outputPath, mimeTypes[format]);
81
62
  }
82
63
  finally {
83
64
  await rm(outputPath, { force: true });
65
+ if (typeof inputPath !== "string") {
66
+ await rm(await inputPath, { force: true });
67
+ }
84
68
  }
85
69
  }, signal);
86
70
  if (!iterable)
@@ -103,11 +87,15 @@ export function optimizeVideo(inputPath, opts, signal) {
103
87
  export function getExtension(format) {
104
88
  return extMap[format] ?? format;
105
89
  }
106
- export const videoQueue = createQueue({
107
- parallelize: Number(process.env.VIDEO_PARALLELIZE ?? 1),
108
- max: Number(process.env.VIDEO_QUEUE_SIZE ?? 5),
109
- });
110
- export const tmpVideoDir = `${process.env.TMP_DIR ?? "/tmp"}/videos`;
90
+ async function createTmp(tmpDir, id, input) {
91
+ const filePath = `${tmpDir}/in-${id}`;
92
+ const writer = createWriteStream(filePath);
93
+ await exhaustAsyncIterableToWritable("stream" in input ? input.stream() : input, writer);
94
+ return filePath;
95
+ }
96
+ function randomId() {
97
+ return Buffer.from(getRandomValues(new Uint8Array(16))).toString("base64url");
98
+ }
111
99
  function parseDuration(metadataStr) {
112
100
  const match = metadataStr.match(/Duration: (\d+:\d+:\d+\.\d+)/);
113
101
  if (!match)
@@ -122,3 +110,4 @@ const ffmpeg = process.env.FFMPEG_PATH ?? (await import("@ffmpeg-installer/ffmpe
122
110
  const extMap = {
123
111
  matroska: "mkv",
124
112
  };
113
+ //# sourceMappingURL=ffmpeg-processor.js.map
@@ -2,3 +2,4 @@
2
2
  * Mapping from file extensions to their corresponding MIME types
3
3
  */
4
4
  export declare const mimeTypes: Record<string, string>;
5
+ //# sourceMappingURL=mime.d.ts.map
@@ -49,3 +49,4 @@ export const mimeTypes = {
49
49
  aiff: "audio/aiff",
50
50
  alac: "audio/alac",
51
51
  };
52
+ //# sourceMappingURL=mime.js.map
@@ -0,0 +1,3 @@
1
+ import type { Writable } from "stream";
2
+ export declare function exhaustAsyncIterableToWritable(it: AsyncIterable<Uint8Array>, writable: Writable): Promise<void>;
3
+ //# sourceMappingURL=streams.d.ts.map
@@ -0,0 +1,9 @@
1
+ export async function exhaustAsyncIterableToWritable(it, writable) {
2
+ for await (const chunk of it) {
3
+ if (!writable.write(chunk))
4
+ await new Promise((resolve) => writable.once("drain", resolve));
5
+ }
6
+ writable.end();
7
+ await new Promise((resolve) => writable.on("finish", resolve));
8
+ }
9
+ //# sourceMappingURL=streams.js.map
@@ -0,0 +1,20 @@
1
+ import { type VideoOptions } from "@m4k/common";
2
+ /**
3
+ * Process a video.
4
+ * @param input - The input video. Can be a file path, a stream or a blob.
5
+ * @param opts - The options for the video processing.
6
+ * @param signal - An optional abort signal.
7
+ * @returns An iterable of the processed videos.
8
+ */
9
+ export declare function processVideo(input: string | AsyncIterable<Uint8Array> | Blob, opts: VideoOptions, { signal }?: {
10
+ signal?: AbortSignal;
11
+ }): AsyncGenerator<import("@m4k/common").ProcessedFile | {
12
+ progress: number;
13
+ } | {
14
+ position: number;
15
+ }, void, unknown> | null;
16
+ /**
17
+ * The queue for video processing.
18
+ */
19
+ export declare const videoQueue: import("tasque").Tasque;
20
+ //# sourceMappingURL=video-processor.d.ts.map
@@ -0,0 +1,60 @@
1
+ import {} from "@m4k/common";
2
+ import { mkdir } from "node:fs/promises";
3
+ import { createQueue } from "tasque";
4
+ import { processFfmpeg } from "../util/ffmpeg-processor";
5
+ /**
6
+ * Process a video.
7
+ * @param input - The input video. Can be a file path, a stream or a blob.
8
+ * @param opts - The options for the video processing.
9
+ * @param signal - An optional abort signal.
10
+ * @returns An iterable of the processed videos.
11
+ */
12
+ export function processVideo(input, opts, { signal } = {}) {
13
+ return processFfmpeg(input, () => {
14
+ const inArgs = [];
15
+ if (opts.inputFormat)
16
+ inArgs.push("-f", opts.inputFormat);
17
+ if (opts.seek)
18
+ inArgs.push("-ss", opts.seek.toString());
19
+ if (opts.duration)
20
+ inArgs.push("-t", opts.duration.toString());
21
+ const outArgs = [];
22
+ if (opts.format)
23
+ outArgs.push("-f", opts.format);
24
+ if (opts.audioBitrate)
25
+ outArgs.push("-b:a", opts.audioBitrate.toString());
26
+ if (opts.videoBitrate)
27
+ outArgs.push("-b:v", opts.videoBitrate.toString());
28
+ if (opts.audioFilters)
29
+ outArgs.push("-af", opts.audioFilters);
30
+ if (opts.videoFilters)
31
+ outArgs.push("-vf", opts.videoFilters);
32
+ if (opts.complexFilters)
33
+ outArgs.push("-filter_complex", opts.complexFilters);
34
+ if (opts.aspect)
35
+ outArgs.push("-aspect", opts.aspect.toString());
36
+ if (opts.pad)
37
+ outArgs.push("-pad", opts.pad);
38
+ if (opts.fps)
39
+ outArgs.push("-r", opts.fps.toString());
40
+ if (opts.size)
41
+ outArgs.push("-scale", opts.size);
42
+ outArgs.push("-c:v", opts.videoCodec ?? "copy");
43
+ outArgs.push("-c:a", opts.audioCodec ?? "copy");
44
+ return {
45
+ input: inArgs,
46
+ out: outArgs,
47
+ format: opts.format ?? "mp4",
48
+ };
49
+ }, { signal, queue: videoQueue, tmpDir });
50
+ }
51
+ /**
52
+ * The queue for video processing.
53
+ */
54
+ export const videoQueue = createQueue({
55
+ parallelize: Number(process.env.VIDEO_PARALLELIZE ?? 1),
56
+ max: Number(process.env.VIDEO_QUEUE_SIZE ?? 5),
57
+ });
58
+ const tmpDir = `${process.env.M4K_TMP_DIR ?? "/tmp/m4k"}/video`;
59
+ await mkdir(tmpDir, { recursive: true });
60
+ //# sourceMappingURL=video-processor.js.map
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "m4k",
3
- "module": "./dist/index.js",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
- "version": "0.1.1",
6
- "main": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
5
+ "main": "./lib/index.js",
6
+ "types": "./lib/index.d.ts",
7
+ "module": "./lib/index.js",
8
+ "license": "MIT",
8
9
  "scripts": {
9
- "prepublishOnly": "bun tsc",
10
- "build": "tsc",
10
+ "prepublishOnly": "bun run build",
11
+ "build": "tsc -b",
11
12
  "typecheck": "tsc --noEmit",
12
13
  "test": "bun test"
13
14
  },
@@ -16,6 +17,9 @@
16
17
  "tasque": "^0.1.2",
17
18
  "typescript": "^5.0.0"
18
19
  },
20
+ "dependencies": {
21
+ "@m4k/common": "^0.1.0"
22
+ },
19
23
  "peerDependencies": {
20
24
  "sharp": "^0.33.5"
21
25
  },
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Sven
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1,9 +0,0 @@
1
- import { type ImageOptimizerOptions, ConvertedFile } from "@m4k/types";
2
- export type Format = Required<ImageOptimizerOptions>["format"];
3
- export type Fit = Required<Required<ImageOptimizerOptions>["resize"]>["fit"];
4
- export declare function optimizeImage(input: ReadableStream | Blob, opts: ImageOptimizerOptions | ImageOptimizerOptions[], signal?: AbortSignal): AsyncGenerator<ConvertedFile | {
5
- progress: number;
6
- } | {
7
- position: number;
8
- }, void, unknown> | null;
9
- export declare const imageQueue: import("tasque").Tasque;
package/dist/index.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export { ConvertedFile } from "@m4k/types";
2
- export { imageQueue, optimizeImage } from "./images/image-optimizer";
3
- export { getExtension, optimizeVideo, tmpVideoDir, videoQueue, } from "./videos/video-optimizer";
package/dist/index.js DELETED
@@ -1,3 +0,0 @@
1
- export { ConvertedFile } from "@m4k/types";
2
- export { imageQueue, optimizeImage } from "./images/image-optimizer";
3
- export { getExtension, optimizeVideo, tmpVideoDir, videoQueue, } from "./videos/video-optimizer";
@@ -1,3 +0,0 @@
1
- import { Readable } from "node:stream";
2
- export declare function readableFromWeb(stream: ReadableStream): Readable;
3
- export declare function readableToWeb(stream: Readable): ReadableStream & AsyncIterable<Uint8Array>;
@@ -1,8 +0,0 @@
1
- import { Readable } from "node:stream";
2
- export function readableFromWeb(stream) {
3
- // Currently node types don't match with TS lib types for ReadableStream, so we need to cast to any.
4
- return Readable.fromWeb(stream);
5
- }
6
- export function readableToWeb(stream) {
7
- return Readable.toWeb(stream);
8
- }
@@ -1,15 +0,0 @@
1
- import { ConvertedFile, type VideoOptimizerOptions } from "@m4k/types";
2
- export declare function optimizeVideo(inputPath: string, opts: VideoOptimizerOptions, signal?: AbortSignal): AsyncGenerator<ConvertedFile | {
3
- progress: number;
4
- } | {
5
- position: number;
6
- }, void, unknown> | null;
7
- /**
8
- * Get the extension for a given format.
9
- * May not be complete yet. Most of the time, the format will be the same as the extension.
10
- * @param format - The format to get the extension for.
11
- * @returns The extension for the given format.
12
- */
13
- export declare function getExtension(format: string): string;
14
- export declare const videoQueue: import("tasque").Tasque;
15
- export declare const tmpVideoDir: string;