Skip to content

🍈 A simple MacOS Apple Silicon media converter.

License

Notifications You must be signed in to change notification settings

honeymelon-app/honeymelon

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

227 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Honeymelon 🍈 | App

A professional media converter built for macOS Apple Silicon.
Remux-first, privacy-minded, and tuned for post-production workflows.

License: GPL-3.0-or-later macOS 13+ Apple Silicon Native PRs Welcome


Table of Contents


Overview

Honeymelon is a native macOS desktop application that provides an intelligent interface for FFmpeg-powered media conversion. Built exclusively for Apple Silicon, it emphasizes lossless stream copying (remuxing) over re-encoding whenever possible, delivering faster conversions with zero quality loss.

Core Philosophy:

  • Remux-first: Automatically detects when lossless stream copying is possible
  • Privacy by design: All processing happens locallyβ€”no network access, no telemetry
  • Performance-optimized: Leverages Apple VideoToolbox hardware acceleration
  • Production-ready: Manages concurrent jobs, preserves color metadata, handles subtitle formats

Technology Stack:

  • Frontend: Vue 3 (Composition API) + TypeScript + Pinia + Tailwind CSS + shadcn-vue
  • Backend: Tauri 2.x + Rust + FFmpeg (out-of-process, LGPL-compliant)
  • Platform: macOS 13+ on Apple Silicon (M1/M2/M3/M4)

Key Features

Intelligent Conversion Engine

  • Remux-first strategy: Automatically detects codec compatibility and uses lossless stream copying when possible
  • Smart planning: Three-phase pipeline (Probe > Plan > Execute) ensures optimal conversion strategy
  • Container-aware: Validates codec compatibility with target containers (MP4, MKV, WebM, MOV, AVI, FLV, TS, OGV, MPEG)
  • Quality tiers: Fast (remux-priority), Balanced (quality/size), High (maximum quality)

Professional Media Handling

  • Color metadata preservation: Copies color primaries, transfer characteristics, and colorspace during transcoding
  • Subtitle support: Text subtitle conversion (mov_text for MP4), image subtitle detection
  • Hardware acceleration: Leverages Apple VideoToolbox for H.264, HEVC, and ProRes encoding
  • Multi-format support: Video (MP4, MKV, MOV, WebM, GIF, AVI, FLV, M4V, TS, OGV, MPEG), Audio (M4A, MP3, FLAC, WAV, OGG, AAC, AIFF, Opus), Image (PNG, JPEG, WebP, BMP, TIFF)

Production-Ready Workflow

  • Concurrent job management: Configurable parallel processing with intelligent concurrency limits
  • Exclusive codec handling: Heavy codecs (AV1, ProRes) run exclusively to prevent resource exhaustion
  • Real-time progress: Live FPS, encoding speed, ETA calculations with circular log buffers
  • Atomic operations: Temp file strategy ensures safe output with automatic cleanup on failure
  • macOS notifications: Desktop alerts on job completion or failure
  • Apple Silicon native: Bundle metadata blocks Rosetta fallback, keeps Retina UI crisp, and predeclares camera/mic usage for notarization readiness

Privacy & Security

  • 100% local processing: All conversions happen on-device with no network access
  • No telemetry: Zero data collection or external communication
  • Command injection protection: Security-first validation of all FFmpeg arguments
  • Full Disk Access support: Optional permission for protected directory access

System Requirements

Requirement Minimum Recommended
Operating system macOS 13 (Ventura) macOS 14 (Sonoma) or newer
Hardware Apple Silicon (M1/M2/M3/M4) M2 Pro/Max for heavy 4K+ workloads
Memory 4β€―GB 16β€―GB for concurrent 4K conversions
Disk space 50β€―MB app + headroom for outputs β‰₯β€―500β€―MB free for temporary files
Network Not required for day-to-day use Optional for future update channels

Note: Honeymelon is compiled exclusively for Apple Silicon (ARM64 architecture). Intel-based Macs are not supported.


Quick Start

Installation

  1. Download the latest signed DMG from the Releases page
  2. Drag Honeymelon.app into /Applications
  3. On first launch, macOS Gatekeeper may prompt you to confirm the developerβ€”choose Open
  4. (Optional) Grant Full Disk Access in System Settings for access to protected directories

