Podcast Producer: Publishing to YouTube
YouTube has created a whole new generation of users who like to view video over the Internet, whether at their computer, their laptop or when using their iPhone. With Podcast Producer, you have many workflows available to you on your Mac OS X Server, but you can also customize workflows and publish content directly to YouTube. Follow along to build a custom workflow that will take an existing video podcast through Podcast Producer and post the content directly onto YouTube.
Publishing Content to YouTube
When developing a Podcast Producer solution, you won't always want to publish your material to one of the services built into the rest of Leopard Server. Podcast Producer is capable of combining and producing content that can be converted, merged and published to a variety of different locations, and in this article we focus on YouTube.
Because YouTube imposes limitations on the type of content that can be uploaded to its site, you must take into account the type of file formats that YouTube supports, the submission process and copyright protection issues. Podcast Producer can help you with all of this and at the same time automate the process, and even allow you to add some cool features as well.
YouTube File Formats and Support
YouTube accepts videos in a variety of different formats, including Apple Quicktime (.MOV), AVI, WMV MPG, and most of the supported audio formats that work with these video formats. There are some limitations on your video submissions to YouTube. They must be less than 10 minutes in length, and the overall video size must be less than 1 GB. And, for submissions from Podcast Producer, you need to use the YouTube API.
The YouTube Submission Process
The YouTube API is a set of HTTP protocols that allow URL-based submissions of video content directly to YouTube and allow you to retrieve and manipulate feeds. Extensions and interfaces are available to allow you to send content from a variety of programming languages and environments, including Java, PHP and Ruby.
In order to use the YouTube API for submissions, you must have an account on YouTube, and you must register with YouTube and obtain an API key (the Developer key) and a client ID. In essence, you must login with the API key information and your user login and password information. The user login/password can either be yours, or it can be unique to a podcast user. Then, once you have logged in, and you have the reference information, you can then submit the video to YouTube, along with the additional information, such as the title and description information (see Resources for information on getting a YouTube API key).
For videos from Podcast Producer, the title and description information submitted into the Podcast Producer client are used to feed the content into the system. A separate Java application has been created for this article that provides the communication functionality with YouTube through the API. Although Java is used for this application, Podcast Producer actions and the pcastaction utility allow you to use any language to write a YouTube upload application. This Java application is then combined with the main Podcast Producer workflow being developed to produce a system that handles the entire process, from submission of the source video to the final video on YouTube. Having a video of proper size and quality not only benefits upload times to YouTube, but also cuts the processing time of the workflow as well.
Creating Content for YouTube
When you submit a video to YouTube, it is converted into a Flash-compatible video format before finally being published. Because YouTube processes all video before it goes live, it is not possible to upload the information in a format that is directly compatible with YouTube. Instead the format and quality of the source video should be as high as possible while matching the video size and other requirements.
Encoding Video for YouTube
To get the highest quality video into YouTube, the first consideration is the size of the video stream. YouTube converts all videos into a 320x240 resolution video, so submitting a higher resolution video wastes bandwidth that can be used to enhance the quality of the video.
The video encoding used to create the videos on YouTube varies. There are differences between the available encodings at the time a video is produced and the inclusion of the H.264 format provided in the latest Flash Player 9 standards used to play the media.
Controlling the Video Encoding
Video encoding during production is handled by the encode command to the pcastaction tool used within Podcast Producer. Because YouTube supports the H.264 standard, the best encoding standard to use is one of the h264 standards. Podcast Producer supports three H.264 based encoding standards: h264, h264_hint and h264_hint_server. The h264_hint standard has the same basic settings as the base h264 format, but it is optimized for streaming, and h264_hint_server is optimized for both streaming and for serving from Leopard Server. However, both the h264_hint and h264_hint_server provide no real benefits in this case, since the YouTube encoding handles the streaming conversion.
The base h264 encoding format is set to encode video at the following settings:
- H.264 Video
- 480x360 resolution
- 550kbps
- Standard frame rate
The audio settings for AAC audio are set as follows:
- AAC audio
- 64kbps
- stereo
- 32KHz
These settings are more than suitable for uploading video to YouTube for further processing.
Adding Content to the Workflow
One of the main advantages of using Podcast Producer when producing content for YouTube is that you can add and combine video and effects to your podcasts automatically before they are submitted to YouTube for publishing. Adding an introduction to the material in your podcast, for example, may be part of a wider branding exercise, while adding watermark and copyright information can be important to ensure that your material is protected when it is finally published. Using a workflow, you can easily add information by extending the Workflow Definition File to merge in the additional content.
Using Pre- and Post- Video Content
Providing a video that can be used to prefix and introduce the main bulk of material is a good idea when publishing to a public environment such as YouTube. Because you no longer have control over the video, you need to make sure that your video is properly identified with you and your company. To do this, you can use standard introductory videos or workflow-specific introductory videos that are attached to the main content only when that workflow is used. You can also use introductory text, which is more commonly known as a splash screen, to ensure that you are identified with your podcast. Although you can't add running text, such as a subtitle, to a podcast, you can use the pcastaction tool to automate the process of adding textual material from a source into your podcast production.
Adding Watermarks and Copyright
Because the video is being published on a public forum, ensuring the validity of the file and having a way of tracking the information so that you can identify the video and, if necessary, track where it has been used and published can be important.
The easiest way to add this information is through a unique watermark that is embedded into the video. Be aware that because the video is re-processed by YouTube, some watermarks may simply be lost during the re-processing phase.
The alternative is to use a simple copyright statement. You cannot embed and apply this to every frame, but you can provide the information as part of the splash screen to the video.
Creating a Workflow for YouTube
The basic Workflow Definition File for the YouTube publication follows most other Podcast Producer workflows, with the various components of the workflow, such as the titles, introductory video, and other material being generated and merged into the final video.
For the basic workflow the sequence is to accept the the main video, merge in the main content, and then encode the video into the final format required to upload to YouTube. The final step of the process is to upload the video to YouTube using a custom component that communicates with the YouTube service.
Workflow Construction
The YouTube workflow has a number of different actions that must be performed before you commit the video to YouTube. Not all of these actions have to be followed for publishing to YouTube, but they are included here to demonstrate the correct sequence required to perform the different operations and produce a consistent output:
- Make the title material into a video
- Make the copyright material into a video
- Merge the title and intro video
- Merge the title/intro video with the main content
- Merge the intro and main content with the closing copyright
- Encode the video into the YouTube format
- Publish the video to YouTube
You can see the basic outline of the structure in Figure 1. The items in red are optional, and are required only if you want custom titles, copyright and introductory videos added to your final video.

