python 传智播客
我有一个播客 ,可与Red Hat同事和各种行业专家聊天,涉及从云到DevOps到容器再到IoT到开源的话题。 随着时间的流逝,我已经大大简化了录制和编辑过程 。 但是,当涉及将播客实际在线放置的机制时,需要精确遵循许多繁琐的小步骤。 我确信任何正在阅读此内容的系统管理员都已经在“您需要一个脚本!” 他们是完全正确的。
在本文中,我将带您看一下我编写的Python脚本,该脚本在很大程度上可以自动编辑播客。 该脚本无法完成所有任务。 我仍然需要输入特定于剧集的信息才能应用该脚本,并且我会手工撰写博客文章。 (我曾经使用脚本为博客创建一个存根,但是该操作的那部分需要足够的手动步骤,以至于我没有买到任何东西。)尽管如此,该脚本仍处理了许多琐碎的小步骤否则会很耗时且容易出错。
我会警告您,这是我几年前针对特定工作流程编写的一个基本程序。 您将需要根据自己的需要进行定制。 此外,尽管出于本文的目的,我对代码进行了一些整理,但它并不包含大量输入或错误检查,并且其用户界面非常基本。
该脚本有六件事。 它:
- 提供一个界面供用户输入剧集标题,字幕和摘要;
- 从MP3文件中获取信息(例如持续时间);
- 更新XML播客feed文件;
- 将原始编辑的MP3文件与前段和后段连接在一起;
- 创建一个OGG文件版本;
- 并将XML,MP3和OGG文件上传到Amazon S3并使其公开。
podcast-python脚本
如果您想下载阅读本文时要参考的全部内容,可以在GitHub上使用podcast-python脚本 。
潜水之前,要整理一点。 我们将boto用于Amazon Web Services S3界面,其中将存储使播客公开可用所需的文件。 我们将使用mpeg1audio从MP3文件中检索元数据。 最后,我们将使用pydub作为操作音频文件的界面,这需要在系统上安装ffmpeg 。
现在,您需要创建一个文本文件,其中包含整个播客的信息。 添加情节时不会改变。 下面的示例来自我的Cloudy Chat播客 。
-
-
-
-
- < ?
- xml version
- =
- "1.0" encoding
- =
- "UTF-8" ?
- >
-
-
- < rss xmlns:itunes
- =
- "http://www.itunes.com/dtds/podcast-1.0.dtd" version
- =
- "2.0"
- >
-
-
- < channel
- >
-
-
- < title
- > Cloudy Chat
- < /title
- >
-
-
- < link
- > http://www.
- bitmasons .
- com
- < /link
- >
-
-
- < language
- > en-us
- < /language
- >
-
-
- < copyright
- > &
- #x2117; & © 2017, Gordon Haff</copyright>
-
-
- < itunes:subtitle
- > Industry experts talk cloud computing
- < /itunes:subtitle
- >
-
-
- < itunes:author
- > Gordon Haff
- < /itunes:author
- >
-
-
- < itunes:summary
- > Information technology today
- is at the explosive intersection of major trends that are fundamentally changing how we do computing
- and ultimately interact
- with the world.
- Longtime industry expert
- , pundit
- ,
- and now Red Hat cloud evangelist Gordon Haff examines these changes through conversations
- with leading technologists
- and visionaries.
- < /itunes:summary
- >
-
-
- < description
- > Industry experts talk cloud computing
- , DevOps
- , IoT
- , containers
- ,
- and more.
- < /description
- >
-
-
- < itunes:owner
- >
-
-
- < itunes:name
- > Gordon Haff
- < /itunes:name
- >
-
-
- < itunes:email
- > REDACTED
- @ gmail.
- com
- < /itunes:email
- >
-
-
- < /itunes:owner
- >
-
-
- < itunes:image href
- =
- "http://s3.amazonaws.com/grhpodcasts/cloudychat300.jpg" /
- >
-
-
- < itunes:category text
- =
- "Technology" /
- >
-
-
- < itunes:explicit
- > no
- < /itunes:explicit
- >
-
然后,您需要一个第二个文本文件,其中包含每个现有项目(例如,情节)的XML,外加几行。 如果您没有任何现有情节,则文件将如下所示。
-
-
-
-
- < /channel
- >
-
-
- < /rss
- >
-
该脚本通过将标题文本与新剧集的XML连接起来,然后附加第二个文本文件,来构建您的播客feed文件。 然后,它还将新项目添加到第二个文本文件,以便在添加另一个新剧集时将其存在。
该程序使用TkInter (位于Tcl / Tk之上的一个薄的面向对象层)作为GUI。 除了选择要上传的MP3文件之外,您还可以在此处输入播客标题,副标题和摘要。 它作为主程序循环运行,如下图所示:
这是使用以下代码构建的。 (您可能应该使用较新的TkInter主题小部件,但我从来没有更新到更漂亮的界面。)
-
-
-
-
- root
- = Tk
- (
- )
-
- Label
- ( root
- , text
- =
- "Podcast Title:"
- ) .
- grid
- ( row
- =
- 1
- , sticky
- = W
- )
-
-
- < Some interface building
- code omitted
- >
-
- Button
- ( root
- , text
- =
- 'Select file...'
- , command
- = open_file_dialog
- ) .
- grid
- ( row
- =
- 9
- , column
- =
- 0
- , sticky
- = W
- )
-
- v
- = StringVar
- (
- )
-
- Label
- ( root
- , textvariable
- = v
- , justify
- = LEFT
- , fg
- =
- "blue"
- ) .
- grid
- ( row
- =
- 10
- , sticky
- = W
- )
-
- TimestampEntry
- = Entry
- ( root
- , width
- =
- 50
- , borderwidth
- =
- 1
- ) TimestampEntry.
- grid
- ( row
- =
- 11
- , sticky
- = W
- )
-
- TimestampEntry.
- insert
- ( END
- ,
- "Time/date (default filled in automatically from file)"
- )
-
- FilelengthStr
- = StringVar
- (
- ) FilelengthStr.
- set
- (
- "Filelength (bytes):"
- )
-
- FilelengthLabel
- = Label
- ( root
- , textvariable
- = FilelengthStr
- )
-
- FilelengthLabel.
- grid
- ( row
- =
- 12
- , sticky
- = W
- )
-
- DurationLabelStr
- = StringVar
- (
- )
-
- DurationLabelStr.
- set
- (
- "Duration: "
- )
- ; DurationLabel
- = Label
- ( root
- , textvariable
- = DurationLabelStr
- ) DurationLabel.
- grid
- ( row
- =
- 13
- , sticky
- = W
- )
-
- Button
- ( root
- , text
- =
- 'Go!'
- , command
- = do_stuff
- ) .
- grid
- ( row
- =
- 14
- , sticky
- = W
- )
-
- StatusText
- = StringVar
- (
- ) StatusText.
- set
- (
- "Status: Nothing to report"
- )
-
- StatusLabel
- = Label
- ( root
- , textvariable
- = StatusText
- ) StatusLabel.
- grid
- ( row
- =
- 15
- , sticky
- = W
- )
-
- root.
- mainloop
- (
- )
-
当我们选择一个MP3文件时, open_file_dialog函数将运行。 此函数执行所有音频文件操作,然后通过全局变量将所需的有关文件大小,长度和日期戳的信息返回到界面中的标签小部件。 首先进行操作更为直接,因为我们要获取适用于将要上传的最终文件的元数据。 根据文件大小,此操作可能需要一分钟左右的时间。
去吧! 按钮然后执行发布播客所需的其余功能,并在该过程似乎已成功完成时返回状态。
借助这些初步知识,让我们看一下脚本执行的一些特定任务。 我将主要跳过与设置目录路径和类似内容相关的内务管理细节,而将重点放在实际的自动化上。
添加简介和结尾。 节省时间:每集5分钟。
我们要做的第一件事是备份原始文件。 如果出现问题,这是个好习惯。 它也给了我基本文件的副本,以便照常发送出去。
-
-
-
-
- renameOriginal
- = FileBase +
- "_original" + FileExtension
-
-
- shutil .
- copy2
- ( filename
- , renameOriginal
- )
-
然后,我将MP3文件与前奏和后奏音频连接在一起。 AudioSegment是pydub函数。
-
-
-
-
- baseSegment
- = AudioSegment.
- from_mp3
- ( filename
- )
-
- introSegment
- = AudioSegment.
- from_mp3
- ( leadIn
- )
-
- outroSegment
- = AudioSegment.
- from_mp3
- ( leadOut
- )
-
- completeSegment
- = introSegment + baseSegment + outroSegment
-
- completeSegment.
- export
- ( filename
- ,
- "mp3"
- )
-
前奏和尾奏是我用来引导和关闭播客的标准音频片段。 它们由简短的人声段和几秒钟的音乐组成。 手动添加这些内容至少需要几分钟,并且可能会添加错误的剪辑。 我还创建了一个OGG版本的播客,可以从我的博客链接到该播客以及MP3文件。
获取文件元数据。 节省时间:每集3分钟。
我们新获得了文件的大小,时间,日期和长度,并将其全部转换为播客feed所需的格式。 大小和时间戳来自标准函数。 mpeg1audio提供MP3文件的持续时间。
-
-
-
-
- Filelength
- = path.
- getsize
- ( filename
- )
-
- FilelengthStr.
- set
- (
- "Filelength (bytes): " +
- str
- ( Filelength
- )
- )
-
- timestruc
- =
- time .
- gmtime
- ( path.
- getmtime
- ( filename
- )
- )
-
- TimestampEntry.
- delete
- (
- 0
- , END
- )
-
- TimestampEntry.
- insert
- (
- 0
- ,
- time .
- strftime
- (
- "%a, %d %b %G %T"
- , timestruc
- ) +
- " GMT"
- )
-
- mp3
- = mpeg1audio.
- MPEGAudio
- ( filename
- )
-
- DurationStr
- =
- str
- ( mp3.
- duration
- )
-
- DurationLabelStr.
- set
- (
- "Duration: " + DurationStr
- )
-
构建播客feed XML文件。 节省时间:每集8分钟。
这确实是一个巨大的胜利。 启动文本编辑器和编辑XML文件所花费的时间甚至不多。 就是因为我经常在第一次尝试时就弄错了。 而且,由于我经常在第一次尝试时就弄错了,因此当我手动编辑文件时,我不得不在上传之前先通过XML验证程序运行该文件。
现在,出于全面披露的目的,我应该注意,编写的脚本对如果字符(例如&符)在供稿中必须转义的字符没有任何作用。 由于不同的原因,如果您将诸如卷曲引号之类的字符剪切并粘贴到“ 摘要”编辑框中,则可能也会遇到问题。 但是,总的来说,我可以放心地将请求的信息输入到GUI中,并可以确信提要是干净的。
-
-
-
-
- # create an XML file containing contents for new </item> for iTunes
-
- FileBase
- , FileExtension
- = path.
- splitext
- ( filename
- )
-
- XMLfilename
- = FileBase +
- '.xml'
-
- MP3url
- =
- "http://s3.amazonaws.com/" +bucket_name+
- "/" +path.
- basename
- ( filename
- )
-
- inp
- =
- file
- ( XMLfilename
- ,
- 'w'
- )
-
- inp.
- write
- (
- "<item> \n "
- )
-
- inp.
- write
- (
- "<title>" +PodcastTitleEntry.
- get
- (
- ) +
- "</title> \n "
- )
-
- inp.
- write
- (
- "<itunes:subtitle>" +PodcastSubtitleEntry.
- get
- (
- ) +
- "</itunes:subtitle> \n "
- )
-
- inp.
- write
- (
- "<itunes:summary>" +PodcastSummaryText.
- get
- (
- 1.0
- , END
- ) +
- "</itunes:summary> \n "
- )
-
- inp.
- write
- (
- "<enclosure url= \" " +MP3url+
- " \" length= \" " +
- str
- ( Filelength
- ) +
- " \" type= \" audio/mpeg \" /> \n "
- )
-
- inp.
- write
- (
- "<guid>" +MP3url+
- "</guid> \n "
- )
-
- inp.
- write
- (
- "<pubDate>" +TimestampEntry.
- get
- (
- ) +
- "</pubDate> \n "
- )
-
- inp.
- write
- (
- "<itunes:duration>" +DurationStr+
- "</itunes:duration> \n "
- )
-
- inp.
- write
- (
- "<itunes:keywords>cloud</itunes:keywords> \n "
- )
-
- inp.
- write
- (
- "<itunes:explicit>no</itunes:explicit> \n "
- )
-
- inp.
- write
- (
- "</item>"
- )
-
- inp.
- write
- (
- ""
- )
-
- inp.
- close
- (
- )
-
-
- #Now concatenate to make a new itunesxml.xml file
-
-
- #create backup of existing iTunes XML file in case something goes kaka
-
- iTunesBackup
- = path.
- join
- ( theDirname
- ,
- "itunesxmlbackup.xml"
- )
-
-
- shutil .
- copy2
- ( iTunesFile
- , iTunesBackup
- )
-
-
- #create temporary iTunes item list (to overwrite the old one later on)
-
- outfile
- =
- file
- (
- "iTunestemp.xml"
- ,
- 'w'
- )
-
-
- # create a new items file
-
-
- with
- open
- ( XMLfilename
- )
- as f:
-
-
- for line
- in f:
-
- outfile.
- write
- ( line
- )
-
-
- with
- open
- ( iTunesItems
- )
- as f:
-
-
- for line
- in f:
-
- outfile.
- write
- ( line
- )
-
- outfile.
- close
- (
- )
-
-
- #replace the old items file with the new one
-
-
- shutil .
- copy2
- (
- "iTunestemp.xml"
- , iTunesItems
- )
-
-
- #now we're ready to create the new iTunes File
-
- outfile
- =
- file
- ( iTunesFile
- ,
- 'w'
- )
-
-
- # create a new items file
-
-
- with
- open
- ( iTunesHeader
- )
- as f:
-
-
- for line
- in f:
-
- outfile.
- write
- ( line
- )
-
-
- with
- open
- ( iTunesItems
- )
- as f:
-
-
- for line
- in f:
-
- outfile.
- write
- ( line
- )
-
- outfile.
- close
- (
- )
-
上载到AWS S3。 节省时间:每集5分钟。
我们有修改后的音频文件,还有提要文件-是时候将它们放置在全世界可以听的地方了。 我使用boto连接到AWS S3并上传文件。
这很简单。 您连接到S3。 在此脚本中,假定AWS凭证存储在您的环境中。 boto的当前版本boto3提供了许多处理凭据的替代方法。 然后将文件上传并公开。
如果您要尝试使用现有播客进行自动化操作,最好给Feed文件提供一个与现有Feed不冲突的名称,然后将文件上传为私有文件。 这使您有机会在上线之前手动检查一切正常。 那是我一开始所做的。 随着时间的流逝,我进行了一些调整,并获得了信心,我可以开除并且(大部分)忘记。
我经常仍然快速浏览一下以确认没有问题,但是老实说,这些天很少出现问题。 而且,如果我听取自己的建议,我将花一些时间来解决一些我所知道的潜在潜在故障,特别是验证和清理输入。
-
-
-
-
- # Upload files to Amazon S3
-
-
- # Change 'public-read' to 'private' if you want to manually set ACLs
-
- conn
- = boto.
- connect_s3
- (
- )
-
- bucket
- = conn.
- get_bucket
- ( bucket_name
- )
-
- k
- = Key
- ( bucket
- )
-
- k.
- key
- = path.
- basename
- ( filename
- )
-
- k.
- set_contents_from_filename
- ( filename
- )
-
- k.
- set_canned_acl
- (
- 'public-read'
- )
-
-
-
- k.
- key
- = path.
- basename
- ( iTunesFile
- )
-
- k.
- set_contents_from_filename
- ( iTunesFile
- )
-
- k.
- set_canned_acl
- (
- 'public-read'
- )
-
节省时间
那么,这会把我们留在哪里呢? 如果我总计节省的时间估计,则每集21分钟。 当然,这仍然需要我几分钟,但其中大部分是用文字描述剧集,无论如何都需要完成。 即使我们为每集分配不那么慷慨的15分钟节省时间,这也算是1,500分钟(25 小时)的不错时间,通过花一天左右的时间来编写脚本,我已经节省了100多个播客。
但是,老实说,我不确定即使那个时间的数字也能捕捉到现实。 反复地,繁琐的工作破坏了一天并消耗了精力。 自动化一切都没有意义。 但是,通常,如果您愿意尝试自动执行经常执行的操作,则不会后悔。
翻译自: https://opensource.com/article/17/4/automate-podcast-publishing-python
python 传智播客