Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify-api #27

Merged
merged 6 commits into from
Mar 23, 2025
Merged

Unify-api #27

merged 6 commits into from
Mar 23, 2025

Conversation

sv2dev
Copy link
Owner

@sv2dev sv2dev commented Mar 23, 2025

  • Add a separate API for processing audio
  • Unify API to accept both binary data and a file path

Summary by CodeRabbit

  • New Features

    • Expanded media processing capabilities to support audio alongside image and video processing with enhanced progress updates.
    • Introduced a new audio processing API endpoint.
    • Improved service configuration with a renamed container service and enhanced volume management.
  • Documentation

    • Updated usage guides for running the server and client, including revised Docker commands and image version details.
    • Streamlined API documentation to reflect the unified approach to media processing.
    • Enhanced documentation for server deployment and client usage, including new instructions for local package installation.

Copy link

coderabbitai bot commented Mar 23, 2025

Walkthrough

The changes update multiple modules to standardize file processing across audio, image, and video types. The .gitignore now ignores package output directories, while documentation and Docker configurations have been revised. In the client and core modules, functions formerly named “optimize” have been renamed to “process,” and the type “ConvertedFile” has been replaced by “ProcessedFile.” New type definitions (e.g., AudioOptions) and functions (e.g., processAudio) have been introduced with corresponding tests and exports. Server routes have been extended with an audio processing endpoint and updated handler logic.

Changes

Files Group Change Summary
.gitignore Added new entry packages/*/output to ignore output directories in package subdirectories.
Documentation
(Root README.md, packages/client/README.md, packages/core/README.md, packages/server/README.md)
Updated instructions and usage examples, replacing “API” sections with guidance on running the server, using new client packages (@m4k/server and @m4k/client), updating Docker image versions, and adding documentation for the new audio API endpoint (POST /audio/process).
Docker Configuration
(docker-compose.yaml)
Renamed service from video-optimizer to m4k and added a volume mapping ./output:/output.
Client Module Changes
(packages/client/src/client.ts, client.spec.ts, index.ts, test-client.ts, test.ts)
Replaced functions optimizeImage/optimizeVideo with new functions processAudio, processImage, and processVideo. Changed type ConvertedFile to ProcessedFile and updated tests to validate new processing flows.
Common Module Changes
(packages/common/src/index.ts)
Renamed types ImageOptimizerOptionsImageOptions and VideoOptimizerOptionsVideoOptions, added new type AudioOptions, and renamed ConvertedFile to ProcessedFile.
Core Module Changes
(packages/core/src/audio/, packages/core/src/images/, packages/core/src/videos/*, util files)
Removed the old image-optimizer.ts and introduced image-processor.ts; added new processAudio in audio-processor.ts with corresponding tests; updated video processing (processVideo, processFfmpeg) and stream handling (exhaustAsyncIterableToWritable), with adjustments for new types and queue management.
Server Module Changes
(packages/server/src/audio/, packages/server/src/images/, packages/server/src/videos/, util/, server.ts, file.ts)
Introduced a new audio processing handler (process-audio-handler.ts with tests) and added the /audio/process route. Updated image and video handlers to use processImage/processVideo and ProcessedFile. Removed the VirtualFile class and revised response logic to align with the new file processing types.

Sequence Diagram(s)

sequenceDiagram
    participant C as Client
    participant S as Server
    participant PA as processAudioHandler
    participant PAud as processAudio (Core)

    C->>S: POST /audio/process with audio file & options
    S->>PA: Route request to processAudioHandler
    PA->>PAud: Validate options and invoke processAudio
    PAud-->>PA: Yield processed audio chunks
    PA->>S: Stream processed results or write output file
    S-->>C: Return multipart/mixed response with ProcessedFile(s)
Loading
sequenceDiagram
    participant App as Application
    participant C as @m4k/client
    participant S as M4K Server

    App->>C: Call processAudio/processImage/processVideo with file and options
    C->>S: Send processing request (via HTTP or Bun)
    S-->>C: Return streaming response with ProcessedFile(s)
    C-->>App: Provide processed output and progress updates
Loading

Poem

I'm a rabbit, hopping through the code,
New functions bloom and lighten our load.
Audio, image, video—each step is bright,
Processed files dance in digital light.
With every commit, our burrow feels so grand,
Cheery lines of code—crafted by my paw and hand! 🐰✨

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

🧹 Nitpick comments (23)
packages/core/src/videos/video-processor.ts (1)

56-58: Consider handling potential filesystem errors.

The mkdir operation could fail due to permission issues or other I/O errors. Since this is using a top-level await, an unhandled rejection could occur.

-await mkdir(tmpDir, { recursive: true });
+try {
+  await mkdir(tmpDir, { recursive: true });
+} catch (error) {
+  console.error(`Failed to create temporary directory ${tmpDir}:`, error);
+  // Consider fallback or graceful handling
+}
packages/client/src/index.ts (1)

1-1: Remove unnecessary renaming in export.

The export statement contains a useless rename that should be simplified.

-export { ProcessedFile as ProcessedFile } from "@m4k/common";
+export { ProcessedFile } from "@m4k/common";
🧰 Tools
🪛 Biome (1.9.4)

[error] 1-1: Useless rename.

Safe fix: Remove the renaming.

(lint/complexity/noUselessRename)

test.ts (2)

3-7: Consider verifying .name before using non-null assertion.
When calling processVideo(Bun.file("fixtures/video.mp4").name!, ...), you assume .name is never null or undefined. To prevent potential runtime errors, consider a safer fallback approach:

- for await (const value of processVideo(Bun.file("fixtures/video.mp4").name!, {
+ const fileRef = Bun.file("fixtures/video.mp4");
+ for await (const value of processVideo(fileRef.name ?? "video.mp4", {
    format: "mp4",
    videoCodec: "libx265",
    output: "test.mp4",
})!) {

11-26: Add error handling for file reading.
If the file at "fixtures/image.jpeg" doesn’t exist or cannot be read, the code could fail without a clear error path. A simple try/catch or a check before calling processImage can improve resilience.

packages/server/src/audio/process-audio-handler.spec.ts (3)

24-28: Rename variable to reflect audio processing context.
Currently, videoInfo references audio metadata. Consider renaming it to audioInfo or a more generic name like mediaInfo to avoid confusion.

- const videoInfo = collected.find((x) => "type" in x)!;
+ const audioInfo = collected.find((x) => "type" in x)!;

30-60: Test name references “videos” instead of “audio.”
The test “should process multiple videos in sequence” might be copying from a video scenario. Since it tests audio with “.ogg” output, rename for clarity and consistency:

- it("should process multiple videos in sequence", async () => {
+ it("should process multiple audio files in sequence", async () => {

157-157: Remove the unnecessary continue statement.
The linter flags this as superfluous. You can safely drop it without changing the logic:

-       continue; // keepalive
+       // keepalive
🧰 Tools
🪛 Biome (1.9.4)

[error] 157-157: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)

packages/core/src/images/image-processor.ts (1)

17-91: Consider handling stream errors inside the queue task.
Wrapping exhaustAsyncIterableToWritable calls in try/catch helps ensure errors from reading or writing streams (e.g., file not found, insufficient permissions) are surfaced. This will improve the reliability of the image processing queue.

+   try {
       ...
     );
     // ... existing code ...
+   } catch (err) {
+     yield { error: (err as Error).message };
+   }
   }, signal);
packages/core/src/audio/audio-processor.spec.ts (1)

58-58: Remove trailing space in test description

There's an extra space at the end of the test description.

-  it("should enqueue processing multiple audio files ", async () => {
+  it("should enqueue processing multiple audio files", async () => {
packages/server/src/util/response.ts (2)

1-1: Update import to use @m4k/common namespace

For consistency with other files in the codebase, consider updating the import to use the @m4k/common namespace instead of just m4k.

-import { ProcessedFile } from "m4k";
+import { ProcessedFile } from "@m4k/common";

18-19: Avoid using {} as a type

The type {} is discouraged as it actually means "any non-nullable value" rather than "empty object" as commonly assumed. Consider using a more specific type or unknown for better type safety.

-  iterable: AsyncIterable<{} | ProcessedFile | Blob>
+  iterable: AsyncIterable<unknown | ProcessedFile | Blob>
🧰 Tools
🪛 Biome (1.9.4)

[error] 19-19: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

packages/server/README.md (1)

19-25: Add language specifiers to fenced code blocks

Add language specifiers to the fenced code blocks to improve syntax highlighting and readability in the documentation.

-```
+```http
 URL: /audio/process?<Options|options=OptionsJSON[]>
 Method: POST
 Headers:
 - [X-Options: <OptionsJSON[]>]
 Body: Binary file

```diff
-```
+```http
 Status: 200 OK
 Headers:
 - Content-Type: multipart/mixed; boundary=<boundary>
 Body: multipart/mixed body with status updates and the processed files (if no output option was provided)


Also applies to: 29-34

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

19-19: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

</details>

</details>

</blockquote></details>
<details>
<summary>packages/core/src/audio/audio-processor.ts (3)</summary><blockquote>

`6-12`: **Fix JSDoc comment**

The JSDoc comment incorrectly states this function processes a video, but it should refer to audio processing.

```diff
 /**
- * Process a video.
+ * Process an audio file.
  * @param input - The input video. Can be a file path, a stream or a blob.
  * @param opts - The options for the video processing.
  * @param signal - An optional abort signal.
- * @returns An iterable of the processed videos.
+ * @returns An iterable of the processed audio.
  */

35-35: Consider using a more appropriate default format for audio

The default format is set to "mp4", which is primarily a video container format. Consider using a more appropriate default audio format like "mp3" or "aac".

