tools / podcast.rb
| 2f16e387 » | archiloque | 2009-06-15 | 1 | # Generate a podcast rss file from all the mp3 contained in a directory | |
| 2 | # The mp3 are named "YYYY-MM-DD??????" and we get their title from their id3 tags | ||||
| 3 | # Params | ||||
| 4 | # - directory of mp3 files, default '.' | ||||
| 5 | # - root url for the mp3s, default 'http:/localhost/' | ||||
| 6 | # - the podcast title, default 'podcast' | ||||
| 7 | # - image url | ||||
| 8 | # - a target directory where the mp3 files will be copied with a short name if param is here, usefull if you have strange names that aren't url-firendly | ||||
| 9 | # Julien Kirch 2009, available under MIT license | ||||
| 10 | |||||
| 11 | require 'rubygems' | ||||
| 12 | require 'id3' | ||||
| 13 | require 'date' | ||||
| 14 | require 'parsedate' | ||||
| 15 | require 'builder' | ||||
| 16 | require 'rss/2.0' | ||||
| 17 | |||||
| 18 | # An item in the feed | ||||
| 19 | class RssItem | ||||
| 20 | include Comparable | ||||
| 21 | attr_accessor :title, :file_name, :duration, :pub_date, :size | ||||
| 22 | |||||
| 23 | def initialize | ||||
| 24 | title = '' | ||||
| 25 | end | ||||
| 26 | |||||
| 27 | def to_s | ||||
| 28 | "\"#{file_name}\", \"#{title}\", #{duration}, #{pub_date}" | ||||
| 29 | end | ||||
| 30 | |||||
| 31 | def <=> o | ||||
| 32 | pub_date <=> o.pub_date | ||||
| 33 | end | ||||
| 34 | end | ||||
| 35 | |||||
| 36 | mp3_directory = ARGV[0] || '.' | ||||
| 37 | root_url = ARGV[1] || 'http://localhost/' | ||||
| 38 | title = ARGV[2] || 'podcast' | ||||
| 39 | image_url = ARGV[3] | ||||
| 40 | target_directory = ARGV[4] | ||||
| 41 | |||||
| 42 | mp3s = Array.new | ||||
| 43 | Dir.chdir(mp3_directory) | ||||
| 44 | Dir.glob('*.mp3') do |file_name| | ||||
| 45 | item = RssItem.new | ||||
| 46 | file = ID3::AudioFile.new file_name | ||||
| 47 | if file.tagID3v1 | ||||
| 48 | item.title = file.tagID3v1['TITLE'] | ||||
| 49 | end | ||||
| 50 | if item.title.nil? || item.title.empty? | ||||
| 51 | item.title = File.basename(file_name, '.*') | ||||
| 52 | end | ||||
| 53 | item.duration = file.audioLength | ||||
| 54 | date = ParseDate.parsedate file_name[0,10] | ||||
| 55 | item.pub_date = Time.gm(date[0], date[1], date[2], 0, 0, 0) | ||||
| 56 | item.size = File.size(file_name) | ||||
| 57 | if target_directory | ||||
| 58 | target_name = sprintf("%03d", mp3s.size + 1) + File.extname(file_name) | ||||
| 59 | File.copy(file_name, target_directory + target_name) | ||||
| 60 | item.file_name = target_name | ||||
| 61 | else | ||||
| 62 | item.file_name = file_name | ||||
| 63 | end | ||||
| 64 | mp3s << item | ||||
| 65 | end | ||||
| 66 | |||||
| 67 | mp3s.sort | ||||
| 68 | |||||
| 69 | result = '' | ||||
| 70 | xml = Builder::XmlMarkup.new(:target=> result, :indent => 2) | ||||
| 71 | xml.instruct! 'xml', :version => '1.0', :encoding => 'UTF-8' | ||||
| 72 | xml.rss(:version=>"2.0", 'xmlns:itunes' =>'http://www.itunes.com/dtds/podcast-1.0.dtd') { | ||||
| 73 | xml.channel { | ||||
| 74 | xml.title title | ||||
| 75 | xml.description title | ||||
| 76 | if image_url && (!image_url.empty?) | ||||
| 77 | xml.image { | ||||
| 78 | xml.url image_url | ||||
| 79 | xml.title title | ||||
| 80 | xml.link root_url | ||||
| 81 | } | ||||
| 82 | end | ||||
| 83 | mp3s.each do |mp3| | ||||
| 84 | xml.item { | ||||
| 85 | xml.title mp3.title | ||||
| 86 | xml.link(root_url + mp3.file_name) | ||||
| 87 | xml.enclosure(:url => (root_url + mp3.file_name), :length => mp3.size, :type => 'audio/mpeg') | ||||
| 88 | xml.guid(root_url + mp3.file_name) | ||||
| 89 | xml.pubDate mp3.pub_date.rfc2822 | ||||
| 90 | } | ||||
| 91 | end | ||||
| 92 | } | ||||
| 93 | } | ||||
| 94 | print result | ||||
| 95 | |||||