Note: For air-gapped deployments, distribute the DMG and bundled FFmpeg binaries internallyβ€”no activation or online checks are required.

Development Setup

# 1. Clone and install dependencies
git clone https://github.com/honeymelon-app/honeymelon.git
cd honeymelon
npm install

# 2. Download FFmpeg binaries (Apple Silicon arm64)
npm run download-ffmpeg

# 3. Launch development app with hot reload
npm run tauri dev

# 4. Or run frontend only (no FFmpeg access)
npm run dev

How It Works

Honeymelon uses a three-stage conversion pipeline that intelligently decides between lossless stream copying and transcoding.

Stage 1: Probe

Extract comprehensive metadata from input files

  • Backend: Executes ffprobe with JSON output (-print_format json -show_format -show_streams)
  • Parsing: Normalizes codec names, handles multiple frame rate formats, categorizes subtitle types
  • Output: ProbeSummary with duration, dimensions, codecs, color metadata (bt709, bt2020, etc.), subtitle flags

Implementation: ffmpeg-probe.ts (frontend) + ffmpeg_probe.rs (backend, 933 lines)

Binary Resolution (4-tier fallback):

  1. $HONEYMELON_FFPROBE_PATH environment variable
  2. Development bundle: src-tauri/bin/ffprobe
  3. Application bundle resource directory
  4. System PATH

Stage 2: Plan

Determine optimal conversion strategy (copy vs. transcode)

  • Decision Logic: Matches source codec against target preset codecβ€”if identical, uses stream copy; otherwise transcodes
  • Container Rules: Validates codec compatibility (e.g., MP4 only supports H.264/HEVC/AV1 video, AAC/ALAC audio)
  • Quality Tiers: Fast (remux-priority), Balanced (moderate bitrate), High (low CRF/high bitrate)
  • Special Handling: GIF palette generation, color metadata copying, subtitle format conversion

Implementation: ffmpeg-plan.ts + container-rules.ts + presets.ts (420 lines)

Decision Matrix:

  • Full Remux: All streams copied (remuxOnly = true) > fastest, lossless
  • Partial Transcode: Some streams copied, others re-encoded
  • Full Transcode: All streams require encoding > applies tier-specific settings

Output: PlannerDecision with complete FFmpeg arguments array, remux flag, human-readable notes, warnings

Stage 3: Execute

Spawn FFmpeg process with real-time progress tracking

  • Concurrency Control: Atomic validation with configurable limits (default: 2 concurrent jobs)
  • Exclusive Mode: Heavy codecs (AV1, ProRes) block other jobs to prevent resource exhaustion
  • Temp File Strategy: Writes to <output>.tmp, atomically renames on success, auto-cleanup on failure
  • Progress Parsing: Background thread parses stderr for time/fps/speed metrics, emits Tauri events
  • Security: Command injection prevention validates all arguments before spawning

Implementation: runner modules under src-tauri/src/runner/ (e.g. mod.rs, process_spawner.rs, progress_monitor.rs, output_manager.rs, validator.rs, concurrency.rs) + the frontend orchestration stack (src/composables/use-job-orchestrator.ts, src/composables/orchestrator/planner-client.ts, src/composables/orchestrator/runner-client.ts, src/composables/orchestrator/event-subscriber.ts, src/composables/use-capability-gate.ts, src/composables/use-desktop-bridge.ts)

Event System:

  • ffmpeg://progress > Real-time metrics (processed seconds, FPS, encoding speed)
  • ffmpeg://stderr > Raw FFmpeg output for debugging
  • ffmpeg://completion > Final status with success/failure/cancellation flag

Circular Log Buffer: Last 500 lines retained per job, prevents unbounded memory growth


Architecture

Technology Stack