-        format: opts.format ?? "mp4",
+        format: opts.format ?? "mp3",

42-45: Update JSDoc comment

The JSDoc comment incorrectly refers to video processing for the audio queue.

 /**
- * The queue for video processing.
+ * The queue for audio processing.
  */
packages/server/src/audio/process-audio-handler.ts (2)

9-21: Clarify the usage of the options field in the schema.
Currently, options is defined as an optional string field. If you expect more structured data, consider requiring JSON or specifying constraints for this field. This will improve readability and reduce parsing ambiguity.


40-59: Enhance streaming flow with robust cleanup.
While streaming or writing output files, consider using a try/finally block or similar approach to ensure partial or interrupted operations are handled cleanly. This prevents orphaned temp files if the request is abruptly closed.

packages/client/README.md (2)

8-25: Include an advanced example for audio processing options.
Showcasing usage of advanced fields like bitrate, codec, or filters would help users configure audio processing more effectively.


27-44: Add clarity on the structure of opts for image processing.
It may be beneficial to provide a short example demonstrating a minimal opts object, illustrating how to specify fields like format or filters.

packages/server/src/videos/process-video-handler.ts (1)

31-31: Consider consolidating output and name into the schema.
Currently, optsArr extends VideoOptions with output and name. Including them in the validation schema (as optional fields) could make it clearer and reduce ad-hoc property extensions.

packages/core/src/util/ffmpeg-processor.ts (1)

10-16: Doc comment mismatch.
The JSDoc references @param opts, but the actual signature has buildArgs plus { signal, queue, tmpDir }. Consider aligning the doc comment with the new parameter names to avoid confusion.

 /**
- * @param opts - The options for video processing.
+ * @param buildArgs - Function returning input/output ffmpeg args and format.
+ * @param param1 - Destructured object containing signal, queue, and tmpDir.
  */
packages/client/src/client.ts (2)

75-79: Consider renaming optimizeFetch to processFetch for consistency.

Since all other functions have been renamed from "optimize" to "process", it would be more consistent to rename this internal function as well.

