Skip to content

Commit

Permalink
Use mp3 instead of flac for apple feeds
Browse files Browse the repository at this point in the history
  • Loading branch information
cavis committed Oct 10, 2024
1 parent 4badbd7 commit 062b77a
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 17 deletions.
41 changes: 39 additions & 2 deletions app/models/feeds/apple_subscription.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
class Feeds::AppleSubscription < Feed
DEFAULT_FEED_SLUG = "apple-delegated-delivery-subscriptions"
DEFAULT_TITLE = "Apple Delegated Delivery Subscriptions"
DEFAULT_AUDIO_FORMAT = {"f" => "flac", "b" => 16, "c" => 2, "s" => 44100}.freeze
DEFAULT_AUDIO_FORMAT = {f: "mp3", b: 128, c: 2, s: 44100}.with_indifferent_access
DEFAULT_ZONES = ["billboard", "sonic_id"]

# min apple settings (though forcing a higher bitrate for mono)
# https://podcasters.apple.com/support/893-audio-requirements
MIN_MP3_BITRATE = 64
MP3_CHANNELS = [1, 2]
MIN_MP3_SAMPLERATE = 44100

after_initialize :set_defaults

after_create :republish_public_feed
Expand All @@ -20,7 +26,7 @@ class Feeds::AppleSubscription < Feed
def set_defaults
self.slug ||= DEFAULT_FEED_SLUG
self.title ||= DEFAULT_TITLE
self.audio_format ||= DEFAULT_AUDIO_FORMAT
self.audio_format ||= guess_audio_format
self.display_episodes_count ||= podcast&.default_feed&.display_episodes_count
self.include_zones ||= DEFAULT_ZONES
self.tokens = [FeedToken.new(label: DEFAULT_TITLE)] if tokens.empty?
Expand All @@ -29,6 +35,10 @@ def set_defaults
super
end

def guess_audio_format
default_feed_audio_format || episode_audio_format || DEFAULT_AUDIO_FORMAT
end

def self.model_name
Feed.model_name
end
Expand Down Expand Up @@ -77,4 +87,31 @@ def apple?
def publish_to_apple?
!!apple_config&.publish_to_apple?
end

def default_feed_audio_format
af = podcast&.default_feed&.audio_format
standardize_audio_format(af) if af && af[:f] == "mp3"
end

def episode_audio_format
episodes = podcast&.episodes&.published&.includes(:contents)&.limit(10)
contents = (episodes || []).map { |e| e.contents.first }.compact
mp3_contents = contents.select { |c| c.audio? && c.mime_type == "audio/mpeg" }

if mp3_contents.any?
max_bitrate = mp3_contents.map { |c| c.bit_rate.to_i }.max
max_channels = mp3_contents.map { |c| c.channels.to_i }.max
max_sample = mp3_contents.map { |c| c.sample_rate.to_i }.max
standardize_audio_format({b: max_bitrate, c: max_channels, s: max_sample})
end
end

def standardize_audio_format(af)
{
f: "mp3",
b: [MIN_MP3_BITRATE, af[:b]].compact.max,
c: MP3_CHANNELS.include?(af[:c]) ? af[:c] : MP3_CHANNELS.min,
s: [MIN_MP3_SAMPLERATE, af[:s]].compact.max,
}.with_indifferent_access
end
end
47 changes: 32 additions & 15 deletions test/models/feed/apple_subscription_test.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
require "test_helper"

describe Feeds::AppleSubscription do
let(:podcast) { create(:podcast) }
let(:feed_1) { podcast.default_feed }
let(:podcast) { create(:podcast, default_feed: default_feed) }
let(:default_feed) { build(:default_feed, audio_format: nil) }
let(:apple_feed) { build(:apple_feed, podcast: podcast) }

describe "#set_defaults" do
let(:default_feed) { build_stubbed(:feed, display_episodes_count: 99) }
let(:default_feed) { build_stubbed(:feed, display_episodes_count: 99, audio_format: nil) }
let(:podcast) { build_stubbed(:podcast, default_feed: default_feed) }

it "sets default values for apple subscription feeds" do
Expand All @@ -29,7 +29,7 @@
podcast: podcast,
slug: "foo",
title: "bar",
audio_format: {f: "baz"},
audio_format: {f: "flac"},
display_episodes_count: 88,
include_zones: ["something"],
private: false,
Expand All @@ -38,7 +38,7 @@

assert_equal "foo", f.slug
assert_equal "bar", f.title
assert_equal ({"f" => "baz"}), f.audio_format
assert_equal "flac", f.audio_format[:f]
assert_equal 88, f.display_episodes_count
assert_equal ["something"], f.include_zones
assert_equal true, f.private
Expand All @@ -49,12 +49,34 @@
end
end

describe "#guess_audio_format" do
it "uses the default feed format" do
default_feed.audio_format = {f: "mp3", b: 192, c: 1, s: 48000}
assert_equal default_feed.audio_format, apple_feed.guess_audio_format
end

it "uses the max episode format" do
c1 = build(:content, mime_type: "audio/mpeg", bit_rate: 192, channels: 1, sample_rate: 22050)
c2 = build(:content, mime_type: "audio/mpeg", bit_rate: 64, channels: 2, sample_rate: 44100)
c3 = build(:content, mime_type: "audio/wav", bit_rate: 16, channels: 1, sample_rate: 48000)
create(:episode, podcast: podcast, contents: [c1])
create(:episode, podcast: podcast, contents: [c2])
create(:episode, podcast: podcast, contents: [c3])

assert_nil default_feed.audio_format
assert_equal ({f: "mp3", b: 192, c: 2, s: 44100}).with_indifferent_access, apple_feed.guess_audio_format
end

it "falls back to the default format" do
assert_equal Feeds::AppleSubscription::DEFAULT_AUDIO_FORMAT, apple_feed.guess_audio_format
end
end

describe "#valid?" do
it "cannot change the default properties once saved" do
apple_feed.title = "new apple feed"
apple_feed.slug = "new-apple-slug"
apple_feed.file_name = "new_file.xml"
apple_feed.audio_format = {f: "flac", b: 16, c: 2, s: 44100}
assert apple_feed.valid?
apple_feed.save!

Expand All @@ -72,11 +94,6 @@
refute apple_feed.valid?
apple_feed.file_name = "new_file.xml"
assert apple_feed.valid?

apple_feed.audio_format = {f: "wav", b: 128, c: 2, s: 44100}
refute apple_feed.valid?
apple_feed.audio_format = {f: "flac", b: 16, c: 2, s: 44100}
assert apple_feed.valid?
end

it "cannot have more than one apple feed on a single podcast" do
Expand Down Expand Up @@ -105,15 +122,15 @@
assert apple_feed.apple_config.valid?

apple_feed.save!
assert_equal feed_1, apple_feed.apple_config.public_feed
assert_equal default_feed, apple_feed.apple_config.public_feed
end
end

describe "#publish_to_apple?" do
it "returns true if the feed has apple credentials" do
apple_feed.save!

refute feed_1.publish_to_apple?
refute default_feed.publish_to_apple?
assert apple_feed.publish_to_apple?
end

Expand All @@ -124,8 +141,8 @@
end

it "returns false if the feed is not an Apple Subscription feed" do
refute_equal feed_1.type, "Feeds::AppleSubscription"
refute feed_1.publish_to_apple?
refute_equal default_feed.type, "Feeds::AppleSubscription"
refute default_feed.publish_to_apple?
end
end
end

0 comments on commit 062b77a

Please sign in to comment.