Skip to content

Commit

Permalink
feat: add --add-mp3-metadata option (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
lightpohl authored Mar 13, 2021
1 parent c2bdbd8 commit 2825a36
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 18 deletions.
37 changes: 19 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,25 @@

## Options

| Option | Type | Required | Description |
| ----------------------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| --url | String | true | URL to podcast RSS feed. |
| --out-dir | String | false | Specify output directory for episodes and metadata. Defaults to "./{{podcast_title}}". See "Templating" for more details. |
| --archive | String | false | Download or write out items not listed in archive file. Generates archive file at path if not found. See "Templating" for more details. |
| --episode-template | String | false | Template for generating episode related filenames. See "Templating" for details. |
| --include-meta | | false | Write out podcast metadata to JSON. |
| --include-episode-meta | | false | Write out individual episode metadata to JSON. |
| --ignore-episode-images | | false | Ignore downloading found images from --include-episode-meta. |
| --offset | Number | false | Offset starting download position. Default is 0. |
| --limit | Number | false | Max number of episodes to download. Downloads all by default. |
| --episode-regex | String | false | Match episode title against provided regex before starting download. |
| --override | | false | Override local files on collision. |
| --reverse | | false | Reverse download direction and start at last RSS item. |
| --info | | false | Print retrieved podcast info instead of downloading. |
| --list | | false | Print episode list instead of downloading. |
| --version | | false | Output the version number. |
| --help | | false | Output usage information. |
| Option | Type | Required | Description |
| ----------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| --url | String | true | URL to podcast RSS feed. |
| --out-dir | String | false | Specify output directory for episodes and metadata. Defaults to "./{{podcast_title}}". See "Templating" for more details. |
| --archive | String | false | Download or write out items not listed in archive file. Generates archive file at path if not found. See "Templating" for more details. |
| --episode-template | String | false | Template for generating episode related filenames. See "Templating" for details. |
| --include-meta | | false | Write out podcast metadata to JSON. |
| --include-episode-meta | | false | Write out individual episode metadata to JSON. |
| --ignore-episode-images | | false | Ignore downloading found images from --include-episode-meta. |
| --offset | Number | false | Offset starting download position. Default is 0. |
| --limit | Number | false | Max number of episodes to download. Downloads all by default. |
| --episode-regex | String | false | Match episode title against provided regex before starting download. |
| --add-mp3-metadata | | false | Attempts to add a base level of MP3 metadata to each episode. Recommended only in cases where the original metadata is of poor quality. (**ffmpeg required**) |
| --override | | false | Override local files on collision. |
| --reverse | | false | Reverse download direction and start at last RSS item. |
| --info | | false | Print retrieved podcast info instead of downloading. |
| --list | | false | Print episode list instead of downloading. |
| --version | | false | Output the version number. |
| --help | | false | Output usage information. |

## Archive

Expand Down
19 changes: 19 additions & 0 deletions bin/bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ let {
logItemsList,
writeFeedMeta,
writeItemMeta,
addMp3Metadata,
} = require("./util");
let {
createParseNumber,
Expand Down Expand Up @@ -71,6 +72,10 @@ commander
"--episode-regex <string>",
"match episode title against regex before downloading"
)
.option(
"--add-mp3-metadata",
"attempts to add a base level of metadata to .mp3 files using ffmpeg"
)
.option("--override", "override local files on collision")
.option("--reverse", "download episodes in reverse order")
.option("--info", "print retrieved podcast info instead of downloading")
Expand All @@ -92,6 +97,7 @@ let {
reverse,
info,
list,
addMp3Metadata: addMp3MetadataFlag,
} = commander;

let main = async () => {
Expand Down Expand Up @@ -256,6 +262,19 @@ let main = async () => {
logError("Unable to download episode", error);
}

if (addMp3MetadataFlag) {
try {
addMp3Metadata({
feed,
item,
itemIndex: i,
outputPath: outputPodcastPath,
});
} catch (error) {
logError("Unable to add episode metadata", error);
}
}

if (includeEpisodeMeta) {
if (!ignoreEpisodeImages) {
let episodeImageUrl = getImageUrl(item);
Expand Down
52 changes: 52 additions & 0 deletions bin/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ let stream = require("stream");
let path = require("path");
let fs = require("fs");
let got = require("got");
let dayjs = require("dayjs");
let { execSync } = require("child_process");

let { logError, logErrorAndExit } = require("./validate");

Expand Down Expand Up @@ -350,6 +352,55 @@ let getFeed = async (url) => {
return feed;
};

let addMp3Metadata = ({ feed, item, itemIndex, outputPath }) => {
if (!fs.existsSync(outputPath)) {
return;
}

if (!outputPath.endsWith(".mp3")) {
console.log("Not an .mp3 file. Unable to add metadata.");
return;
}

let album = feed.title || "";
let title = item.title || "";
let artist =
item.itunes && item.itunes.author ? item.itunes.author : item.author || "";
let track =
item.itunes && item.itunes.episode
? item.itunes.episode
: `${feed.items.length - itemIndex}`;
let date = item.pubDate
? dayjs(new Date(item.pubDate)).format("YYYY-MM-DD")
: "";

let metaKeysToVales = {
album,
artist,
title,
track,
date,
album_artist: album,
};

let metadataString = Object.keys(metaKeysToVales)
.map((key) =>
metaKeysToVales[key]
? `-metadata ${key}="${metaKeysToVales[key].replace(/"/g, '\\"')}"`
: null
)
.filter((segment) => !!segment)
.join(" ");

let tmpMp3Path = `${outputPath}.tmp.mp3`;
execSync(
`ffmpeg -loglevel quiet -i "${outputPath}" -map_metadata 0 ${metadataString} -codec copy "${tmpMp3Path}"`
);

fs.unlinkSync(outputPath);
fs.renameSync(tmpMp3Path, outputPath);
};

module.exports = {
download,
getArchiveKey,
Expand All @@ -361,6 +412,7 @@ module.exports = {
logFeedInfo,
logItemInfo,
logItemsList,
addMp3Metadata,
writeFeedMeta,
writeItemMeta,
};

0 comments on commit 2825a36

Please sign in to comment.