Podcastの配信において、音声ファイル(MP3)とそのメタデータを使って、PodcastのRSSフィード(XML形式)を生成することがよくあります。今回は、TypeScriptを使って、ローカルディレクトリまたはAWS S3からMP3ファイルを取得し、その情報をもとにPodcastのXMLファイルを作成する方法を紹介します。
概要
- MP3ファイルのメタデータを取得:ファイル名、タイトル、説明、再生時間など。
- XML形式でPodcastのRSSフィードを生成:iTunesに適した形式でエピソード情報をXML化。
- ローカルディレクトリとS3バケットからMP3ファイルを取得:環境によって処理を分岐。
必要なライブラリ
以下のライブラリを使用します:
music-metadata:MP3ファイルのメタデータを取得します。xml2js:JavaScriptオブジェクトをXMLに変換します。fs、path:ローカルファイルシステム操作に必要です。aws-sdk:AWS S3からファイルを取得するために使用します。
まず、必要なパッケージをインストールします。
npm install fs path xml2js music-metadata aws-sdk
1. MP3ファイルのメタデータを取得
PodcastのXMLを作成するために、MP3ファイルから以下の情報を取得します:
- タイトル:ファイルに設定されているタイトル。
- 説明:ファイルに設定されているコメント(なければデフォルトの説明を使用)。
- 再生時間:音声の長さ。
MP3ファイルのメタデータを取得するために、music-metadataライブラリを使います。
import musicMetadata from 'music-metadata';
const getEpisodeMetadata = async (filePath: string) => {
try {
const metadata = await musicMetadata.parseFile(filePath);
const duration = metadata.format.duration;
const hours = Math.floor(duration / 3600);
const minutes = Math.floor((duration % 3600) / 60);
const seconds = Math.floor(duration % 60);
const episodeDuration = `${hours}:${minutes}:${seconds}`;
const episodeTitle = metadata.common.title || path.basename(filePath, '.mp3');
const episodeDescription = metadata.common.comment || `Description for episode ${episodeTitle}.`;
return { episodeTitle, episodeDescription, episodeDuration };
} catch (err) {
console.error('MP3メタデータの取得に失敗しました:', err);
return {
episodeTitle: path.basename(filePath, '.mp3'),
episodeDescription: `Description for episode ${path.basename(filePath, '.mp3')}.`,
episodeDuration: '00:00:00'
};
}
};
2. ローカルディレクトリとS3からMP3ファイルを取得
次に、MP3ファイルをどこから取得するか決めます。今回は、ローカルディレクトリとS3からファイルを取得する方法を実装します。
ローカルディレクトリからファイルを取得
const getFilesFromLocal = (directory: string) => {
return fs.readdirSync(directory).filter(file => file.endsWith('.mp3'));
};
S3からファイルを取得
S3にあるMP3ファイルを取得するには、AWS SDKを使用します。listObjectsV2を使って、指定したプレフィックス(ディレクトリ)にあるMP3ファイルの一覧を取得します。
import AWS from 'aws-sdk';
const s3 = new AWS.S3({
region: 'us-west-2', // 適切なリージョンを指定
});
const getFilesFromS3 = async (bucketName: string, prefix: string) => {
const params = {
Bucket: bucketName,
Prefix: prefix,
};
try {
const data = await s3.listObjectsV2(params).promise();
return data.Contents?.filter(file => file.Key?.endsWith('.mp3')).map(file => file.Key!) || [];
} catch (err) {
console.error('S3からファイル一覧の取得に失敗しました:', err);
return [];
}
};
3. PodcastのXMLを生成
MP3ファイルの情報を集めたら、それを元にPodcastのXMLを生成します。xml2jsライブラリを使用して、JSONオブジェクトからXMLを作成します。
import { Builder } from 'xml2js';
const podcastMetadata = {
title: 'My Podcast',
description: 'This is a description of the podcast.',
link: process.env.PODCAST_DOMAIN || '',
language: 'ja',
copyright: 'Your Company',
pubDate: new Date().toUTCString(),
itunes: {
author: 'Your Name',
category: 'Technology',
image: 'https://yourwebsite.com/podcast-image.jpg'
}
};
const createPodcastXML = async (directory: string, isS3: boolean, bucketName?: string, prefix?: string) => {
let files: string[] = [];
if (isS3) {
if (!bucketName || !prefix) {
throw new Error('S3のバケット名とプレフィックスを指定してください');
}
files = await getFilesFromS3(bucketName, prefix);
} else {
files = getFilesFromLocal(directory);
}
const episodes = await Promise.all(files.map(async (file) => {
const episodeLink = isS3
? `https://your-s3-bucket-name.s3.amazonaws.com/${file}`
: `${podcastMetadata.link}/podcasts/${file}`;
const filePath = isS3 ? file : path.join(directory, file);
const { episodeTitle, episodeDescription, episodeDuration } = await getEpisodeMetadata(filePath);
return {
title: episodeTitle,
description: episodeDescription,
link: episodeLink,
enclosure: {
$: {
url: episodeLink,
type: 'audio/mpeg',
length: isS3 ? '0' : fs.statSync(filePath).size.toString()
}
},
guid: episodeLink,
pubDate: new Date().toUTCString(),
'itunes:duration': episodeDuration
};
}));
const podcastXML = {
rss: {
$: {
version: '2.0',
xmlns: 'http://www.itunes.com/dtds/podcast-1.0.dtd',
},
channel: [
{
title: podcastMetadata.title,
description: podcastMetadata.description,
link: podcastMetadata.link,
language: podcastMetadata.language,
copyright: podcastMetadata.copyright,
pubDate: podcastMetadata.pubDate,
'itunes:author': podcastMetadata.itunes.author,
'itunes:category': {
$: {
text: podcastMetadata.itunes.category
}
},
'itunes:image': {
$: {
href: podcastMetadata.itunes.image
}
},
item: episodes
}
]
}
};
const builder = new Builder();
const xml = builder.buildObject(podcastXML);
if (!isS3) {
fs.writeFileSync(path.join(directory, 'podcast.xml'), xml, 'utf-8');
console.log('Podcast XMLが作成されました');
}
if (isS3) {
console.log('Podcast XMLをS3にアップロードする処理を追加できます');
}
};
4. 実行
実際にこのコードを使ってPodcastのXMLを作成する際、ローカルディレクトリからMP3ファイルを取得する場合、isS3をfalseに設定します。S3から取得する場合は、isS3をtrueに設定し、S3のバケット名とプレフィックスを指定します。
const directoryPath = './podcasts'; // ローカルディレクトリパス
const isS3 = false; // S3から取得する場合は true、ローカルから取得する場合は false
const bucketName = 'your-s3-bucket-name'; // S3バケット名
const prefix = 'podcasts/'; // S3内のディレクトリ
createPodcastXML(directoryPath, isS3, bucketName, prefix);
まとめ
このように、TypeScriptとAWS SDKを活用して、ローカルディレクトリまたはS3からMP3ファイルを取得し、それを元にPodcastのRSSフィード(XMLファイル)を生成することができます。Podcast配信の準備が整うと、配信先のサービス(iTunesやSpotifyなど)で番組を簡単に公開できるようになります。