Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
blank_issues_enabled: false
contact_links:
- name: 🛟 Support
url: https://github.com/linuxmatters/jivedrop/blob/HEAD/SUPPORT.md
url: https://github.com/linuxmatters/jive-encoder/blob/HEAD/SUPPORT.md
about: Check the support guide before opening an issue.
# - name: Code of Conduct Report
# url: https://yourproject.org/community-report/
Expand Down
Binary file added .github/jive-encoder.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed .github/jivedrop.gif
Binary file not shown.
22 changes: 11 additions & 11 deletions .github/workflows/builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -212,15 +212,15 @@ jobs:
run: |
VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo "dev")
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Building jivedrop $VERSION for ${{ matrix.os }}/${{ matrix.arch }}"
echo "Building jive-encoder $VERSION for ${{ matrix.os }}/${{ matrix.arch }}"
- name: Build binary
run: |
go build -ldflags="-X main.version=${{ steps.version.outputs.version }}" -o jivedrop-${{ matrix.os }}-${{ matrix.arch }} ./cmd/jivedrop
go build -ldflags="-X main.version=${{ steps.version.outputs.version }}" -o jive-encoder-${{ matrix.os }}-${{ matrix.arch }} ./cmd/jive-encoder
- name: Upload artifact
uses: actions/upload-artifact@v7
with:
name: jivedrop-${{ matrix.os }}-${{ matrix.arch }}
path: jivedrop-${{ matrix.os }}-${{ matrix.arch }}
name: jive-encoder-${{ matrix.os }}-${{ matrix.arch }}
path: jive-encoder-${{ matrix.os }}-${{ matrix.arch }}

release:
name: Release 📦
Expand Down Expand Up @@ -257,12 +257,12 @@ jobs:

```bash
# Linux (amd64)
chmod +x jivedrop-linux-amd64
sudo mv jivedrop-linux-amd64 /usr/local/bin/jivedrop
chmod +x jive-encoder-linux-amd64
sudo mv jive-encoder-linux-amd64 /usr/local/bin/jive-encoder

# macOS (Apple Silicon)
chmod +x jivedrop-darwin-arm64
sudo mv jivedrop-darwin-arm64 /usr/local/bin/jivedrop
chmod +x jive-encoder-darwin-arm64
sudo mv jive-encoder-darwin-arm64 /usr/local/bin/jive-encoder
```

## Checksums
Expand All @@ -275,16 +275,16 @@ jobs:
uses: actions/download-artifact@v8
with:
path: artifacts
pattern: jivedrop-*
pattern: jive-encoder-*
merge-multiple: false
- name: Create release
uses: softprops/action-gh-release@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.version.outputs.version }}
name: Jivedrop ${{ steps.version.outputs.version }}
name: Jive Encoder ${{ steps.version.outputs.version }}
body_path: CHANGELOG.md
draft: false
prerelease: false
files: artifacts/jivedrop-*/jivedrop-*
files: artifacts/jive-encoder-*/jive-encoder-*
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.direnv
/jivedrop
/jive-encoder
testdata/
*.mp3
*.opus
Expand Down
2 changes: 2 additions & 0 deletions .harper-dictionary.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Jivedrop
jive-encoder
8 changes: 4 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ just clean # Remove build artifacts and test outputs (*.mp3)
## Architecture