Layer Technology Purpose
Frontend Vue 3 (Composition API) + TypeScript UI components, business logic
Pinia State management (jobs, preferences)
shadcn-vue + Tailwind CSS UI components and styling
Vite 6.x Build tooling and dev server
Backend Tauri 2.x + Rust (2021 edition) Native integration, FFmpeg orchestration
Tokio async runtime Process management and IPC
Serde + JSON Type-safe serialization
Media FFmpeg/FFprobe (out-of-process) Media probing and conversion
Apple VideoToolbox Hardware acceleration (H.264/HEVC/ProRes)

Project Structure

Key Directories:

src/
β”œβ”€β”€ lib/                    # Core business logic
β”‚   β”œβ”€β”€ ffmpeg-plan.ts      # Planning engine
β”‚   β”œβ”€β”€ ffmpeg-probe.ts     # Probe wrapper
β”‚   β”œβ”€β”€ container-rules.ts  # Codec compatibility rules
β”‚   β”œβ”€β”€ presets.ts          # Dynamic preset generation (420 lines)
β”‚   β”œβ”€β”€ media-formats.ts    # Video/audio/image container definitions
β”‚   β”œβ”€β”€ job-lifecycle.ts    # Shared lifecycle chart + DEV assertions
β”‚   └── types.ts            # TypeScript definitions
β”œβ”€β”€ stores/                 # Pinia state
β”‚   β”œβ”€β”€ job-queue.ts        # Job queue operations (enqueue/start/peek)
β”‚   β”œβ”€β”€ job-state.ts        # Job state transitions (probing/planning/running)
β”‚   β”œβ”€β”€ job-progress.ts     # Progress tracking utilities
β”‚   β”œβ”€β”€ job-logs.ts         # Circular job log buffer
β”‚   └── prefs.ts            # User preferences
β”œβ”€β”€ services/               # Shared service layer
β”‚   └── job-service.ts      # Repository proxy with duplicate detection
β”œβ”€β”€ composables/            # Vue composables
β”‚   β”œβ”€β”€ use-app-orchestration.ts # Queue/start/cancel coordination
β”‚   β”œβ”€β”€ use-capability-gate.ts  # Capability gating + preset readiness
β”‚   β”œβ”€β”€ use-desktop-bridge.ts   # Drag/drop and menu wiring
β”‚   β”œβ”€β”€ use-job-orchestrator.ts # Coordinates planner/runner clients
β”‚   └── orchestrator/
β”‚       β”œβ”€β”€ event-subscriber.ts # Centralized event lifecycle management
β”‚       β”œβ”€β”€ planner-client.ts   # Frontend bridge to planner commands
β”‚       └── runner-client.ts    # Frontend bridge to runner commands
└── components/             # Vue UI components

src-tauri/
β”œβ”€β”€ Info.plist              # Bundle overrides (arm64-only, Retina, privacy usage descriptions)
β”œβ”€β”€ bin/                    # Bundled FFmpeg sidecars (arm64 builds)
└── src/
    β”œβ”€β”€ runner/             # FFmpeg process orchestration split into focused modules
    β”‚   β”œβ”€β”€ mod.rs
    β”‚   β”œβ”€β”€ process_spawner.rs
    β”‚   β”œβ”€β”€ progress_monitor.rs
    β”‚   β”œβ”€β”€ output_manager.rs
    β”‚   β”œβ”€β”€ validator.rs
    β”‚   └── concurrency.rs
    β”œβ”€β”€ ffmpeg_probe.rs     # Media probing
    β”œβ”€β”€ ffmpeg_capabilities.rs  # Capability detection
    β”œβ”€β”€ fs_utils.rs         # File discovery
    └── error.rs            # Unified error handling

Documentation:

Core Principles

  1. LGPL Compliance: FFmpeg runs as separate processβ€”no static/dynamic linking, communication via stdin/stdout/files only
  2. Type-Safe State Machine: Discriminated union types for job states prevent invalid transitions
  3. Event-Driven Progress: Tauri events stream FFmpeg output asynchronously, non-blocking UI updates
  4. Atomic Operations: Temp file writes + atomic renames ensure data integrity
  5. Security First: Command injection validation, path sanitization, permission checks

Usage