-async function* optimizeFetch<T>(
+async function* processFetch<T>(
  url: string,
  input: AsyncIterable<Uint8Array> | Blob,
  opts: any
)

And update the function calls in the processing functions:

-yield* optimizeFetch<Progress | QueuePosition | ProcessingError>(
+yield* processFetch<Progress | QueuePosition | ProcessingError>(

88-90: Update error message to reflect the new naming.

The error message still references "optimize" instead of "process".

-      `Failed to optimize: [${res.statusText}] ${await res.text()}`
+      `Failed to process: [${res.statusText}] ${await res.text()}`
🛑 Comments failed to post (2)
packages/server/src/videos/process-video-handler.ts (1)

47-60: 🛠️ Refactor suggestion

Add a more robust error handling path for output file writing.
If an error occurs while writing the output file or removing the temporary file, it may leave partial files or lock resources. Protect these operations within a try/finally block or add error handling logic to ensure proper cleanup.

packages/client/src/client.spec.ts (1)

60-82: ⚠️ Potential issue

Pipeline failure due to size mismatch.
Your test expects 1055836 bytes, but the pipeline reports 1055796. Container metadata or slight encoding differences can cause minor deviations.

Consider a more tolerant check:

-    expect(files).toEqual([
-      { name: "video.mp4", type: "video/mp4", size: 1055836 },
-    ]);
+    expect(files).toHaveLength(1);
+    expect(files[0].name).toBe("video.mp4");
+    expect(files[0].type).toBe("video/mp4");
+    // Allow a slight variation in file size
+    expect(Math.abs(files[0].size - 1055836)).toBeLessThanOrEqual(512);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

describe("processVideo()", () => {
  it("should query the server to process a video", async () => {
    const video = Bun.file("../../fixtures/video.mp4");
    const files: { name: string; type: string; size: number }[] = [];

    for await (const x of processVideo("http://localhost:3000", video, [
      { format: "mp4", name: "video.mp4" },
    ])) {
      if (x instanceof ProcessedFile) {
        const chunks = await Array.fromAsync(x.stream);
        files.push({
          name: x.name,
          type: x.type,
          size: chunks.reduce((sum, chunk) => sum + chunk.length, 0),
        });
      }
    }

    expect(files).toHaveLength(1);
    expect(files[0].name).toBe("video.mp4");
    expect(files[0].type).toBe("video/mp4");
    // Allow a slight variation in file size
    expect(Math.abs(files[0].size - 1055836)).toBeLessThanOrEqual(512);
  });
});
🧰 Tools
🪛 GitHub Actions: Test and Build

[error] 78-78: Test failed: expect(received).toEqual(expected) - Expected size to be 1055836 but received 1055796.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (10)
packages/client/src/index.ts (1)

1-1: Remove redundant type alias.

The current export statement includes a useless rename. This can be simplified.

-export { ProcessedFile as ProcessedFile } from "@m4k/common";
+export { ProcessedFile } from "@m4k/common";
🧰 Tools
🪛 Biome (1.9.4)

[error] 1-1: Useless rename.

Safe fix: Remove the renaming.

(lint/complexity/noUselessRename)

packages/server/src/audio/process-audio-handler.spec.ts (5)

30-30: Fix typo in test description.

The test description refers to processing "multiple videos" but should refer to "multiple audio files" to match the actual test content.

-  it("should process multiple videos in sequence", async () => {
+  it("should process multiple audio files in sequence", async () => {

53-54: Variable naming inconsistency.

The variable is named video1 but it's referring to an audio file. This should be renamed for clarity.

-    const video1 = coll1.find((x) => "type" in x)!;
-    expect(video1.filename).toMatch(/\.ogg$/);
-    expect(video1.size).toBeGreaterThan(1000);
+    const audio1 = coll1.find((x) => "type" in x)!;
+    expect(audio1.filename).toMatch(/\.ogg$/);
+    expect(audio1.size).toBeGreaterThan(1000);

57-59: Variable naming inconsistency.

Similar to the previous comment, the variable is named video2 but refers to an audio file.

-    const video2 = coll2.find((x) => "type" in x)!;
-    expect(video2.filename).toMatch(/\.ogg$/);
-    expect(video2.size).toBeGreaterThan(1000);
+    const audio2 = coll2.find((x) => "type" in x)!;
+    expect(audio2.filename).toMatch(/\.ogg$/);
+    expect(audio2.size).toBeGreaterThan(1000);

157-157: Remove unnecessary continue statement.

The continue statement is unnecessary as it's the last statement in the conditional block.

    } else if (part.type === "text/plain") {
-      continue; // keepalive
+      // keepalive
    } else {
🧰 Tools
🪛 Biome (1.9.4)

[error] 157-157: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)


24-24: Variable naming inconsistency.

The variable is named videoInfo but it's referring to audio data. This should be renamed for clarity.

-    const videoInfo = collected.find((x) => "type" in x)!;
-    expect(videoInfo.filename).toEqual(expect.stringContaining(".ogg"));
-    expect(videoInfo.type).toEqual("audio/ogg");
-    expect(videoInfo.size).toBeGreaterThan(1000);
+    const audioInfo = collected.find((x) => "type" in x)!;
+    expect(audioInfo.filename).toEqual(expect.stringContaining(".ogg"));
+    expect(audioInfo.type).toEqual("audio/ogg");
+    expect(audioInfo.size).toBeGreaterThan(1000);
packages/server/README.md (2)

19-25: Add language specifier to fenced code block.

It's best practice to specify the language for fenced code blocks to enable proper syntax highlighting.

-```
+```http
 URL: /audio/process?<Options|options=OptionsJSON[]>
 Method: POST
 Headers:
 - [X-Options: <OptionsJSON[]>]
 Body: Binary file

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

19-19: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

</details>

</details>

---

`29-34`: **Add language specifier to fenced code block.**

It's best practice to specify the language for fenced code blocks to enable proper syntax highlighting.


```diff
-```
+```http
 Status: 200 OK
 Headers:
 - Content-Type: multipart/mixed; boundary=<boundary>
 Body: multipart/mixed body with status updates and the processed files (if no output option was provided)

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

29-29: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

</details>

</details>

</blockquote></details>
<details>
<summary>packages/core/src/util/ffmpeg-processor.ts (1)</summary><blockquote>

`35-35`: **Await on inputPath could cause issues with string inputs**

When `inputPath` is a string, `await inputPath` will still work (it will just return the string), but it's unnecessary and could be confusing. Consider checking the type before awaiting.

```diff
-        ["-y", ...inArgs, "-i", await inputPath, ...outArgs, outputPath],
+        ["-y", ...inArgs, "-i", typeof inputPath === "string" ? inputPath : await inputPath, ...outArgs, outputPath],
packages/client/src/client.ts (1)

75-79: Helper function parameter types updated

The optimizeFetch function has been updated to accept AsyncIterable or Blob as input, aligning with the processing functions. Consider renaming this function to processFetch to maintain naming consistency.

-async function* optimizeFetch<T>(
+async function* processFetch<T>(
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 921fd64 and 7c182c8.

⛔ Files ignored due to path filters (1)
  • fixtures/audio.mp3 is excluded by !**/*.mp3
📒 Files selected for processing (19)
  • .gitignore (1 hunks)
  • README.md (1 hunks)
  • packages/client/README.md (2 hunks)
  • packages/client/src/client.spec.ts (2 hunks)
  • packages/client/src/client.ts (5 hunks)
  • packages/client/src/index.ts (1 hunks)
  • packages/common/src/index.ts (4 hunks)
  • packages/core/README.md (1 hunks)
  • packages/core/src/audio/audio-processor.spec.ts (1 hunks)
  • packages/core/src/audio/audio-processor.ts (1 hunks)
  • packages/core/src/index.ts (1 hunks)
  • packages/core/src/util/ffmpeg-processor.ts (3 hunks)
  • packages/core/src/videos/video-processor.spec.ts (5 hunks)
  • packages/core/src/videos/video-processor.ts (1 hunks)
  • packages/server/README.md (1 hunks)
  • packages/server/src/audio/process-audio-handler.spec.ts (1 hunks)
  • packages/server/src/audio/process-audio-handler.ts (1 hunks)
  • packages/server/src/server.ts (2 hunks)
  • test-client.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • .gitignore
  • packages/core/src/audio/audio-processor.spec.ts
  • packages/core/src/videos/video-processor.ts
  • packages/server/src/audio/process-audio-handler.ts
  • packages/common/src/index.ts
  • packages/core/src/videos/video-processor.spec.ts
  • packages/core/src/audio/audio-processor.ts
  • packages/server/src/server.ts
🧰 Additional context used
🧬 Code Definitions (3)
packages/server/src/audio/process-audio-handler.spec.ts (2)
packages/server/src/audio/process-audio-handler.ts (1)
  • processAudioHandler (25-60)
packages/common/src/index.ts (3)
  • QueuePosition (5-7)
  • Progress (1-3)
  • ProcessingError (9-11)
test-client.ts (5)
packages/client/src/client.ts (3)
  • processAudio (25-35)
  • processVideo (63-73)
  • processImage (44-54)
packages/core/src/audio/audio-processor.ts (1)
  • processAudio (13-40)
packages/common/src/index.ts (1)
  • ProcessedFile (127-133)
packages/core/src/videos/video-processor.ts (1)
  • processVideo (12-46)
packages/core/src/images/image-processor.ts (1)
  • processImage (17-91)
packages/client/src/client.ts (1)
packages/common/src/index.ts (4)
  • AudioOptions (104-125)
  • ImageOptions (13-65)
  • VideoOptions (67-102)
  • ProcessedFile (127-133)
🪛 Biome (1.9.4)
packages/server/src/audio/process-audio-handler.spec.ts

[error] 157-157: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)

packages/client/src/index.ts

[error] 1-1: Useless rename.

Safe fix: Remove the renaming.

(lint/complexity/noUselessRename)

🪛 markdownlint-cli2 (0.17.2)
packages/server/README.md

19-19: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


29-29: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

🔇 Additional comments (41)
packages/core/src/index.ts (1)

2-5: Well-structured exports with consistent naming.

The changes in exports demonstrate a well-organized approach, providing a unified API surface with consistent function naming patterns. The transition from "optimizer" to "processor" terminology and the addition of audio processing capabilities align well with the PR objectives.

packages/client/src/index.ts (1)

2-2: API surface is consistent with architectural changes.

The export pattern properly exposes the newly added audio processing functionality and maintains the consistent naming pattern across media types.

packages/server/src/audio/process-audio-handler.spec.ts (1)

8-29: Comprehensive test coverage for audio processing.

The test suite thoroughly validates the basic functionality of audio processing with proper status code checking and result validation.

packages/server/README.md (1)

15-35: Well-documented new audio processing endpoint.

The documentation for the new audio processing endpoint follows the same structure as the existing endpoints, providing clear information about request and response formats.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

19-19: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


29-29: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

packages/core/README.md (4)

6-7: Well-defined API unification statement.

The clear statement about API unification for audio, images, and videos sets the stage for the documentation that follows and aligns with the PR objective of unifying the API.


10-21: Good addition of audio processing documentation.

The new section for audio processing includes all necessary information - import statements, input type explanation, and usage pattern. This is consistent with the PR objective of adding a separate API for processing audio.


22-23: Appropriate terminology update for image processing.

The section has been appropriately renamed from "Converting images" to "Processing images" and the code example has been updated to use the new processImage function and ProcessedFile type, maintaining consistency across the API.

Also applies to: 25-32


34-44: Consistent documentation for video processing.

The video processing section follows the same pattern as the audio and image sections, creating a consistent experience for developers using the API.

README.md (4)

9-15: Clear server deployment instructions with updated Docker image.

The section has been renamed to "Running the server" and includes the updated Docker image version, providing clear instructions for deploying the server as a container.


17-29: Helpful local installation instructions.

Added instructions for installing and running the server locally provide flexibility for users who prefer not to use Docker. The note about Bun runtime requirement is important information for users.


31-37: Good module import example for server embedding.

The added example shows how to import and embed the server in a custom project, giving developers additional flexibility for integration.


39-59: Comprehensive client usage example.

The new section provides a clear example of how to use the client package to connect to the server and process a video file. The example demonstrates proper handling of both processed files and status updates.

packages/client/README.md (3)

8-25: Well-documented audio processing functionality.

The new section for audio processing includes a complete example with proper import statements, input type explanation, and comprehensive output handling including progress reporting and error handling.


27-44: Consistent image processing documentation.

The image processing section maintains the same structure as the audio section, ensuring consistency across the API documentation. The example includes all necessary error and progress handling patterns.


46-63: Complete video processing documentation.

The video processing section completes the documentation set, providing developers with examples for all three media types. The structure is consistent with the other sections, making the API intuitive to use.

test-client.ts (4)

1-6: Updated imports reflect new API structure.

The imports have been updated to use the new ProcessedFile type and processing functions, aligning with the unified API approach.


8-24: Comprehensive audio processing example.

The new audio processing example demonstrates how to use the processAudio function with appropriate options and how to properly handle the returned ProcessedFile. This implementation matches the documentation and core implementation seen in the relevant code snippets.


26-30: Consistent video processing implementation.

The video processing example follows the same pattern as the audio processing, using the unified API approach. The options now include an output path parameter which aligns with the API changes.

Also applies to: 31-31


44-48: Standardized image processing implementation.

The image processing implementation maintains consistency with the audio and video examples, using the same pattern for function calls and output handling, which reinforces the unified API approach.

Also applies to: 49-49

packages/core/src/util/ffmpeg-processor.ts (9)

1-1: Import changes reflect the new naming convention

The import has been updated from ConvertedFile to ProcessedFile, which aligns with the broader renaming effort across the codebase to standardize terminology.


4-8: New imports support the enhanced input handling

These additional imports enable the new functionality for handling various input types (file paths, streams, blobs). The createWriteStream and rm functions support temporary file operations, while Tasque provides queue management.


10-25: Function signature rework improves API flexibility

The function has been renamed from optimizeVideo to processFfmpeg and its signature has been enhanced to accept multiple input types and use a callback for argument building. This makes the function more versatile and reusable for different media types.


77-77: Updated to use ProcessedFile instead of ConvertedFile

This change is part of the broader refactoring to standardize on "process" terminology throughout the codebase.


80-82: Improved cleanup handling for temporary files

The code now checks if the input path is a temporary file before attempting to remove it, which prevents accidentally deleting the original file when a file path is provided directly.


104-116: New helper function for temporary file creation

The createTmp function efficiently handles conversion of both stream and blob inputs to a temporary file. The implementation correctly handles the different input types and returns a promise that resolves to the file path.


112-112: Stream extraction handles both Blob and AsyncIterable inputs

The ternary expression correctly handles different input types by checking if the input is a Blob (which has a stream method) or directly using the AsyncIterable.


118-120: Secure random ID generation

The randomId function uses cryptographically secure random values, which is appropriate for generating unique file identifiers. The implementation uses Base64URL encoding which avoids characters that could cause issues in file paths.


26-31:

❓ Verification inconclusive

Dynamic input and output path handling

The implementation now creates a unique ID for each processing job and handles different input types appropriately. This makes the function more versatile but could potentially introduce race conditions if multiple processes use the same temporary directory.


🏁 Script executed:

#!/bin/bash
# Verify if there's any potential race condition handling in the tmpDir creation or cleanup
rg -A 5 $'tmpDir.*mkdir' 

Length of output: 25


Attention: Revisit Concurrency Controls for tmpDir

The dynamic handling using a unique ID for each processing job is a solid improvement. However, our verification did not uncover any explicit mechanism (such as atomic directory creation via mkdir or file locking) to manage concurrent access to the shared temporary directory (tmpDir). This raises a potential risk of race conditions when multiple processes operate in parallel using the same directory.

Action Items:

  • Confirm that the shared usage of tmpDir is either by design or that additional safeguards (e.g., locking mechanisms or unique subdirectory creation per job) are implemented elsewhere.
  • Verify that the helper function (e.g., createTmp) safely creates and cleans up temporary files in concurrent environments.

Please review these aspects to ensure robust concurrency handling.

packages/client/src/client.spec.ts (6)

1-1: Updated import reflects naming convention change

The import has been updated from ConvertedFile to ProcessedFile, aligning with the broader renaming effort across the codebase.


4-4: Updated imports include new processing functions

The import statement now includes processAudio, processImage, and processVideo, reflecting the renamed and expanded API.


6-8: Mock fetch implementation updated

The mock fetch implementation has been updated with improved syntax, using arrow functions and proper typecasting for the server options.


10-32: Added comprehensive tests for audio processing

A new test case for processAudio() verifies that the function correctly processes audio files and returns instances of ProcessedFile with the expected properties.


34-43: Updated image processing tests

The test for image processing has been updated to use processImage instead of optimizeImage and ProcessedFile instead of ConvertedFile. The functionality remains consistent.


60-82: Added comprehensive tests for video processing

A new test case for processVideo() verifies that the function correctly processes video files and returns instances of ProcessedFile with the expected properties. Note that the size check uses expect.any(Number) since video sizes may vary across ffmpeg versions or platforms.

packages/client/src/client.ts (7)

1-9: Updated imports reflect API changes

The imports have been updated to use ProcessedFile instead of ConvertedFile and include the new option types (AudioOptions, ImageOptions, VideoOptions). This aligns with the broader renaming effort across the codebase.


18-35: New audio processing function added

A new processAudio function has been added with comprehensive JSDoc comments. The function accepts a host URL, input (as AsyncIterable or Blob), and options for audio processing. The implementation delegates to the optimizeFetch helper function.


37-54: Image processing function renamed and updated

The optimizeImage function has been renamed to processImage with updated JSDoc comments and parameter types. The function now accepts AsyncIterable or Blob as input, aligning with the other processing functions.


56-73: Video processing function renamed and updated

The optimizeVideo function has been renamed to processVideo with updated JSDoc comments and parameter types. The function now accepts AsyncIterable or Blob as input, aligning with the other processing functions.


80-86: Updated request creation

The request creation has been updated to use the new input handling function. The implementation correctly uses inputToStream to handle different input types.


96-103: Updated to use ProcessedFile instead of ConvertedFile

This change is part of the broader refactoring to standardize on "process" terminology throughout the codebase. The implementation now yields instances of ProcessedFile instead of ConvertedFile.


107-111: Input handling helper function updated

The inputToStream function has been updated to handle AsyncIterable or Blob inputs. The function correctly checks if the input is a ReadableStream or if it doesn't implement the AsyncIterable protocol.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🔭 Outside diff range comments (1)
packages/server/src/videos/process-video-handler.ts (1)

30-42: 🛠️ Refactor suggestion

Add null check for request body

The handler passes request.body! directly to processVideo without checking if it's null or undefined. This could lead to runtime errors if the request doesn't have a body.

-  const iterable = processVideo(request.body!, opts, {
+  if (!request.body) return error(400, "Request body is required");
+  const iterable = processVideo(request.body, opts, {
     signal: request.signal,
   });
🧹 Nitpick comments (9)
packages/core/src/util/streams.ts (1)

3-13: Add error handling to ensure proper stream cleanup

The function correctly handles backpressure and ensures proper stream termination, but lacks error handling. If an exception occurs during iteration, the writable stream might not be properly closed.

Consider adding a try/finally block to ensure the writable stream is properly closed even in case of errors:

export async function exhaustAsyncIterableToWritable(
  it: AsyncIterable<Uint8Array>,
  writable: Writable
) {
-  for await (const chunk of it) {
-    if (!writable.write(chunk))
-      await new Promise((resolve) => writable.once("drain", resolve));
-  }
-  writable.end();
-  await new Promise((resolve) => writable.on("finish", resolve));
+  try {
+    for await (const chunk of it) {
+      if (!writable.write(chunk))
+        await new Promise((resolve) => writable.once("drain", resolve));
+    }
+    writable.end();
+    await new Promise((resolve) => writable.on("finish", resolve));
+  } catch (error) {
+    writable.end();
+    throw error;
+  }
}
packages/server/src/util/response.ts (2)

18-20: Improve type safety in the parameter definition

The {} type is flagged by static analysis as it provides minimal type safety.

Consider using a more specific type or unknown instead of {}:

export async function queueAndStream(
-  iterable: AsyncIterable<{} | ProcessedFile | Blob>
+  iterable: AsyncIterable<unknown | ProcessedFile | Blob>
) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 19-19: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)


30-43: Add null checks for optional properties

The code uses non-null assertion operators (!) with x.name and x.stream, but these properties could be undefined as the stream parameter is optional in the ProcessedFile constructor.

Replace non-null assertions with proper null checks:

if (x instanceof ProcessedFile) {
  clear();
+  if (!x.name || !x.stream) {
+    multipart.part({ payload: { error: "Missing required properties in ProcessedFile" } });
+    continue;
+  }
  multipart.part({
    contentType: x.type,
-    filename: basename(x.name!),
+    filename: basename(x.name),
  });
-  for await (const chunk of x.stream!) {
+  for await (const chunk of x.stream) {
    multipart.write(chunk);
  }
} else {
packages/server/src/audio/process-audio-handler.ts (2)

9-21: Schema definition includes unused field

The options field is included in the schema definition but isn't used anywhere in the handler implementation. This could be confusing to consumers of the API.

-  options: T.Optional(T.String()),

40-58: Consistent error handling for ProcessedFile operations

The file handling operations (writing to output, reading streams) aren't wrapped in try/catch blocks. Consider adding proper error handling to ensure robustness.

 if (opts.output) {
-  await Bun.write(Bun.file(opts.output), Bun.file(value.name));
-  await rm(value.name, { force: true });
+  try {
+    await Bun.write(Bun.file(opts.output), Bun.file(value.name));
+    await rm(value.name, { force: true });
+  } catch (err) {
+    return error(500, `Failed to write to output: ${(err as Error).message}`);
+  }
test-client.ts (2)

1-24: Extract common file handling logic

All three processing examples use identical logic for handling the processed file streams. Consider extracting this into a reusable function to reduce code duplication.

+async function handleProcessedFile(value: ProcessedFile) {
+  const file = Bun.file(value.name);
+  const writer = file.writer();
+  for await (const chunk of value.stream) {
+    writer.write(chunk);
+    await writer.flush();
+  }
+  await writer.end();
+}

 for await (const value of processAudio(
   "http://localhost:3000",
   Bun.file("fixtures/audio.mp3"),
   { format: "ogg", codec: "libvorbis", output: "output/audio.ogg" }
 )) {
   if (value instanceof ProcessedFile) {
-    const file = Bun.file(value.name);
-    const writer = file.writer();
-    for await (const chunk of value.stream) {
-      writer.write(chunk);
-      await writer.flush();
-    }
-    await writer.end();
+    await handleProcessedFile(value);
   } else {
     console.log(value);
   }
 }

22-23: Improve non-file result handling

The else block only logs the value without differentiating between different types (progress, queue position, error). Consider adding more specific handling for each type.

-  } else {
-    console.log(value);
+  } else if ("progress" in value) {
+    console.log(`Progress: ${value.progress}%`);
+  } else if ("position" in value) {
+    console.log(`Queue position: ${value.position}`);
+  } else if ("error" in value) {
+    console.error(`Error: ${value.error}`);
+  } else {
+    console.log("Unknown value type:", value);
   }
packages/server/src/videos/process-video-handler.ts (2)

49-52: Add error handling for file operations

The file operations (writing to output, removing temporary files) aren't wrapped in try/catch blocks. Consider adding proper error handling to ensure robustness.

 if (opts.output) {
-  await Bun.write(Bun.file(opts.output), Bun.file(value.name));
-  await rm(value.name, { force: true });
+  try {
+    await Bun.write(Bun.file(opts.output), Bun.file(value.name));
+    await rm(value.name, { force: true });
+  } catch (err) {
+    console.error(`Failed to write to output: ${(err as Error).message}`);
+    // Consider returning an error or handling this more gracefully
+  }

38-39: Consider supporting multiple options

The comment indicates that only one option is currently supported. Consider supporting multiple options to align with the array parsing approach, or document this limitation better.

Would you like me to provide an implementation that supports processing multiple options in sequence?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c182c8 and 88db9b8.

⛔ Files ignored due to path filters (2)
  • bun.lock is excluded by !**/*.lock
  • fixtures/audio.mp3 is excluded by !**/*.mp3
📒 Files selected for processing (30)
  • .gitignore (1 hunks)
  • .husky/pre-commit (1 hunks)
  • README.md (1 hunks)
  • docker-compose.yaml (1 hunks)
  • package.json (1 hunks)
  • packages/client/README.md (2 hunks)
  • packages/client/src/client.spec.ts (2 hunks)
  • packages/client/src/client.ts (5 hunks)
  • packages/client/src/index.ts (1 hunks)
  • packages/common/src/index.ts (4 hunks)
  • packages/core/README.md (1 hunks)
  • packages/core/src/audio/audio-processor.spec.ts (1 hunks)
  • packages/core/src/audio/audio-processor.ts (1 hunks)
  • packages/core/src/images/image-optimizer.ts (0 hunks)
  • packages/core/src/images/image-processor.ts (1 hunks)
  • packages/core/src/index.ts (1 hunks)
  • packages/core/src/util/ffmpeg-processor.ts (3 hunks)
  • packages/core/src/util/streams.ts (1 hunks)
  • packages/core/src/videos/video-processor.spec.ts (5 hunks)
  • packages/core/src/videos/video-processor.ts (1 hunks)
  • packages/server/README.md (2 hunks)
  • packages/server/src/audio/process-audio-handler.spec.ts (1 hunks)
  • packages/server/src/audio/process-audio-handler.ts (1 hunks)
  • packages/server/src/images/process-image-handler.ts (6 hunks)
  • packages/server/src/server.ts (2 hunks)
  • packages/server/src/util/file.ts (0 hunks)
  • packages/server/src/util/response.ts (3 hunks)
  • packages/server/src/videos/process-video-handler.ts (3 hunks)
  • test-client.ts (2 hunks)
  • test.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • packages/server/src/util/file.ts
  • packages/core/src/images/image-optimizer.ts
✅ Files skipped from review due to trivial changes (1)
  • .husky/pre-commit
🚧 Files skipped from review as they are similar to previous changes (14)
  • packages/server/src/server.ts
  • docker-compose.yaml
  • packages/server/src/audio/process-audio-handler.spec.ts
  • .gitignore
  • test.ts
  • packages/core/src/videos/video-processor.ts
  • packages/core/src/videos/video-processor.spec.ts
  • packages/core/src/images/image-processor.ts
  • packages/core/src/audio/audio-processor.spec.ts
  • packages/client/src/index.ts
  • packages/core/src/index.ts
  • packages/server/README.md
  • packages/common/src/index.ts
  • packages/core/src/audio/audio-processor.ts
🧰 Additional context used
🧬 Code Definitions (7)
packages/server/src/audio/process-audio-handler.ts (2)
packages/common/src/index.ts (2)
  • AudioOptions (104-125)
  • ProcessedFile (127-133)
packages/core/src/audio/audio-processor.ts (1)
  • processAudio (13-40)
test-client.ts (5)
packages/client/src/client.ts (3)
  • processAudio (25-35)
  • processVideo (63-73)
  • processImage (44-54)
packages/core/src/audio/audio-processor.ts (1)
  • processAudio (13-40)
packages/common/src/index.ts (1)
  • ProcessedFile (127-133)
packages/core/src/videos/video-processor.ts (1)
  • processVideo (12-46)
packages/core/src/images/image-processor.ts (1)
  • processImage (17-91)
packages/server/src/videos/process-video-handler.ts (3)
packages/common/src/index.ts (2)
  • VideoOptions (67-102)
  • ProcessedFile (127-133)
packages/client/src/client.ts (1)
  • processVideo (63-73)
packages/core/src/videos/video-processor.ts (1)
  • processVideo (12-46)
packages/client/src/client.spec.ts (4)
packages/client/src/index.ts (5)
  • setFetch (2-2)
  • processAudio (2-2)
  • ProcessedFile (1-1)
  • processImage (2-2)
  • processVideo (2-2)
packages/server/src/server.ts (1)
  • serveOpts (6-23)
packages/core/src/index.ts (3)
  • processAudio (2-2)
  • processImage (3-3)
  • processVideo (5-5)
packages/common/src/index.ts (1)
  • ProcessedFile (127-133)
packages/client/src/client.ts (1)
packages/common/src/index.ts (4)
  • AudioOptions (104-125)
  • ImageOptions (13-65)
  • VideoOptions (67-102)
  • ProcessedFile (127-133)
packages/server/src/images/process-image-handler.ts (6)
packages/common/src/index.ts (2)
  • ImageOptions (13-65)
  • ProcessedFile (127-133)
packages/client/src/index.ts (2)
  • processImage (2-2)
  • ProcessedFile (1-1)
packages/core/src/index.ts (1)
  • processImage (3-3)
packages/client/src/client.ts (1)
  • processImage (44-54)
packages/core/src/images/image-processor.ts (1)
  • processImage (17-91)
packages/server/src/util/response.ts (2)
  • error (5-7)
  • queueAndStream (18-53)
packages/server/src/util/response.ts (1)
packages/common/src/index.ts (1)
  • ProcessedFile (127-133)
🪛 Biome (1.9.4)
packages/server/src/util/response.ts

[error] 19-19: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

🔇 Additional comments (39)
package.json (2)

8-8: New "check" Script Added: Verify Combined Build & Test Command
The addition of the "check": "bun run build -f && bun run test" script helps automate the build and test process. Please ensure that both commands work as expected in your environment, and consider verifying that the -f flag with the build command is required and functions correctly.


14-14: New "husky" Dev Dependency: Confirm Pre-commit Hook Integration
The introduction of "husky": "^9.1.7" is in line with the updated pre-commit configuration. Please confirm that documentation or setup instructions (such as running husky install) are provided so that developers correctly initialize Husky after cloning the repository.

packages/core/README.md (4)

6-7: LGTM! Clear introduction to the unified API concept

The explicit mention of a unified API for all media types sets proper expectations for users and improves documentation clarity.


10-20: LGTM! Well-structured audio processing documentation

The new audio processing section follows the same pattern as other media types, contributing to a consistent documentation experience. The examples clearly show how to use the new API.


22-32: LGTM! Updated image processing section

The section has been renamed from "optimizing" to "processing" for consistency with other media types and includes updated import statements and standardized input type description.


34-44: LGTM! Consistent video processing documentation

The video processing section follows the same pattern as other media types, maintaining documentation consistency across the codebase.

packages/server/src/util/response.ts (1)

1-1: LGTM! Updated import to reflect the new ProcessedFile type

Import statement correctly updated to use ProcessedFile, consistent with the codebase-wide renaming.

README.md (4)

9-15: LGTM! Clear server deployment instructions

The updated Docker command references the correct image version and provides clear deployment instructions.


17-29: LGTM! Helpful local installation instructions

The addition of local installation instructions makes the documentation more comprehensive, clearly noting the Bun runtime requirement.


31-37: LGTM! Useful server embedding instructions

The example for embedding the server as a module is a valuable addition for developers who want to integrate the server into their own applications.


39-59: LGTM! Comprehensive client usage example

The client usage example clearly demonstrates how to:

  1. Connect to the server
  2. Process a video file
  3. Handle both processed file results and status updates
packages/server/src/audio/process-audio-handler.ts (1)

33-34: Consider supporting multiple options

The comment indicates that only one option is currently supported. Consider supporting multiple options to align with the array parsing approach, or document this limitation better.

Is this a temporary limitation or a design decision? If it's temporary, you might want to track it with a TODO comment.

packages/client/src/client.spec.ts (5)

1-4: Updated imports reflect the API changes

The imports have been correctly updated to use ProcessedFile from the common package and to import the new functions processAudio, processImage, and processVideo.


6-8: Good test setup with mock fetch implementation

The setup correctly configures the tests to route requests through the server's fetch handler directly, enabling proper integration testing without network calls.


10-32: New test suite for audio processing functionality

The new test case for processAudio() correctly verifies that:

  1. The function can process an audio file
  2. The server returns a properly formatted ProcessedFile instance
  3. The processed file has the expected name, MIME type, and size

This aligns with the PR objective of adding dedicated audio processing capabilities.


34-58: Updated image processing test suite

The test for processImage() has been correctly updated to:

  1. Use the new function name (processImage instead of optimizeImage)
  2. Check for ProcessedFile instances instead of ConvertedFile
  3. Maintain the same verification logic for the processed output

This ensures backward compatibility while implementing the unified API approach.


60-82: New test suite for video processing

The test case for processVideo() follows the same pattern as the audio and image tests, providing consistent coverage for all media types. The use of expect.any(Number) for the size is appropriate since video processing may result in variable file sizes.

packages/core/src/util/ffmpeg-processor.ts (7)

1-8: Updated imports align with the new processing model

The import statements have been correctly updated to include ProcessedFile from the common package and add necessary utilities for working with file streams.


10-25: Enhanced function signature with improved flexibility

The function has been renamed from optimizeVideo to processFfmpeg with a more flexible signature that:

  1. Accepts multiple input types (string path, AsyncIterable, or Blob)
  2. Uses a callback for dynamic FFmpeg argument generation
  3. Supports queue management and abort signaling

This significantly improves the reusability of the function for different media types.


26-32: Improved input handling with temporary file creation

The code now handles different input types intelligently:

  1. Uses direct file paths when provided
  2. Creates temporary files for streams or blobs
  3. Generates unique IDs for temporary files

This implementation supports the PR objective of unifying the API to handle both file paths and binary data.


77-77: Updated to use ProcessedFile class

The function now correctly yields a ProcessedFile instance instead of ConvertedFile, maintaining consistency with the unified API model.


80-82: Improved cleanup for temporary files

The cleanup logic has been enhanced to handle temporary input files created from streams or blobs, preventing file system leaks.


104-116: Well-implemented temporary file creation

The createTmp helper function effectively:

  1. Creates a temporary file with a unique name
  2. Handles both AsyncIterable and Blob inputs
  3. Uses the efficient exhaustAsyncIterableToWritable utility

This implementation supports processing streams and blobs seamlessly.


118-120: Secure random ID generation

The randomId function uses cryptographically secure random values to generate unique identifiers, which is appropriate for temporary file names.

packages/server/src/images/process-image-handler.ts (8)

1-1: Updated type import aligns with naming convention changes

The import now correctly uses ImageOptions instead of ImageOptimizerOptions, maintaining consistency with the type system changes.


4-4: Updated imports for the new processing model

The import now correctly includes ProcessedFile and processImage from the m4k package, reflecting the API changes.


80-80: Type declaration updated to use the new options type

The variable declaration now correctly uses ImageOptions[] instead of ImageOptimizerOptions[], maintaining type consistency.


89-91: Updated function call with improved parameter passing

The function call has been updated to:

  1. Use processImage instead of optimizeImage
  2. Pass the request body directly, which could be a stream or a blob
  3. Pass the request's abort signal for cancellation support

This implements the unified API approach for image processing.


97-97: Updated type check for processed files

The type check now correctly looks for ProcessedFile instances instead of ConvertedFile, maintaining consistency with the new processing model.


109-109: Updated constructor call for processed files

The code now correctly creates a new ProcessedFile instance instead of ConvertedFile, maintaining consistency with the new processing model.


131-131: Updated return type annotation

The function's return type has been correctly updated to ImageOptions instead of ImageOptimizerOptions, maintaining type consistency.


143-149: Consistent object property formatting

The crop object properties are now consistently formatted, improving code readability.

packages/client/src/client.ts (7)

1-9: Updated imports align with the new type system

The imports have been correctly updated to:

  1. Use ProcessedFile instead of ConvertedFile
  2. Import the new types AudioOptions, ImageOptions, and VideoOptions
  3. Maintain necessary types for progress tracking and error handling

This supports the unified API approach.


18-35: Well-implemented audio processing function

The new processAudio function:

  1. Has comprehensive JSDoc comments
  2. Follows the same pattern as other processing functions
  3. Correctly handles input streams or blobs
  4. Leverages the common optimizeFetch helper function

This satisfies the PR objective of adding a separate API for audio processing.


37-54: Renamed and updated image processing function

The function has been renamed from optimizeImage to processImage and includes:

  1. Detailed JSDoc comments
  2. Simplified input types (AsyncIterable or Blob)
  3. Updated options type (ImageOptions)

This maintains consistency with the unified API approach.


56-73: Renamed and updated video processing function

The function has been renamed from optimizeVideo to processVideo and includes:

  1. Detailed JSDoc comments
  2. Simplified input types (AsyncIterable or Blob)
  3. Updated options type (VideoOptions)

This maintains consistency with the unified API approach.


75-85: Enhanced request handling in optimizeFetch

The helper function now correctly:

  1. Accepts simplified input types
  2. Converts inputs to streams when needed
  3. Properly constructs the request with options in headers

This implementation supports the unified API approach for all media types.


96-102: Updated to yield ProcessedFile instances

The function now correctly yields ProcessedFile instances instead of ConvertedFile, maintaining consistency with the unified API model.


107-111: Efficient input conversion utility

The inputToStream function intelligently handles different input types:

  1. Passes ReadableStream instances through directly
  2. Passes Blob instances through directly
  3. Converts AsyncIterable instances to streams

This enables the API to work with a variety of input types.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
packages/server/src/audio/process-audio-handler.ts (1)

44-54: Potential temporary file cleanup issue.

When no output path is specified, the temporary file created by processAudio isn't explicitly cleaned up. This could lead to accumulation of temporary files over time.

Consider adding cleanup for temporary files even when no output is specified:

 if (opts.output) {
   await Bun.write(Bun.file(opts.output), Bun.file(value.name));
   await rm(value.name, { force: true });
 } else {
   yield new ProcessedFile(
     opts.name ?? basename(value.name),
     value.type,
     value.stream ?? Bun.file(value.name).stream()
   );
+  // Clean up the temporary file after streaming
+  await rm(value.name, { force: true });
 }
test-client.ts (1)

8-60: Consider reducing code duplication across processing functions

There's significant code duplication between the audio, video, and image processing sections. Each block uses nearly identical patterns for handling the processed files.

Consider creating a helper function to reduce duplication:

+async function processMediaFile(generator, outputPath) {
+  for await (const value of generator) {
+    if (value instanceof ProcessedFile) {
+      const file = Bun.file(value.name);
+      const writer = file.writer();
+      for await (const chunk of value.stream) {
+        writer.write(chunk);
+        await writer.flush();
+      }
+      await writer.end();
+    } else {
+      console.log(value);
+    }
+  }
+}
+
 // Then use it like:
+await processMediaFile(
+  processAudio(
+    "http://localhost:3000",
+    Bun.file("fixtures/audio.mp3"),
+    { format: "ogg", codec: "libvorbis", output: "output/audio.ogg" }
+  )
+);
packages/server/src/videos/process-video-handler.ts (1)

49-53: Potential lack of feedback when using output option

When opts.output is provided, the function writes to that file but doesn't yield any value to the caller, which means they receive no feedback about the processing.

Consider yielding a success message or status object when using the output option:

if (opts.output) {
  await Bun.write(Bun.file(opts.output), Bun.file(value.name));
  await rm(value.name, { force: true });
+ yield { success: true, output: opts.output };
} else {
packages/core/src/util/ffmpeg-processor.ts (1)

17-92: Consider enhancing error handling

While the function handles basic errors, it could be improved for more robust error reporting, especially for FFmpeg process errors.

Consider enhancing error handling with more detailed information:

if (code !== 0) {
-  throw new Error(`ffmpeg exited with code ${code}: ${errStr}`);
+  const errorInfo = {
+    code,
+    message: errStr,
+    command: ["-y", ...inArgs, "-i", "(input)", ...outArgs, outputPath].join(" "),
+    format
+  };
+  throw new Error(`FFmpeg processing failed: ${JSON.stringify(errorInfo)}`);
}
packages/client/src/client.spec.ts (1)

10-80: Consider reducing test code duplication

There's significant code duplication between the three test functions. Each follows the same pattern for testing the respective processing functions.

Consider creating a helper function to reduce duplication:

+async function testProcessFunction(
+  processFn,
+  fileUrl,
+  options,
+  expectedResults
+) {
+  const file = Bun.file(fileUrl);
+  const files: { name: string; type: string; size: number }[] = [];
+
+  for await (const x of processFn("http://localhost:3000", file, options)) {
+    if (x instanceof ProcessedFile) {
+      const chunks = await Array.fromAsync(x.stream);
+      files.push({
+        name: x.name,
+        type: x.type,
+        size: chunks.reduce((sum, chunk) => sum + chunk.length, 0),
+      });
+    }
+  }
+
+  expect(files).toEqual(expectedResults);
+}
+
+// Example usage:
+it("should query the server to process an audio file", async () => {
+  await testProcessFunction(
+    processAudio,
+    "../../fixtures/audio.mp3",
+    [{ format: "mp3", name: "audio.mp3" }],
+    [{ name: "audio.mp3", type: "audio/mpeg", size: 52288 }]
+  );
+});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 88db9b8 and 1133c91.

⛔ Files ignored due to path filters (2)
  • bun.lock is excluded by !**/*.lock
  • fixtures/audio.mp3 is excluded by !**/*.mp3
📒 Files selected for processing (23)
  • .gitignore (1 hunks)
  • .husky/pre-commit (1 hunks)
  • README.md (1 hunks)
  • package.json (1 hunks)
  • packages/client/README.md (2 hunks)
  • packages/client/src/client.spec.ts (2 hunks)
  • packages/client/src/client.ts (5 hunks)
  • packages/client/src/index.ts (1 hunks)
  • packages/common/src/index.ts (4 hunks)
  • packages/core/README.md (1 hunks)
  • packages/core/src/audio/audio-processor.spec.ts (1 hunks)
  • packages/core/src/audio/audio-processor.ts (1 hunks)
  • packages/core/src/index.ts (1 hunks)
  • packages/core/src/util/ffmpeg-processor.ts (3 hunks)
  • packages/core/src/videos/video-processor.spec.ts (5 hunks)
  • packages/core/src/videos/video-processor.ts (1 hunks)
  • packages/server/README.md (2 hunks)
  • packages/server/src/audio/process-audio-handler.spec.ts (1 hunks)
  • packages/server/src/audio/process-audio-handler.ts (1 hunks)
  • packages/server/src/images/process-image-handler.ts (5 hunks)
  • packages/server/src/server.ts (2 hunks)
  • packages/server/src/videos/process-video-handler.ts (3 hunks)
  • test-client.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (13)
  • .husky/pre-commit
  • .gitignore
  • packages/server/src/server.ts
  • packages/client/src/index.ts
  • packages/server/src/audio/process-audio-handler.spec.ts
  • packages/server/README.md
  • packages/core/src/audio/audio-processor.spec.ts
  • package.json
  • packages/core/src/index.ts
  • packages/core/src/videos/video-processor.ts
  • packages/core/src/audio/audio-processor.ts
  • packages/common/src/index.ts
  • packages/core/src/videos/video-processor.spec.ts
🧰 Additional context used
🧬 Code Definitions (5)
packages/server/src/audio/process-audio-handler.ts (2)
packages/common/src/index.ts (2)
  • AudioOptions (104-125)
  • ProcessedFile (127-133)
packages/core/src/audio/audio-processor.ts (1)
  • processAudio (13-40)
packages/server/src/videos/process-video-handler.ts (3)
packages/common/src/index.ts (2)
  • VideoOptions (67-102)
  • ProcessedFile (127-133)
packages/client/src/client.ts (1)
  • processVideo (63-73)
packages/core/src/videos/video-processor.ts (1)
  • processVideo (12-46)
packages/client/src/client.spec.ts (5)
packages/client/src/index.ts (5)
  • setFetch (2-2)
  • processAudio (2-2)
  • ProcessedFile (1-1)
  • processImage (2-2)
  • processVideo (2-2)
packages/core/src/audio/audio-processor.ts (1)
  • processAudio (13-40)
packages/common/src/index.ts (1)
  • ProcessedFile (127-133)
packages/core/src/images/image-processor.ts (1)
  • processImage (17-91)
packages/core/src/videos/video-processor.ts (1)
  • processVideo (12-46)
packages/server/src/images/process-image-handler.ts (6)
packages/server/src/util/response.ts (2)
  • error (5-7)
  • queueAndStream (18-53)
packages/common/src/index.ts (2)
  • ImageOptions (13-65)
  • ProcessedFile (127-133)
packages/client/src/index.ts (2)
  • processImage (2-2)
  • ProcessedFile (1-1)
packages/client/src/client.ts (1)
  • processImage (44-54)
packages/core/src/index.ts (1)
  • processImage (3-3)
packages/core/src/images/image-processor.ts (1)
  • processImage (17-91)
packages/client/src/client.ts (1)
packages/common/src/index.ts (4)
  • AudioOptions (104-125)
  • ImageOptions (13-65)
  • VideoOptions (67-102)
  • ProcessedFile (127-133)
🔇 Additional comments (43)
packages/core/README.md (3)

6-7: Well-designed API unification.

Unifying the API across audio, images, and videos creates a more consistent developer experience. This approach follows the principle of least surprise by providing a standardized interface for similar operations.


10-21: Good addition of audio processing documentation.

The new audio processing section maintains consistency with the image and video processing documentation. This ensures that developers have a clear understanding of how to process all supported media types.


22-44: Consistent naming convention applied correctly.

Renaming from optimize* to process* functions creates a more accurate description of the functionality while maintaining consistency across all media types. The updated examples properly reflect these changes.

README.md (2)

9-37: Comprehensive server deployment instructions.

The detailed instructions for running the server as a Docker container or as a local package provide clear guidance for users. Including the note about Bun runtime requirements is particularly helpful.


39-59: Clear client usage example.

The client usage example effectively demonstrates how to process a video file using the API, including proper handling of both processed files and status updates. This aligns well with the unified API approach.

packages/client/README.md (4)

4-4: Improved clarity on progress reporting mechanism.

Explicitly mentioning that progress reporting is via AsyncIterables provides developers with a clear understanding of how to consume progress information.


8-25: Consistent API naming for audio processing.

The updated section for audio processing maintains consistency with the other media types and properly reflects the renamed function from optimizeAudio to processAudio.


27-44: Consistent API naming for image processing.

The renamed section for image processing aligns with the other media types and properly reflects the renamed function from optimizeImage to processImage.


46-63: Added video processing documentation.

The new video processing section completes the documentation for all media types, providing consistency in the API documentation.

packages/server/src/audio/process-audio-handler.ts (3)

9-21: Well-structured options schema.

The schema correctly defines all the potential options for audio processing, using appropriate type definitions for each field. The use of TypeBox for schema validation is a good practice for ensuring type safety at runtime.


25-39: Request validation and error handling is robust.

The handler correctly validates the request body and options, providing appropriate error responses for invalid inputs. The explicit comment about supporting only one option set helps future maintainers understand the current limitation.


35-38: Add null check for request body before passing to processAudio.

While there's a check at the beginning of the handler, passing request.body directly to processAudio without a type assertion or additional check could lead to type errors.

test-client.ts (4)

1-6: Updated imports align with the new unified API

The imports have been correctly updated to reflect the new API naming convention, replacing ConvertedFile with ProcessedFile and using the new process* functions instead of optimize* functions.


8-24: New audio processing functionality works correctly

The new audio processing code correctly implements the unified API approach, handling the input file and processing options appropriately.


26-30: Video processing now includes output path parameter

The updated video processing code correctly includes the output path parameter in the options, which aligns with the unified API approach.


44-48: Image processing now includes output path parameter

The updated image processing code correctly includes the output path parameter in the options, consistent with the other processing functions.

packages/server/src/videos/process-video-handler.ts (4)

3-4: Updated imports align with the unified API

The imports have been correctly updated to reflect the new API naming convention, replacing ConvertedFile with ProcessedFile and using processVideo instead of optimizeVideo.


31-33: Added proper request body validation

Good addition of a check to ensure the request body is provided, returning an appropriate error response if missing.


41-43: Simplified video processing with unified API

The code now directly calls processVideo with the request body and options, which is cleaner than the previous approach of manually handling temporary files.


48-59: Improved output file handling logic

The updated code properly handles the output file path if provided, or yields a new ProcessedFile with the appropriate name and type.

packages/core/src/util/ffmpeg-processor.ts (8)

1-9: Updated imports align with the unified API

The imports have been correctly updated to include ProcessedFile instead of ConvertedFile and add necessary imports for the new functionality.


10-16: Improved function documentation

The JSDoc comment for the processFfmpeg function clearly explains its purpose and parameters, including the new flexibility to accept different input types.


17-25: Enhanced function signature with better flexibility

The function signature has been significantly improved to:

  1. Accept multiple input types (file path, stream, or blob)
  2. Use a callback for dynamic argument generation
  3. Accept necessary context parameters like signal, queue, and tmpDir

This design provides much better flexibility and reusability.


26-29: Smart input handling with type checking

The code efficiently determines how to handle the input based on its type, using a string path directly or creating a temporary file for streams/blobs.


77-77: Updated to use ProcessedFile

Correctly updated to use ProcessedFile instead of ConvertedFile, maintaining consistency with the rest of the codebase.


79-82: Improved cleanup with type checking

The cleanup code now properly checks if the input path is not a string before attempting to remove it, preventing errors when the input is a file path string.


104-116: Well-designed helper function for temporary file creation

The createTmp function is a clean, reusable helper that handles creating a temporary file from an input stream or blob.


118-120: Secure random ID generation

The randomId function uses cryptographically secure random values, which is appropriate for generating unique file identifiers.

packages/client/src/client.spec.ts (4)

1-8: Updated imports and setup for the unified API

The imports and setup have been correctly updated to reflect the new API naming convention and functions.


10-32: New comprehensive test for audio processing

The new test for processAudio is well-structured and verifies that the function correctly processes audio files and returns the expected output.


34-58: Updated image processing test

The test for processImage has been properly updated to use the new function name and verify the correct processing of image files.


60-82: New comprehensive test for video processing

The new test for processVideo correctly verifies the function's ability to process video files and return the expected output.

Note that using expect.any(Number) for the size is appropriate since video processing may result in different file sizes depending on various factors.

packages/server/src/images/process-image-handler.ts (5)

1-1: Import statements updated to reflect the unified API approach.

The imports have been appropriately updated to use the new type names (ImageOptions instead of what was likely ImageOptimizerOptions) and the renamed processing function (processImage instead of optimizeImage), which aligns with the PR objective of unifying the API.

Also applies to: 4-4


80-81: Good defensive coding with request body validation.

Adding an explicit check for the request body before proceeding with processing is a good practice for robust error handling. The type declaration for optsArr has also been properly updated to match the new type name.


89-91: Function call updated to use abort signal for cancellation support.

The function call has been updated to use the new processImage function and now includes the request's abort signal. This is a good improvement as it allows for proper cancellation of in-progress operations when the client disconnects.


97-97: Instance checks and yield statements updated to use ProcessedFile.

The code has been properly updated to check for instances of ProcessedFile instead of ConvertedFile, maintaining consistency with the type changes across the codebase.

Also applies to: 109-109


131-131: Return type and crop object construction updated.

The return type annotation has been updated to match the new ImageOptions type. The crop object creation has been maintained with the same structure, ensuring that optional properties are properly handled.

Also applies to: 143-149

packages/client/src/client.ts (6)

2-9: Import statements updated to reflect the unified API approach.

The imports have been properly updated to use the new ProcessedFile class and type definitions for the different media options (AudioOptions, ImageOptions, VideoOptions), which aligns with the PR objective of unifying the API.


18-35: New processAudio function added with proper documentation.

A new function has been added to process audio files, following the same pattern as the existing functions for images and videos. The well-written JSDoc comments clearly explain the purpose, parameters, and return values, enhancing the API's usability.


37-54: Image processing function renamed and documented with JSDoc.

The function has been renamed from optimizeImage to processImage for consistency with the new unified API approach. Comprehensive JSDoc comments have been added to improve developer experience. The function signature has been updated to accept a more specific input type (AsyncIterable<Uint8Array> | Blob).


56-73: Video processing function renamed and documented with JSDoc.

The function has been renamed from optimizeVideo to processVideo for consistency with the new unified API approach. Comprehensive JSDoc comments have been added to improve developer experience. The function signature has been updated to accept a more specific input type (AsyncIterable<Uint8Array> | Blob).


75-105: Fetch implementation updated with modern Request API.

The fetch implementation has been updated to use the modern Request constructor pattern and properly yield instances of ProcessedFile instead of ConvertedFile. This change maintains consistency with the type changes across the codebase.


107-111: Helper function renamed for clarity.

The function has been renamed from what was likely bodyToStream to inputToStream, which better reflects its purpose of converting various input types to a stream.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/client/src/client.ts (1)

107-111: Potential type checking inconsistency in inputToStream function.

The function still checks if the input is an instance of ReadableStream, but ReadableStream is no longer part of the parameter type. While this doesn't cause issues with the current implementation, it could be simplified.

-function inputToStream(input: AsyncIterable<Uint8Array> | Blob) {
-  return input instanceof ReadableStream || !(Symbol.asyncIterator in input)
-    ? input
-    : iterableToStream(input);
+function inputToStream(input: AsyncIterable<Uint8Array> | Blob) {
+  return !(Symbol.asyncIterator in input)
+    ? input
+    : iterableToStream(input);
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1133c91 and ff3d7a1.

⛔ Files ignored due to path filters (2)
  • bun.lock is excluded by !**/*.lock
  • fixtures/audio.mp3 is excluded by !**/*.mp3
📒 Files selected for processing (23)
  • .gitignore (1 hunks)
  • .husky/pre-commit (1 hunks)
  • README.md (1 hunks)
  • package.json (1 hunks)
  • packages/client/README.md (2 hunks)
  • packages/client/src/client.spec.ts (2 hunks)
  • packages/client/src/client.ts (5 hunks)
  • packages/client/src/index.ts (1 hunks)
  • packages/common/src/index.ts (4 hunks)
  • packages/core/README.md (1 hunks)
  • packages/core/src/audio/audio-processor.spec.ts (1 hunks)
  • packages/core/src/audio/audio-processor.ts (1 hunks)
  • packages/core/src/index.ts (1 hunks)
  • packages/core/src/util/ffmpeg-processor.ts (3 hunks)
  • packages/core/src/videos/video-processor.spec.ts (5 hunks)
  • packages/core/src/videos/video-processor.ts (1 hunks)
  • packages/server/README.md (2 hunks)
  • packages/server/src/audio/process-audio-handler.spec.ts (1 hunks)
  • packages/server/src/audio/process-audio-handler.ts (1 hunks)
  • packages/server/src/images/process-image-handler.ts (5 hunks)
  • packages/server/src/server.ts (2 hunks)
  • packages/server/src/videos/process-video-handler.ts (3 hunks)
  • test-client.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (13)
  • .husky/pre-commit
  • packages/server/src/server.ts
  • .gitignore
  • package.json
  • packages/core/src/videos/video-processor.ts
  • packages/client/src/index.ts
  • packages/server/src/audio/process-audio-handler.spec.ts
  • packages/core/src/videos/video-processor.spec.ts
  • packages/server/src/audio/process-audio-handler.ts
  • packages/core/src/audio/audio-processor.spec.ts
  • packages/core/src/audio/audio-processor.ts
  • packages/common/src/index.ts
  • packages/server/src/images/process-image-handler.ts
🧰 Additional context used
🧬 Code Definitions (3)
packages/client/src/client.spec.ts (3)
packages/client/src/index.ts (4)
  • processAudio (2-2)
  • ProcessedFile (1-1)
  • processImage (2-2)
  • processVideo (2-2)
packages/core/src/index.ts (3)
  • processAudio (2-2)
  • processImage (3-3)
  • processVideo (5-5)
packages/common/src/index.ts (1)
  • ProcessedFile (127-133)
test-client.ts (5)
packages/client/src/client.ts (3)
  • processAudio (25-35)
  • processVideo (63-73)
  • processImage (44-54)
packages/core/src/audio/audio-processor.ts (1)
  • processAudio (13-40)
packages/common/src/index.ts (1)
  • ProcessedFile (127-133)
packages/core/src/videos/video-processor.ts (1)
  • processVideo (12-46)
packages/core/src/images/image-processor.ts (1)
  • processImage (17-91)
packages/client/src/client.ts (1)
packages/common/src/index.ts (4)
  • AudioOptions (104-125)
  • ImageOptions (13-65)
  • VideoOptions (67-102)
  • ProcessedFile (127-133)
🔇 Additional comments (41)
packages/core/src/index.ts (1)

2-5: Excellent API unification with consistent naming patterns

The export updates successfully implement the unified API approach mentioned in the PR objectives. The naming convention has been standardized from "optimize" to "process" across all media types (audio, image, video), which creates a more consistent and intuitive API.

The addition of audio processing functionality aligns with the PR's goal of adding a separate API for audio processing.

packages/core/README.md (4)

6-7: Good introduction to the unified API concept

This addition clearly communicates the key concept of API unification for all media types, which matches the PR objectives.


10-21: Well-structured documentation for the new audio processing feature

The documentation for audio processing follows the same pattern as the existing media types, making it easy for users to understand. The comment about input types clearly explains the flexibility of the API to accept different input formats.


22-32: Consistent documentation across media types

The image processing section has been updated to maintain consistency with the other sections. The renaming from "optimizeImage" to "processImage" and standardization of input types helps users understand the unified API approach.


34-44: Consistent documentation for video processing

The video processing section has been similarly updated for API consistency, following the same pattern as the other media types. This completes the unified API documentation.

packages/server/README.md (3)

15-36: Well-structured API documentation for the new audio processing endpoint

The new audio processing endpoint documentation is well-structured and follows the same format as the existing endpoints. The request and response sections are clear and provide all necessary information for consumers of the API.


37-57: Improved formatting for image processing endpoint documentation

The image processing endpoint documentation has been reformatted to match the new structure, enhancing overall consistency in the API documentation.


59-79: Consistent formatting for video processing endpoint

The video endpoint documentation has been updated to maintain consistency with the other endpoints, making the entire API documentation more cohesive and easier to follow.

README.md (4)

9-15: Improved server deployment documentation

The reorganization from "Usage" to "Running the server" with specific package references improves clarity. The updated Docker image version ensures users have access to the latest functionality including the new audio processing capabilities.


17-29: Valuable alternative installation and usage instructions

Adding documentation for local package installation provides flexibility for users who prefer not to use Docker. The clear note about Bun runtime requirements helps avoid potential confusion or deployment issues.


31-37: Useful embedded server implementation example

This addition provides a more advanced use case for developers who want to integrate the server into their own projects rather than running it standalone.


39-59: Clear client usage example with the unified API

The client usage section effectively demonstrates how to use the new unified API, showing the consistent method signature pattern. The example provides a complete workflow including handling both processed files and status updates.

packages/client/README.md (2)

13-14: Input type documentation inconsistency.

The comment states input is "an AsyncIterable or Blob", but according to the core implementation (processAudio in core/src/audio/audio-processor.ts), the input can also be a file path string. This inconsistency exists for all processing functions in this README.

To verify this inconsistency, let's review the function signatures:

#!/bin/bash
# Check the input types for process functions in core package
rg -A 1 "export function process(Audio|Image|Video)" packages/core/src/

51-52: Inconsistent input type documentation.

For processVideo, the comment states that input is "an AsyncIterable or Blob", but according to the core implementation, the input can also be a file path string.

test-client.ts (4)

1-6: LGTM! Package imports updated correctly.

Imports have been properly updated to use the new ProcessedFile class and process functions.


8-24: Good implementation of audio processing.

The new audio processing code follows the same pattern as the existing video and image processing code, maintaining consistency across the different media types.


26-30: Updated video processing with output path.

The video processing code has been correctly updated to use the new processVideo function with the additional output parameter.


44-48: Updated image processing with output path.

The image processing code has been correctly updated to use the new processImage function with the additional output parameter.

packages/server/src/videos/process-video-handler.ts (4)

3-4: LGTM! Updated imports.

Correctly updated the imports to use ProcessedFile and processVideo from the m4k package.


31-32: Good validation for request body.

Added proper validation to check for the presence of a request body before processing.


41-43: Simplified video processing.

The code has been streamlined to directly call processVideo with the request body instead of creating temporary files first, which is more efficient.


48-62: Updated ProcessedFile handling logic.

The handler has been properly updated to work with the new ProcessedFile class and handle output files correctly.

packages/core/src/util/ffmpeg-processor.ts (6)

1-8: LGTM! Updated imports.

The imports have been correctly updated to support the new functionality.


10-16: Improved documentation.

The function documentation clearly explains that the input can be a file path, a stream, or a blob, which is a good improvement.


17-25: Good API unification.

The function signature has been updated to accept multiple input types (string, AsyncIterable, or Blob) as specified in the PR objectives, making the API more flexible.


26-91: LGTM! Updated ffmpeg processing logic.

The function has been refactored to handle different input types and properly process media using ffmpeg. The cleanup logic has been improved to handle temporary files correctly.


104-116: Good helper function for temporary files.

The createTmp function is a clean abstraction for handling temporary file creation from stream or blob inputs.


118-120: Secure random ID generation.

The randomId function uses cryptographically secure random values, which is appropriate for generating temporary file names.

packages/client/src/client.spec.ts (6)

1-4: Updated imports to reflect the new API design.

The imports now correctly reflect the API renaming pattern with ProcessedFile replacing ConvertedFile, and adding the new processing functions. The naming convention is more consistent as all media types now use a "process" prefix.


6-8: Simplified setFetch implementation.

The updated implementation for mocking the fetch function uses cleaner TypeScript casting with as any for better compatibility with the testing environment.


10-32: Well-structured test for the new audio processing functionality.

This new test case for processAudio() follows the same pattern as the other media processing tests, ensuring consistency across the test suite. It properly verifies the audio file processing by checking the returned file properties.


34-42: Updated image processing test to use the new function name.

The test for image processing has been correctly updated to use processImage instead of optimizeImage, maintaining the same functionality but aligning with the new naming convention.


43-58: Correctly updated type checking for processed files.

The test now checks for ProcessedFile instances instead of ConvertedFile, which aligns with the updated type system. The expectations for the processed files remain the same, ensuring backward compatibility.


60-82: Well-implemented test for video processing functionality.

The new test for processVideo() follows the same pattern as the audio and image tests, ensuring consistency. Using expect.any(Number) for the video file size is appropriate since video processing might result in variable file sizes.

packages/client/src/client.ts (7)

1-9: Updated import statements to reflect the new type system.

The imports now correctly include ProcessedFile instead of ConvertedFile and add the new AudioOptions type. The naming convention is more consistent across all media types with ImageOptions and VideoOptions.


18-35: Well-implemented audio processing function with comprehensive documentation.

The new processAudio function follows the same pattern as the other media processing functions, ensuring a consistent API. The JSDoc comments clearly explain the purpose, parameters, and return values of the function.


37-54: Renamed and updated image processing function with improved documentation.

The function has been renamed from optimizeImage to processImage for consistency with other media types. The parameter types have been simplified to only accept AsyncIterable<Uint8Array> | Blob, and comprehensive JSDoc comments have been added.


56-73: Renamed and updated video processing function with improved documentation.

The function has been renamed from optimizeVideo to processVideo for consistency with other media types. The parameter types have been simplified to only accept AsyncIterable<Uint8Array> | Blob, and comprehensive JSDoc comments have been added.


75-79: Simplified the input parameter type for the optimizeFetch function.

The input parameter type has been updated to match the simplified types used in the processing functions.


80-86: Improved request construction in optimizeFetch function.

The code for creating and sending the HTTP request is cleaner and more readable.


96-100: Updated to use ProcessedFile instead of ConvertedFile.

The code now yields instances of ProcessedFile instead of ConvertedFile, aligning with the updated type system.

@sv2dev sv2dev merged commit bac741b into main Mar 23, 2025
2 checks passed
@sv2dev sv2dev deleted the unify-api branch March 23, 2025 19:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant