The Workflow Edition

Post a show

Here is the typical routine for posting a new episode:

  1. Name your master file (preferably in the .flac format) as your [show name]_[episode number].[codec extension]

  2. Place your master file into your podwrite media directory. This directory bears the same name as your media directory on your server.

  3. Run mkenc on your master file to generate all the formats you publish: mkenc audio/foo_100.flac

  4. Edit the shownotes.htm and links.htm files.

  5. Run podwrite: podwrite -e 100 foo

  6. Check the files podwrite has generated to make sure everything is correct.

  7. Publish: podwrite -e 100 --no-build --publish foo

That's it!

What are podwrite and mkenc?

Podwrite and mkenc are podcasting tools for geeks. If you have SSH to your web server, have a basic understanding of wget and scp, and are lazy like me, then podwrite and mkenc may be for you.

If you're new to podcasting, or you don't understand how RSS and Atom feeds work, or have an account on a server you do not have shell access to, then podwrite is not for you (I recommend Podpress on Wordpress, as an easy alternative), although mkenc may still be useful.

Since mkenc is useful to anyone who needs to encode media, I cover that first.


Install podwrite and mkenc with the script you got in the download.


The mkenc script encodes and tags audio files. It prefers .flac files, but can also handle .wav files.

The mkenc script relies on, which was installed along with mkenc and podwrite. It does not require a configuration file, but you can use a configuration file to avoid having to type long commands.


Currently, mkenc outputs to Ogg Vorbis, Opus, an open source version of AAC, and Speex. More codecs may be supported in the future.

To transcode to all codecs:

$ mkenc foo.flac


All output files are given tags, which some media players use when listing files.

The default values in mkenc are very generic, so you probably want to set them. You can define tags as a part of your mkenc command:

mkenc --author Klaatu \

--show-title "Gnu World Order" \

--episode 101 \

--comment "" \

--track-title gnuWorldOrder_100.ogg \

--category Podcast foo.flac

Different audio files implement tags differently, but the tags you provide here are mapped to the tags available. Not all formats have slots for all tags, but mkenc does its best.


Instead of typing out all that information everytime you use mkenc, you can set up a configuration file for mkenc to use.

There is an example configuration file in the example of the podwrite documentation directory. Copy it to $HOME/.config/podwriterc.

(You can actually put the configuration file anywhere, but if you do, you must use the --config option when launching mkenc so that mkenc knows where to find it.)

In the configuration file, set the appropriate values. Since some people host more than one podcast, some values (in the [global] section) apply to all your shows. Others are show-specific and must be placed in a show section. For example, here's an example for my show GNU World Order:


author = Klaatu

email =


format = ogg,opus,m4a,spx

show = GNU World Order

category = Podcast

comment =

Episode number has to be given as part of the command, and the track title is derived from the file name. If you want each track title to be unique, you can do that as part of the command, although be warned, podcast listeners generally prefer simple file names that fall into a natural order.

That's all there is to mkenc. For more command options, see mkenc --help


The podwrite script is more complex than mkenc, especially if you don't have a good understanding of how to interact with web servers.

Regardless of your familiarity with web servers, before you start using podwrite, think about the structure of your show. This is important, because podwrite is better with consistency.

For instance, you need to know or decide upon these things before starting to use podwrite:


Podwrite relies on a config file called podwriterc.

There is an example podwriterc file in the examples directory.

In the [global] section of the config file, you must have two values: an author and an email. These values are used in your RSS and Atom feeds and can be used by mkenc.

[global] author = Klaatu email =