Basic Workflow

  1. Add Files: Drag-and-drop files/folders or click "Choose Files"
  2. Select Preset: Auto-selected based on file type, or choose from dropdown
  3. Choose Quality Tier:
    • Fast: Remux-priority (lossless copy when possible)
    • Balanced: Moderate bitrate for good quality/size ratio
    • High: Maximum quality (low CRF, high bitrate)
  4. Monitor Progress: Real-time progress bar, FPS, encoding speed, ETA
  5. Access Output: Default location same as source, or configure custom output directory

Keyboard Shortcuts

Shortcut Action
Cmd+, Open Preferences
Cmd+O Open file picker
Cmd+Q Quit Application
Cmd+W Close Window
Cmd+M Minimize Window

Configuration

Access: Cmd+, or menu: Honeymelon > Preferences

Settings:

  • Concurrent Jobs: 1-∞ (default: 2, recommended 2-4 based on Mac model)
  • Output Directory: Choose custom location or use source directory
  • FFmpeg Path: Auto-detected or specify custom binary
  • Filename Options: Include preset/tier in output filenames, configure separator

Environment Variables:

  • HONEYMELON_FFMPEG_PATH – Override FFmpeg binary path
  • RUST_LOG=debug – Enable Rust logging for development

Development

Build Commands

Command Purpose
npm install Install dependencies
npm run tauri dev Run full app with hot reload (recommended)
npm run dev Run frontend only (no FFmpeg)
npm run build Build frontend assets
npm run tauri build Build production DMG
npm run lint Lint TypeScript + Rust
npm run format Format all code
npm run type-check Validate TypeScript
npm run test:unit Run Vitest suites for planners/runners/jobs
npm test Run all tests
cd src-tauri && cargo test Run Rust tests
cd src-tauri && cargo clippy Lint Rust code

Code Style

TypeScript/Vue:

  • Strict mode, explicit types, no any
  • Use <script setup> (Composition API)
  • 2-space indentation, single quotes
  • File naming: kebab-case for libs, PascalCase for components

Rust:

  • Idiomatic Rust with Result<T, E> error handling
  • Async/await for I/O operations
  • 4-space indentation, snake_case modules
  • Document public APIs with ///

General:

  • Discriminated unions for state machines
  • Immutability by default (const over let)
  • Extract reusable logic into composables/helper functions
  • Keep functions focused (<100 lines ideal)

Testing

Stack

  • Frontend: Vitest powers unit suites for ffmpeg-plan, planner/runner clients, repositories, and composables
  • Backend: cargo test exercises probe parsing, runner validator/concurrency, filesystem helpers, and the mirrored Rust JobLifecycle
  • Integration: Playwright drives drag/drop, preset selection, licensing, and exclusive-job workflows
  • Coverage: npm run test:unit:coverage emits V8 coverage for the TypeScript surface area