```
cmd/jivedrop/
cmd/jive-encoder/
main.go # CLI entry, mode detection (Hugo vs Standalone), argument validation
workflow.go # Workflow interface + CLIOptions struct passed to each workflow
hugo.go # Hugo-mode workflow (frontmatter-driven)
Expand All @@ -52,16 +52,16 @@ third_party/ffmpeg-statigo/ # Git submodule: FFmpeg 8.1 static bindings

### Dual-Mode CLI

- **Hugo mode**: `jivedrop audio.flac episode.md`: reads metadata from Hugo frontmatter
- **Standalone mode**: `jivedrop audio.flac --title X --num N --cover Y`: explicit flags
- **Hugo mode**: `jive-encoder audio.flac episode.md`: reads metadata from Hugo frontmatter
- **Standalone mode**: `jive-encoder audio.flac --title X --num N --cover Y`: explicit flags
- Mode detection: second argument ending in `.md` triggers Hugo mode
- `--format mp3|opus|aac` selects one format per invocation (single value, default `mp3`); Kong rejects unknown values at parse time. Each invocation emits one file with the preset extension

### Hugo Frontmatter

- Required fields in episode markdown: `episode`, `title`, `episode_image`
- `episode` must be a non-empty, non-negative integer (validated by `encoder.ParseEpisodeNumber`); same rule applies to the standalone `--num` flag
- After encoding, Jivedrop calculates `podcast_duration` and `podcast_bytes`
- After encoding, Jive Encoder calculates `podcast_duration` and `podcast_bytes`
- Write-back is format-agnostic: the stats reflect the single encoded file, whatever format was chosen
- Prompts user to update frontmatter if values differ or are missing

Expand Down
32 changes: 17 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# Jivedrop 🪩
# Jive Encoder 🪩

*Formerly known as Jivedrop.*

> Drop your podcast .wav into a shiny MP3, AAC, or Opus with metadata, cover art, and all

## The Groove

Jivedrop takes your mixed podcast audio (WAV/FLAC) and outputs RSS-ready podcast files with optimised encoding, embedded artwork, and complete metadata. Choose MP3 for universal compatibility, AAC for Apple-recommended quality, or Opus for modern Android and web delivery. One command, distribution-ready output.
Jive Encoder takes your mixed podcast audio (WAV/FLAC) and outputs RSS-ready podcast files with optimised encoding, embedded artwork, and complete metadata. Choose MP3 for universal compatibility, AAC for Apple-recommended quality, or Opus for modern Android and web delivery. One command, distribution-ready output.

### Example Output

<div align="center"><img alt="Jivedrop Demo" src=".github/jivedrop.gif" width="600" /></div>
<div align="center"><img alt="Jive Encoder Demo" src=".github/jive-encoder.gif" width="600" /></div>

### What's Cooking

Expand All @@ -33,7 +35,7 @@ Jivedrop takes your mixed podcast audio (WAV/FLAC) and outputs RSS-ready podcast

### Hugo Mode (Integrated Workflow)

For podcasts using Hugo static site generator and the something like [Castanet](https://github.com/mattstratton/castanet), Jivedrop reads metadata from episode markdown:
For podcasts using Hugo static site generator and the something like [Castanet](https://github.com/mattstratton/castanet), Jive Encoder reads metadata from episode markdown:

**Hugo mode automatically:**
- Reads episode title and number from frontmatter
Expand All @@ -44,13 +46,13 @@ For podcasts using Hugo static site generator and the something like [Castanet](

```bash
# Basic encoding (MP3 by default)
jivedrop LMP67.flac episode/67.md
jive-encoder LMP67.flac episode/67.md

# Encode as AAC for Apple-recommended distribution
jivedrop LMP67.flac episode/67.md --format aac
jive-encoder LMP67.flac episode/67.md --format aac

# Override Hugo defaults
jivedrop LMP67.flac episode/67.md --artist "Ubuntu Podcast" --comment "https://ubuntupodcast.org"
jive-encoder LMP67.flac episode/67.md --artist "Ubuntu Podcast" --comment "https://ubuntupodcast.org"
```
### Standalone Mode (Universal Workflow)

Expand All @@ -64,20 +66,20 @@ For podcasts without Hugo, specify metadata via flags:

```bash
# Minimal (title, episode number, and cover art required)
jivedrop audio.flac \
jive-encoder audio.flac \
--title "Terminal Full of Sparkles" \
--num 66 \
--cover artwork.png

# Encode as Opus (note: Opus is not accepted by Apple Podcasts)
jivedrop audio.flac \
jive-encoder audio.flac \
--title "Terminal Full of Sparkles" \
--num 66 \
--cover artwork.png \
--format opus