You can add one section for each show you publish. The name of the section must be the same as the showName part of your audio files you publish. For instance, if you name a section [gnuWorldOrder], then podwrite expects your episodes to start with gnuWorldOrder (my files are all called gnuWorldOrder_12x1.ogg, with 12x1 being the episode number and the .ogg being the codec-appropriate file extension.

Nearly anything you can configure as a command option can be put into the configuration file. Here is an example for my show Chronicles & Commons:


note = shownotes.htm

linkdoc = links.htm

html = template.htm

server =

srvpath = podcast

target = ~/html/

media = cnc_audio

files = ogg.xml,opus.xml,ogg.atom.xml,opus.atom.xml,m4a.xml,m4a.atom.xml,index.html

format = ogg,opus,m4a

user = klaatu

Here's what it all means:

note path to the shownotes. Shownotes are placed into the feeds and HTML.

linkdoc path to significant links. These are placed into the HTML.

html path to the HTML template.

server the domain name of your server. This is used by both wget to download the feeds and HTML source, and by SSH to upload the files back to the Internet.

srvpath the path to your HTML and feeds, used by wget. This is not used by SSH.

target where to put the files when uploading. This is used by SSH and not by wget.

media path to your local media directory. Name your local media directory whatever it is named on the server. For example, if your episodes are kept in a directory on your server called audio, then name your local media directory audio. If your episodes are in a directory on your server called shows then name your local media directory shows.

files what files you want podwrite to manage. For instance, if you only wanted to provide Atom feeds, don't list any RSS feeds here.

format which codecs you want podwrite to create feeds for.

user the username you need to use to access your server. This may be entirely different than the username you use on your computer. If you're not sure, check with your hosting provider.

Once you have set up a config file, podwrite is configured. The question is, are you?

RSS and Atom feeds

RSS and Atom "feeds" are the way that listeners find out that you have posted a new episode of your podcast. When podwrite posts a show for you, it creates a new entry in your feed. Your subscribers are alerted of a new episode in whatever software they use to subscribe to your content, whether it's Gpodder, AntennaPod, iTunes, or something else.

For podwrite to update a feed, you must have a feed. Feeds are written in XML (think of it as a very strict form of HTML). There are example feeds in the example directory. Personalise those files, leaving all comments in tact..

Most importantly: do not erase the <!--SCRIPTENT--> comment. That comment is what podwrite uses to know where to put the updates.

Once your feed is personalized, make a copy for each feed for each codec you offer listeners. Then rename each copy using the codec extensions that podwrite and mkenc understand. Those are:

ogg: ogg.xml and ogg.atom.xml

The ogg and opus formats are open source standards. They play in all open source web browsers (like Firefox, Chromium, Brave, Vivaldi, and Chrome) and on most computers and mobiles.

opus: opus.xml and opus.atom.xml

A new codec, but well supported by Android and open source web browsers.

m4a: m4a.xml and m4a.atom.xml

AAC uses .m4a and is pretty much the only thing Apple devices play without complaint. It's not particularly good and the file size needs to be larger than other formats for it to achieve similar quality.

spx: spx.xml and spx.atom.xml

The .spx extension is Speex. It is extremely low quality, but renders the smallest file sizes. Use this if you have listeners in locations where Internet access is at a premium.

Once you have all your feeds named, upload them to your server in the place you have defined in your podwrite configuration. Remember, the folder path on your server will be different from what the rest of the world sees, and podwrite downloads as if it were a listener, but uploads as if it were you.


Podwrite can, optionally, generate HTML for your show. This gets complex, because for the HTML to be useful to you, you must design your own website. There is a sample HTML template in the example folder.

Your template may contain whatever HTML you want to be repeated with each episode release (you probably want to make each episode a div, to contain each one, but it's up to you). In place of the content generated by podwrite, use macros. Valid macros are:

%MEDIA for the directory path to the episode

%EPNUM for episode number

%TITLE for the track title

%DATE for the publication date

%NOTE for shownotes

%LINK for links to things you might have talked about in your show

Shownotes for your show go into a file called shownotes.htm by default.

Links go into a file called links.htm by default. Podwrite uses <dt> elements for links.

You must place a <!--SCRIPTENT--> comment in your HTML file so that podwrite knows where to put your updates.

As with the feeds, you must upload your HTML file to your server before using podwrite. If podwrite can't find your HTML file, it will fail (unless you use the --feed-only flag).

Getting subscribers

Finding an audience is tough, but there are a few things you just have to do if you're a new podcaster.

Register your podcast on Blubrry and on iTunes. Luckily, you don't actually need iTunes to register a show with it.

Server access

Most modern hosting accounts use SSH for shell access, and SCP for copying. Podwrite can use other access methods, like FTP, but SSH is safer.

SSH uses its own configuration file to keep track of credentials. Using this, you can ensure that podwrite doesn't encounter authentication problems when attempting to upload your media, feeds, and HTML.

The SSH config file is $HOME/.ssh/config and it can contain unique configuration blocks based on the hostname you are accessing. For instance, if I am trying to access but my hosting provider has given me the username bob123 and an SSH key called cast_rsa, then I would communicate these requirements to SSH in its config file:

$ cat $HOME/.ssh/config



    user bob123

    identityfile $HOME/.ssh/cast_rsa

All podwrite needs to know is what username to use (which you can place into your podwrite config under each show that requires that username).

If you're having trouble accessing your server with podwrite, try it with just SSH. If you can log in to your server with basically no interaction, then podwrite ought to be able to do so, as well. If it continues to fail, file a bug with me.

100% Free & Open Source Software