Coverage highlights

  • src/services/job-service.ts and repository helpers guard duplicate detection, timestamp patching, and transactional writes
  • src/lib/job-lifecycle.ts enforces legal transitions in Pinia stores while matching the Rust backend state chart
  • src/composables/orchestrator/*.ts suites rely on a shared teardown helper, ensuring mocked Tauri listeners are cleaned after each run
  • Planner tests assert tier fallbacks, warning propagation, and capability filtering for video-optional inputs; runner tests cover exclusive job fan-out and cleanup paths
  • use-file-handler specs verify browser vs. Tauri file acquisition, preset readiness fallbacks, and mixed-media filtering

Running tests locally

  1. npm run download-ffmpeg – fetch Apple Silicon FFmpeg sidecars used by planner/orchestrator specs (alternatively set HONEYMELON_FFMPEG_PATH to your own build)
  2. npm run test:unit – execute Vitest suites headlessly; use npm run test:unit:watch for rapid cycles
  3. cd src-tauri && cargo test – run backend unit and integration tests
  4. npm run test:e2e – launch Playwright against the Tauri shell (requires npm run tauri dev in another terminal)
  5. Optional: npm run test:unit:coverage for per-file coverage gating

Continuous Integration

  • ci.yml installs FFmpeg via npm run download-ffmpeg, runs ESLint/Clippy, enforces Markdown lint + format checks, executes npm run type-check, npm run test:unit, npm run build, and finishes with cargo test
  • release.yml mirrors those gates (lint > type-check > unit tests > coverage > build) before packaging artifacts, preventing regressions from skipping CI
  • Both workflows cache npm/cargo artifacts for speed and fail fast when Vitest coverage or Markdown formatting drifts from the expected state

Release Process

  1. Bump versions in package.json, src-tauri/Cargo.toml, src-tauri/tauri.conf.json
  2. Update CHANGELOG.md with release notes
  3. Run full QA: npm run lint && npm test && npm run build && cd src-tauri && cargo test
  4. Confirm bundled binaries are Apple Silicon only: file src-tauri/bin/ffmpeg src-tauri/bin/ffprobe (expect arm64)
  5. Configure code signing environment variables (APPLE_ID, APPLE_PASSWORD, APPLE_TEAM_ID)
  6. Build signed bundle: npm run tauri build
  7. Verify signature: codesign -vvv --deep --strict <app> and spctl -a -vvv -t install <app>
  8. Generate SHA256 checksum for DMG
  9. Create GitHub Release with DMG, changelog, and checksum
  10. Smoke test on clean machine

Output: src-tauri/target/aarch64-apple-darwin/release/bundle/dmg/Honeymelon_*.dmg


Legal & Licensing

Open Source Software

Honeymelon is free and open-source software licensed under the GNU General Public License version 3.0 or later (GPL-3.0-or-later).

This means you are free to:

  • Use Honeymelon for any purpose
  • Study how it works and modify it
  • Share copies with others
  • Distribute modified versions

Under the conditions that:

  • You provide the source code when distributing
  • You license your modifications under GPL-3.0-or-later
  • You preserve copyright and license notices

For the complete license text, see LICENSE.

FFmpeg Licensing

License: LGPL v2.1 or later

Compliance Method: Process Separation

  • Honeymelon executes FFmpeg as a completely separate process (no shared memory, no library calls)
  • No static linking to FFmpeg libraries (.a files)
  • No dynamic linking to FFmpeg libraries (.so/.dylib files)
  • Communication exclusively via:
    • Command-line arguments
    • Standard input/output/error streams
    • File system (input files, output files)
  • This approach satisfies LGPL requirements and is compatible with GPL-3.0-or-later

Implications:

  • FFmpeg's LGPL license is compatible with Honeymelon's GPL-3.0-or-later license
  • Process separation ensures compliance without restrictions
  • Must include FFmpeg license file with distribution
  • Must provide information on obtaining FFmpeg source code
  • Honeymelon does not modify FFmpeg

See LICENSES/FFMPEG-LGPL.txt for complete license text.

FFmpeg Installation & Sources:

For trusted FFmpeg installation methods and binary verification:

  1. Homebrew (recommended): brew install ffmpeg
  2. Official builds: https://evermeet.cx/ffmpeg/
  3. Build from source: https://github.com/FFmpeg/FFmpeg

See docs/FFMPEG_SOURCES.md for detailed information about:

  • Recommended installation methods
  • Binary verification and checksums
  • Building from source
  • Security considerations
  • Distribution requirements

Patent Considerations

Certain audio and video codecs may be subject to patent claims in various jurisdictions:

H.264/HEVC (H.265):

  • Patent pools managed by MPEG LA and HEVC Advance
  • When using hardware encoders (VideoToolbox), Apple handles patent licensing
  • Software encoders (libx264, libx265) may require separate licensing in some jurisdictions
  • Recommendation: Use system-provided hardware encoders when possible

AAC:

  • Patent pool managed by Via Licensing
  • Provided by system codecs when using hardware acceleration
  • Covered by Apple's licensing for system-provided encoders

VP9/AV1/Opus:

  • Royalty-free codecs without patent licensing requirements
  • Open-source encoder libraries (libvpx, libaom, libopus)
  • No additional licensing needed

User Responsibility: Users who compile custom FFmpeg builds with software encoders (x264, x265, fdk-aac) are responsible for ensuring proper patent licensing in their jurisdiction.

Third-Party Software

All third-party dependencies are documented with proper attribution:

License Documentation:

Key Dependencies (all used in compliance with their respective licenses):

  • Tauri: MIT/Apache-2.0 dual license
  • Vue.js: MIT license
  • Rust ecosystem: Primarily MIT/Apache-2.0 dual licensed crates
  • shadcn-vue: MIT license
  • Tailwind CSS: MIT license
  • FFmpeg: LGPL v2.1+ (process-separated, not linked)

Distribution Requirements

When distributing Honeymelon under GPL-3.0-or-later, the following must be included:

  1. LICENSE file (GNU GPLv3 license)
  2. LICENSES/FFMPEG-LGPL.txt (FFmpeg LGPL license)
  3. THIRD_PARTY_NOTICES.md (all dependency attributions)
  4. Source code or clear instructions for obtaining it
  5. Link to FFmpeg source code: https://ffmpeg.org/download.html

Source code is available at: https://github.com/honeymelon-app/honeymelon


Troubleshooting

Common Issues

Issue Solution
Conversion fails immediately Check FFmpeg: which ffmpeg && ffmpeg -version. Verify encoder support: ffmpeg -encoders | grep <name>. Check Console.app logs (filter: "Honeymelon")
Progress stuck at 0% Input lacks duration metadata. Conversion continues normally, but ETA unavailable. Common with streaming formats.
Image subtitles in MP4 MP4 doesn't support PGS/VOBSUB. Use burn-in (hardcoded) or output to MKV. Text subs auto-convert to mov_text.
Output file missing Temp rename failed. Check for .tmp file. Ensure sufficient disk space and write permissions.
Choppy HEVC playback Use H.264 preset for broader compatibility. Reduce quality tier from High to Balanced.
Large GIF files Keep clips <10s. Resolution auto-limited to 640px width. Consider WebM for better compression.
FFmpeg not found Install: brew install ffmpeg, or specify custom path in Preferences, or bundle with app.
Permission denied Grant Full Disk Access: System Settings > Privacy & Security > Full Disk Access > Add Honeymelon.app
Slow AV1/ProRes encoding Expected: AV1 (0.05-0.5x realtime), ProRes (0.5-2x). Exclusive mode prevents concurrent slow jobs.

Performance Tips

Speed:

  • Use Fast tier (remux-priority)
  • Match source/target codecs (enables stream copy)
  • Increase concurrent jobs if CPU/RAM available
  • Use MKV (accepts any codec > more remux opportunities)

Memory:

  • Decrease concurrent jobs to 1-2
  • Process files sequentially
  • Clear completed jobs regularly

Getting Help

Before Reporting:

  1. Check troubleshooting above
  2. Review GitHub Discussions
  3. Verify: ffmpeg -version and ffmpeg -encoders
  4. Check Console.app (filter: "Honeymelon")

Bug Reports: GitHub Issues with macOS version, chip type, Honeymelon version, file details, FFmpeg version, logs

Feature Requests: GitHub Issues with use case, expected behavior, examples


Contributing

Contributions welcome! See CONTRIBUTING.md for:

  • Code of conduct
  • Development setup
  • Coding standards (TypeScript strict mode, Vue <script setup>, Rust idioms)
  • Commit format (Conventional Commits)
  • PR workflow

Priorities:

  • High: Concurrency management, error handling, performance optimizations
  • Medium: New presets, UI/UX refinements, testing infrastructure
  • Future: Subtitle burn-in, multi-track selection, video trimming

See AGENTS.md for commit conventions.


Acknowledgements

Built with gratitude for:

  • FFmpeg Team – Comprehensive media processing
  • Tauri Team – Modern desktop framework
  • Vue.js Team – Reactive UI framework
  • Rust Community – Safe systems programming
  • shadcn Community – Accessible UI components
  • All Contributors – Code, docs, bug reports, suggestions

License

Honeymelon: Licensed under GNU General Public License v3.0 or later (GPL-3.0-or-later). Copyright Β© 2025 Jerome Thayananthajothy. See LICENSE.

FFmpeg: LGPL v2.1+. Process-separated (no linking). See LICENSES/FFMPEG-LGPL.txt.

Dependencies: See THIRD_PARTY_NOTICES.md for full attributions.

Licensing inquiries: tjthavarshan@gmail.com