# Full metadata
jivedrop audio.flac \
jive-encoder audio.flac \
--title "Terminal Full of Sparkles" \
--num 66 \
--artist "Linux Matters" \
Expand All @@ -93,9 +95,9 @@ jivedrop audio.flac \
```
Usage:
Hugo mode:
jivedrop <audio-file> <episode-md> [flags]
jive-encoder <audio-file> <episode-md> [flags]
Standalone mode:
jivedrop <audio-file> --title TEXT --num NUMBER --cover PATH [flags]
jive-encoder <audio-file> --title TEXT --num NUMBER --cover PATH [flags]


Arguments:
Expand Down Expand Up @@ -155,7 +157,7 @@ Same text fields as MP3. Cover art is not embedded in Opus files.

## Build

Jivedrop uses [ffmpeg-statigo](https://github.com/linuxmatters/ffmpeg-statigo) for FFmpeg static bindings.
Jive Encoder uses [ffmpeg-statigo](https://github.com/linuxmatters/ffmpeg-statigo) for FFmpeg static bindings.

```bash
# Setup or update ffmpeg-statigo submodule and library
Expand All @@ -167,8 +169,8 @@ just test # Run tests
just test-encoder # Test encoder
```

## Why Jivedrop?
## Why Jive Encoder?

FFmpeg's CLI can absolutely encode podcast-ready audio with metadata. But getting the incantation right for CBR encoding, mono downmix, format-native tags, embedded artwork, and correct lowpass filtering requires a sprawling command line you'll never remember. Switch from MP3 to AAC and every option changes. Add Hugo frontmatter parsing on top and you're writing a script.

Jivedrop wraps the fiddly bits into a single binary that speaks Hugo natively. Drop your WAV, point at your episode markdown, pick your format, and get distribution-ready output with duration and byte counts ready to paste back into your frontmatter.
Jive Encoder wraps the fiddly bits into a single binary that speaks Hugo natively. Drop your WAV, point at your episode markdown, pick your format, and get distribution-ready output with duration and byte counts ready to paste back into your frontmatter.
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Only the latest release is supported. Security fixes are released as patch versi

**Do not open a public issue for security vulnerabilities.**

[Report vulnerabilities privately](https://github.com/linuxmatters/jivedrop/security/advisories/new). Include:
[Report vulnerabilities privately](https://github.com/linuxmatters/jive-encoder/security/advisories/new). Include:

- Steps to reproduce
- Affected versions
Expand Down
6 changes: 3 additions & 3 deletions cmd/jivedrop/hugo.go → cmd/jive-encoder/hugo.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"os"
"strings"

"github.com/linuxmatters/jivedrop/internal/cli"
"github.com/linuxmatters/jivedrop/internal/encoder"
"github.com/linuxmatters/jivedrop/internal/id3"
"github.com/linuxmatters/jive-encoder/internal/cli"
"github.com/linuxmatters/jive-encoder/internal/encoder"
"github.com/linuxmatters/jive-encoder/internal/id3"
)

// Hugo mode metadata defaults for the Linux Matters podcast.
Expand Down
File renamed without changes.
10 changes: 5 additions & 5 deletions cmd/jivedrop/main.go → cmd/jive-encoder/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import (
tea "charm.land/bubbletea/v2"
"github.com/alecthomas/kong"
"github.com/charmbracelet/x/term"
"github.com/linuxmatters/jivedrop/internal/cli"
"github.com/linuxmatters/jivedrop/internal/encoder"
"github.com/linuxmatters/jivedrop/internal/id3"
"github.com/linuxmatters/jivedrop/internal/ui"
"github.com/linuxmatters/jive-encoder/internal/cli"
"github.com/linuxmatters/jive-encoder/internal/encoder"
"github.com/linuxmatters/jive-encoder/internal/id3"
"github.com/linuxmatters/jive-encoder/internal/ui"
)

// version is set via ldflags at build time: "dev" for local builds, the git
Expand Down Expand Up @@ -325,7 +325,7 @@ func main() {

func run() int {
ctx := kong.Parse(&CLI,
kong.Name("jivedrop"),
kong.Name("jive-encoder"),
kong.Description("Drop the mix, ship the show—metadata, cover art, and all."),
kong.Vars{"version": version},
kong.UsageOnError(),
Expand Down
6 changes: 3 additions & 3 deletions cmd/jivedrop/main_test.go → cmd/jive-encoder/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -705,21 +705,21 @@ func TestDetectMode_Integration(t *testing.T) {
audioFile: "LMP67.flac",
episodeMD: "content/episodes/67.md",
expected: HugoMode,
description: "User runs: jivedrop LMP67.flac content/episodes/67.md",
description: "User runs: jive-encoder LMP67.flac content/episodes/67.md",
},
{
name: "real standalone workflow",
audioFile: "podcast.wav",
episodeMD: "",
expected: StandaloneMode,
description: "User runs: jivedrop podcast.wav --title 'Ep 1' --num 1 --cover art.png",
description: "User runs: jive-encoder podcast.wav --title 'Ep 1' --num 1 --cover art.png",
},
{
name: "common mistake: user passes non-md file in hugo mode",
audioFile: "episode.flac",
episodeMD: "episode.txt",
expected: StandaloneMode,
description: "User runs: jivedrop episode.flac episode.txt (should be .md not .txt)",
description: "User runs: jive-encoder episode.flac episode.txt (should be .md not .txt)",
},
{
name: "edge: .md file with uppercase extension",
Expand Down
4 changes: 2 additions & 2 deletions cmd/jivedrop/standalone.go → cmd/jive-encoder/standalone.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import (
"fmt"
"os"

"github.com/linuxmatters/jivedrop/internal/encoder"
"github.com/linuxmatters/jivedrop/internal/id3"
"github.com/linuxmatters/jive-encoder/internal/encoder"
"github.com/linuxmatters/jive-encoder/internal/id3"
)

// StandaloneWorkflow implements the Workflow interface for standalone mode.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ func TestStandaloneWorkflowValidate_Integration(t *testing.T) {
num: "66",
cover: "artwork.png",
wantErr: false,
description: "User runs: jivedrop audio.flac --title 'Terminal Full of Sparkles' --num 66 --cover artwork.png",
description: "User runs: jive-encoder audio.flac --title 'Terminal Full of Sparkles' --num 66 --cover artwork.png",
},
{
name: "common mistake: forgot --title flag",
Expand Down
6 changes: 3 additions & 3 deletions cmd/jivedrop/workflow.go → cmd/jive-encoder/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package main
import (
"fmt"

"github.com/linuxmatters/jivedrop/internal/cli"
"github.com/linuxmatters/jivedrop/internal/encoder"
"github.com/linuxmatters/jivedrop/internal/id3"
"github.com/linuxmatters/jive-encoder/internal/cli"
"github.com/linuxmatters/jive-encoder/internal/encoder"
"github.com/linuxmatters/jive-encoder/internal/id3"
)

// Workflow defines the mode-specific operations for Hugo and Standalone workflows.
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module github.com/linuxmatters/jivedrop
module github.com/linuxmatters/jive-encoder

go 1.26

Expand Down
2 changes: 1 addition & 1 deletion internal/cli/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func StyledHelpPrinter(options kong.HelpOptions) kong.HelpPrinter {
var sb strings.Builder

// Title and description
sb.WriteString(TitleStyle.Render("Jivedrop 🪩"))
sb.WriteString(TitleStyle.Render("Jive Encoder 🪩"))
sb.WriteString("\n")
sb.WriteString(helpDescStyle.Render("Drop your podcast .wav into a shiny MP3, AAC, or Opus with metadata, cover art, and all."))
sb.WriteString("\n")
Expand Down
2 changes: 1 addition & 1 deletion internal/cli/styles.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ var (

// PrintVersion prints version information
func PrintVersion(version string) {
fmt.Println(TitleStyle.Render("Jivedrop 🪩"))
fmt.Println(TitleStyle.Render("Jive Encoder 🪩"))
fmt.Printf("%s %s\n", KeyStyle.Render("Version:"), ValueStyle.Render(version))
fmt.Println()
}
Expand Down
2 changes: 1 addition & 1 deletion internal/encoder/encoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"sync"
"testing"

"github.com/linuxmatters/jivedrop/internal/id3"
"github.com/linuxmatters/jive-encoder/internal/id3"
)

// TestNewFormatResolution verifies that New defaults an empty Format to the
Expand Down
2 changes: 1 addition & 1 deletion internal/ui/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"charm.land/bubbles/v2/progress"
tea "charm.land/bubbletea/v2"
"github.com/charmbracelet/harmonica"
"github.com/linuxmatters/jivedrop/internal/encoder"
"github.com/linuxmatters/jive-encoder/internal/encoder"
)

// ProgressUpdate represents a progress update from the encoder
Expand Down
2 changes: 1 addition & 1 deletion internal/ui/encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"testing"

tea "charm.land/bubbletea/v2"
"github.com/linuxmatters/jivedrop/internal/encoder"
"github.com/linuxmatters/jive-encoder/internal/encoder"
)

// newTestModel builds a minimal EncodeModel for exercising Update in isolation.
Expand Down
2 changes: 1 addition & 1 deletion internal/ui/styles.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package ui

import (
"charm.land/lipgloss/v2"
"github.com/linuxmatters/jivedrop/internal/cli"
"github.com/linuxmatters/jive-encoder/internal/cli"
)

// Import shared colour palette from cli package
Expand Down
2 changes: 1 addition & 1 deletion internal/ui/views.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"strings"

"charm.land/lipgloss/v2"
"github.com/linuxmatters/jivedrop/internal/encoder"
"github.com/linuxmatters/jive-encoder/internal/encoder"
)

// progressView renders the encoding progress UI
Expand Down
Loading