Figure 1: The YouTube Workflow sequence
As mentioned, not all of these actions are required. You can create a simple workflow for YouTube that does not create a title, an introduction or copyright material. Since the basics of adding and combining this material are well known, we will concentrate the remainder of the article on the two main custom actions.
The main actions, merging the video and creating the title, can be taken from existing workflows. The two final custom actions, creating the video in YouTube format, and publishing the content to YouTube, must be created separately.
Creating the Custom Actions
The key element for the workflow is not the basic structure and overall sequence of events, but the action that takes the final generated video and then submits it to YouTube. The script itself is detailed in this section, but keep in mind that there are many potential solutions to the problem in a variety of different languages.
In the example workflow, you will use a standard script that accepts the required login, password, key and other information required to connect to YouTube, and the other material, such as the filename and metadata. All of this information is needed to post the material to YouTube.
When the post is completed, the unique reference number generated during the process is used and written into a Yet Another Markup Language (YAML) file that can be used to generate blog or wiki entries that include the YouTube file information.
The first custom action, converting the video into a format suitable for upload to YouTube, can be created by modifying one of the existing workflows.
To create the new workflow, copy the existing Blog Workflow from the /System/Library/PodcastProducer/Workflows/Blog.pwf file into /Library/PodcastProducer/Workflows/YouTube.pwf. Then:
- Open the YouTube.pwf bundle.
- Open Info.plist in Property List Editor and do the following:
- Set CFBundleIdentifier to com.apple.PodcastProducer.workflow.YouTube.
- Set CFBundleName to YouTube.
- Open InfoPlist.strings and set the Name and Description keys as follows:
- Name = "YouTube";
- Description = "Posts video to YouTube";
Next, you need to delete the following unused tasks from the template.plist file tasks specification:
- annotate
- archive
- encode_audio
- encode_iphone
- encode_iphone_cellular
- publish_audio
- publish_iphone
- unpack
- template_mail
- groupblog
Now you must modify two actions. The original encode_ipod action will be used to encode the material into the h264 format that has been determined to be the best for publication to YouTube for the best conversion.
To do this, change the existing encode_ipod to use the h264 encoding:
<key>encode_youtube</key>
<dict>
<key>arguments</key>
<array>
<string>encode</string>
<string>--basedir=$$Base Directory$$</string>
<string>--input=$$Content File Basename$$$$Content File Extension$$</string>
<string>--output=$$Content File Basename$$-youtube.m4v</string>
<string>--encoder=h264</string>
</array>
<key>command</key>
<string>/usr/bin/pcastaction</string>
<key>dependsOnTasks</key>
<array>
<string>preflight</string>
</array>
</dict>
You might also want to change the name of this action to encode_youtube. The rest of the action is correct, but depending on the complexity of your workflow, you may also need to change the dependsOnTasks element to the correct pre-condition.
Publishing to YouTube
The YouTube publication action relies on an external script, which takes the information and publishes the content to YouTube. The script is actually a wrapper around a Java application that uses the YouTube API Library to upload the video to YouTube. To use it, you need to modify the Java source code with your YouTube API key. The YouTube Uploader code is shown in the listing below:
import com.google.gdata.client.*;
import com.google.gdata.client.youtube.*;
import com.google.gdata.data.*;
import com.google.gdata.data.geo.impl.*;
import com.google.gdata.data.media.*;
import com.google.gdata.data.media.mediarss.*;
import com.google.gdata.data.youtube.*;
import com.google.gdata.data.extensions.*;
import com.google.gdata.util.*;
import java.io.IOException;
import java.io.*;
import java.net.URL;
class Uploader {
public static void main (String [ ] argv) throws IOException {
You then replace the client ID and developer key:
YouTubeService service = new YouTubeService("CLIENT_ID","DEVELOPER_KEY");
This will hold the completed video entry:
VideoEntry createdEntry = null;
You then capture the username/password login information from the command line. This will be automatically populated by the Podcast Producer workflow:
try {
service.setUserCredentials(argv[2], argv[3]);
}
catch (Exception e) {
System.err.println("Failed to login");
}
Create a new video object, and set the physical location of the video:
VideoEntry newEntry = new VideoEntry();
newEntry.setLocation("Mountain View, CA");
Next, create a media group, and set the category for the uploaded video. YouTube supports hundreds of different categories, and you may want to change these settings to another category (see the YouTube API documentation for more details):
YouTubeMediaGroup mg = newEntry.getOrCreateMediaGroup(); mg.addCategory(new MediaCategory(YouTubeNamespace.CATEGORY_SCHEME, "Films")); mg.addCategory(new MediaCategory(YouTubeNamespace.DEVELOPER_TAG_SCHEME, "blogs")); mg.setPrivate(false);
Set the metadata about the video, using the information supplied on the command line:
mg.setTitle(new MediaTitle()); mg.getTitle().setPlainTextContent(argv[0]); mg.setKeywords(new MediaKeywords()); mg.getKeywords().addKeyword(argv[0]); mg.setDescription(new MediaDescription()); mg.getDescription().setPlainTextContent(argv[0]);
Specify the source location for the video you want to upload:
MediaFileSource ms = new MediaFileSource(new File(argv[1]), "video/quicktime"); newEntry.setMediaSource(ms);
Specify the URL where you want to upload the YouTube information:
String uploadUrl = "http://uploads.gdata.youtube.com/feeds/api/users/default/uploads";
Start the upload:
try {
createdEntry = service.insert(new URL(uploadUrl), newEntry);
}
catch (Exception e) {
System.err.println("Failed to upload video");
}
Once the video is uploaded, you have to wait for the video to be successfully processed before you get the YouTube unique ID for the video. So wait, checking the processing status until either the video has been processed or there is a failure.
while(createdEntry.isDraft()) {
YtPublicationState pubState = createdEntry.getPublicationState();
if(pubState.getState() == YtPublicationState.State.PROCESSING) {
try {
Thread.sleep(60000);
}
catch (Exception e) {
System.err.println("Sleep interrupted");
}
}
else {
System.exit(1);
}
}
Write out the YAML file required by Podcast Producer with the published video information:
try {
FileWriter yamlstream = new FileWriter("youtube_publish_description_file.yaml");
BufferedWriter yamlout = new BufferedWriter(yamlstream);
YouTubeMediaGroup mediaGroup = createdEntry.getMediaGroup();
MediaPlayer mediaPlayer = mediaGroup.getPlayer();
yamlout.write("---\n");
yamlout.write("url: " + mediaPlayer.getUrl() + "\n");
yamlout.close();
}
catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
}
To compile, you need to use the YouTube API Library:
$ javac -cp java/lib/gdata-core-1.0.jar:java/lib/gdata-media-1.0.jar:java/lib/gdata-youtube-2.0.jar Uploader.java
To use the script, supply the title of the post, and the location of the source video file. You also need to provide the YouTube username/password combination on the command line that you can take from the Podcast Producer global properties:
<key>publish_youtube</key>
<dict>
<key>arguments</key>
<array>
<string>shell</string>
<string>--basedir=$$Base Directory$$</string>
<string>--</string>
<string>publish_youtube</string>
<string>$$YouTube Login$$</string>
<string>$$YouTube Password$$</string>
<string>$$Content Title$$</string>
<string>$$Content File Basename$$-youtube.m4v</string>
</array>
<key>command</key>
<string>/usr/bin/pcastaction</string>
<key>dependsOnTasks</key>
<array>
<string>encode_youtube</string>
</array>
</dict>
Now create a small shell script file that will set the correct path and call the Java Uploader class.
The script should be called publish_youtube and it needs to be placed in the workflow's resources
directory. Also, copy the compiled Java Uploader class (Uploader.class) and the JAR files from
the YouTube API into the 'resources directory'. The contents of the script are below:
#!/bin/bash /usr/bin/java -cp java/lib/gdata-core-1.0.jar:java/lib/gdata-media-1.0.jar:java/lib/gdata-youtube-2.0.jar:. Uploader $*
In addition to setting the action, you must also make sure that the YouTube publication script is added to the resources for the workflow so that it is available to Podcast Producer during the execution of the podcast production.
These two actions we've completed provide you with all of the information and structure needed within the workflow to encode and then publish to YouTube any video or audio supplied.
Creating Additional YouTube Workflows
Our standard workflow publishes the file to YouTube, but makes no attempt to record the location of the file into the system in any way. To improve that situation, the standard templates that are used when publishing to the Leopard Server blog can be used and extended so that they embed the YouTube video that you created into the blog post instead.
To do this, take the HTML template file from one of the existing workflows and use that as the basis of the template that embeds the YouTube video content. The actual format of the HTML templates is a Ruby file that will be parsed, and the content of the file will also be parsed by Ruby before publication. This allows various settings and information, such as the name of the file and its size, to be calculated and used to replace the real values within the HTML template during publication.
You can see a sample of one of the original HTML templates here:
% description = (properties["Description"] || "")
% ipod_publish = ((YAML::load_file("ipod_publish_description_file.yaml")
rescue nil) || {})
% ipod_publish_poster_url = (ipod_publish[:poster_url] || "")
% ipod_publish_url = (ipod_publish[:url] || "")
% ipod_publish_width = (ipod_publish[:width].to_i <= 480 ?
ipod_publish[:width].to_i : 480).to_s
% ipod_publish_height = (ipod_publish[:width].to_i <= 480 ?
ipod_publish[:height].to_i :
(480.0/ipod_publish[:width].to_f*ipod_publish[:height].to_f).to_i)\
.to_s
<%= h(description) %>
<br>
<br>
<img src=<%= quotify(ipod_publish_poster_url) %> alt=<
%= quotify(ipod_publish_url)
%> width=<%= quotify(ipod_publish_width) %> height=<%= quotify(ipod_publ\
ish_height) %> class="aligncenter posterimg" />
In the example, the code takes the information about the podcast that has been produced, calculates the correct viewport setting for the size of the video material, and then generates an HTML fragment that contains the structure for embedding the podcast directly within the blog post entry.
To embed a YouTube video into the HTML, you can use the embedding fragment provided automatically on any YouTube page. The basis of the fragment is the same for any video, only the reference number required to select the video is significant. You can use the same basic structure with any YouTube video reference.
The publication script used in the main workflow returns the YouTube reference number, so replacing the information is straightforward. A sample of the YouTube embedding HTML is shown here:
<object width="425" height="344">
<param name="movie" value="http://www.youtube.com/v/4itNWe27d38
&hl=en&fs=1">
</param>
<param name="allowFullScreen" value="true">
</param>
<embed src="http://www.youtube.com/v/4itNWe27d38&hl=en&fs=1"
type="application/x-shockwave-flash" allowfullscreen="true"
width="425" height="344">
</embed>
</object>
You exchange the information about the video through the YAML file that contains the information, thus you can change the template to that shown here:
% description = (properties["Description"] || "")
% ipod_publish = ((YAML::load_file("ipod_publish_description_file.yaml")
rescue nil) || {})
<%= h(description) %>
<br>
<br>
<object width="425" height="344">
<param name="movie" value="http://www.youtube.com/v/<%=
quotify(ipod_publish_ref) %>&hl=en&fs=1">
</param>
<param name="allowFullScreen" value="true">
</param>
<embed src="http://www.youtube.com/v/<%= quotify(ipod_publish_ref) %>
&hl=en&fs=1" type="application/x-shockwave-flash" allowfullscreen="true"
width="425" height="344">
</embed>
</object>
You can use the same method to mail the content, or a URL to the content, to subscribers of your group blog, as you would with any other workflow.
Conclusion
Publishing to YouTube can be done in a reasonably straightforward manner when you start with the right assumptions. The main considerations are that you encode the video in a quality as high possible to ensure that when the video is processed by YouTube for publication, the quality is of a similar value. The upload process relies on an additional script to do the publication up to YouTube, and you must have a suitable API key and login, but in other respects the structure and process are no different from publication through to the local resources such as the blog or wiki. By allowing you to specify any script for execution, the workflow actions are practical and flexible.
Updated: 2009-01-09
Related Articles
- Podcast Producer: Anatomy of a Workflow
- Podcast Producer: Writing Actions
- Podcast Producer: Using the Command Line
- Podcast Producer: Scheduling Podcasts
- Leopard Technology Series for Developers: Server Overview
Resources
- Uploader Project (.dmg, 464Kb)
- YouTube Workflow Project (.dmg, 504Kb)
- Get a YouTube API Key
- YouTube Developer's Guide
- Reference Library: Mac OS X Server
- Mac OS X Server Podcast Producer Workflow Tutorial (PDF, 1MB)
- Mac OS X Server Podcast Producer Administration (PDF, 2.1 MB)
- Leopard Server QuickTours
(in iTunes) - Quick Tips Videos
- Podcast Producer Mailing List
- Podcast Producer Technology Brief (PDF, 1.2 MB)