Skip to content
Merged
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
Binary file modified .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.
8 changes: 7 additions & 1 deletion .github/workflows/builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
env:
CGO_ENABLED: 1
steps:
- uses: actions/checkout@v7
with:
Expand Down Expand Up @@ -97,6 +99,8 @@ jobs:
runs-on: ${{ matrix.runner }}
permissions:
contents: read
env:
CGO_ENABLED: 1
steps:
- uses: actions/checkout@v7
with:
Expand Down Expand Up @@ -139,7 +143,7 @@ jobs:
comment-summary-in-pr: on-failure

- name: Run govulncheck
uses: golang/govulncheck-action@master
uses: golang/govulncheck-action@v1.0.4
with:
repo-checkout: false
go-version-file: go.mod
Expand Down Expand Up @@ -193,6 +197,8 @@ jobs:
runs-on: ${{ matrix.runner }}
permissions:
contents: read
env:
CGO_ENABLED: 1
steps:
- uses: actions/checkout@v7
with:
Expand Down
2 changes: 1 addition & 1 deletion .tailor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
license: GPL-3.0

repository:
description: Drop your podcast .wav into a shiny MP3, AAC or Opus with metadata, cover art, and all 🪩
description: Drop your podcast .wav into a shiny MP3, AAC or Opus with metadata, cover art, and all 🗜️
homepage: https://linuxmatters.sh
has_wiki: false
has_discussions: false
Expand Down
5 changes: 5 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ third_party/ffmpeg-statigo/ # Git submodule: FFmpeg 8.1 static bindings
- **Shell:** Fish (interactive), bash (scripts)
- **CGO required:** Set `CGO_ENABLED=1` for builds

## CI and Dependencies

- **Release checksums:** GitHub attaches SHA256 sums to all release artifacts automatically. Do not hand-roll a checksum step.
- **Dependabot Nix:** Dependabot supports the `nix` ecosystem and updates `flake.lock`. The entry in `.github/dependabot.yml` is expected.

## FFmpeg-Statigo Submodule

This project uses [`ffmpeg-statigo`](https://github.com/linuxmatters/ffmpeg-statigo) for FFmpeg 8.1 static bindings:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Jive Encoder 🪩
# Jive Encoder 🗜️

*Formerly known as Jivedrop.*

Expand Down
38 changes: 26 additions & 12 deletions cmd/jive-encoder/hugo.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"errors"
"fmt"
"os"
"strings"
Expand Down Expand Up @@ -28,7 +29,7 @@ type HugoWorkflow struct {
// Validate checks Hugo-specific arguments and file existence.
func (h *HugoWorkflow) Validate() error {
if h.opts.EpisodeMD == "" {
return fmt.Errorf("hugo mode requires episode markdown file as second argument")
return errors.New("hugo mode requires episode markdown file as second argument")
}

if !isMarkdownPath(h.opts.EpisodeMD) {
Expand Down Expand Up @@ -62,6 +63,9 @@ func (h *HugoWorkflow) CollectMetadata() (encoder.Metadata, string, error) {
episodeTitle := metadata.Title
artist := HugoDefaultArtist
comment := HugoDefaultComment
// Frontmatter supplies a parsed time.Time, so format it to the muxer's
// YYYY-MM tag string. Standalone mode instead passes --date through raw
// (see standalone.go), because there the user types the exact tag value.
date := encoder.FormatDateForID3(metadata.Date)

if h.opts.Artist != "" {
Expand Down Expand Up @@ -112,6 +116,12 @@ func (h *HugoWorkflow) CollectMetadata() (encoder.Metadata, string, error) {
// new podcast_duration/podcast_bytes and waits for confirmation before writing, so a non-mp3
// encode cannot silently overwrite values for a different enclosure.
func (h *HugoWorkflow) PostEncode(stats *encoder.FileStats) error {
// hugoMetadata is populated by CollectMetadata; guard the implicit ordering
// so an out-of-order call returns an error instead of a nil-deref panic.
if h.hugoMetadata == nil {
return errors.New("PostEncode called before CollectMetadata")
}

printPodcastStats(stats)

needsUpdate := false
Expand All @@ -129,29 +139,33 @@ func (h *HugoWorkflow) PostEncode(stats *encoder.FileStats) error {
// A mismatch and a missing value both need confirmation, but each gets its
// own prompt wording so the user knows which case they are approving.
if needsUpdate {
promptAndUpdateFrontmatter(h.opts.EpisodeMD, "\nUpdate frontmatter with new values? [y/N]: ", stats.DurationString, stats.FileSizeBytes)
return promptAndUpdateFrontmatter(h.opts.EpisodeMD, "\nUpdate frontmatter with new values? [y/N]: ", stats.DurationString, stats.FileSizeBytes)
} else if h.hugoMetadata.PodcastDuration == "" || h.hugoMetadata.PodcastBytes == 0 {
promptAndUpdateFrontmatter(h.opts.EpisodeMD, "\nAdd podcast_duration and podcast_bytes to frontmatter? [y/N]: ", stats.DurationString, stats.FileSizeBytes)
return promptAndUpdateFrontmatter(h.opts.EpisodeMD, "\nAdd podcast_duration and podcast_bytes to frontmatter? [y/N]: ", stats.DurationString, stats.FileSizeBytes)
}

return nil
}

// promptAndUpdateFrontmatter prompts the user and updates the frontmatter with podcast stats
func promptAndUpdateFrontmatter(markdownPath, promptMsg, duration string, bytes int64) {
// promptAndUpdateFrontmatter prompts the user and updates the frontmatter with
// podcast stats. A write failure is returned so the caller can exit non-zero;
// declining the prompt is not an error.
func promptAndUpdateFrontmatter(markdownPath, promptMsg, duration string, bytes int64) error {
fmt.Print(promptMsg)
var response string
_, _ = fmt.Scanln(&response)

if strings.ToLower(strings.TrimSpace(response)) == "y" {
if err := encoder.UpdateFrontmatter(markdownPath, duration, bytes); err != nil {
cli.PrintError(fmt.Sprintf("Failed to update frontmatter: %v", err))
} else {
cli.PrintSuccess("Frontmatter updated successfully")
}
} else {
if strings.ToLower(strings.TrimSpace(response)) != "y" {
cli.PrintInfo("Frontmatter not updated")
return nil
}

if err := encoder.UpdateFrontmatter(markdownPath, duration, bytes); err != nil {
return fmt.Errorf("failed to update frontmatter: %w", err)
}

cli.PrintSuccess("Frontmatter updated successfully")
return nil
}

// Ensure HugoWorkflow implements Workflow at compile time.
Expand Down
Loading
Loading