Display YouTube Videos Safely & Save Moderation Time

Marshall Bauernfeind

YouTube ID Issue

YouTube is a BIG DEAL with today’s youth. Allowing users to share YouTube videos within your application increases user engagement and retention. However, consider what might happen if inappropriate content such as sex, violence, or personally identifiable information (PII) is shared. In this post I will walk you through the process to provide a safe environment that parents will trust and save precious moderator hours by building a list of already-approved and already-rejected videos.

Clip of Inversoft's Sean Bryant's puppy "Bodhi"

Approval Process: YouTube ID White & Black List

Allowing kids to post and share videos without being reviewed first by a moderator is risky, to say the least. Even if you allow users to report inappropriate content, it would not take more than one angry parent seeing pornography on your site to ruin your reputation for good. Therefore you must watch every video before it is made public in your community.

Kids love to share videos, particularly the same video over and over. Your moderation efforts will be taxed if a single video is reviewed 700 times! However, you can reduce the burden on moderators by employing a simple whitelist/blacklist technique on YouTube videos. Each YouTube video has a unique ID that can be saved after a moderator watches it. The next time the same video is posted, you can check the whitelist/blacklist to determine if it has already been moderated.

The YouTube ID is embedded in the URL, but the format of the URL is not always the same. In order to extract the ID, use a regular expression such as:

%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i

Source: Stack Overflow

Create a table in your database with two columns:

create table youtube_video_approvals (
id varchar(255) not null,
approved boolean not null,
primary key (id)

Now you can query the database to see if a moderator has already approved or rejected a video with this select statement:

select approved from youtube_video_approvals where id = ‘YouTube-ID-Here’;

If the table doesn’t contain a record for a specific video, after the moderator has approved or rejected it, you can insert the result into the table like this:

insert into youtube_video_approvals (id, approved) values 
(‘YouTube-ID-Here’, true);


Watch Out! Content Updates from the YouTube Video Editor

With the YouTube video editor, the user that submitted the video to YouTube can change the content of the video to:

    • Overlay a music soundtrack. (Luckily, users cannot upload their own soundtrack. They must select from a predefined list.)
    • Trim the video length.
    • Enhance the video by rotating it or adding visual effects such as “cinemascope”.
    • Change the title and description.
    • Add or update annotations.
    • Add or update the caption.

The same video as above with the Title changed

When any of the above updates are made, the ID of the YouTube video does not change. Therefore, even if you review every video prior to them being public, the video content can be changed without your knowing. The YouTube API provides a partial solution. When you query the API for a specific video, the response contains an element called <updated>. The element contains an ISO date-time value. This element changes each time a video is updated by adding a soundtrack, trimming the video length, enhancing the video, or changing the title or description. However, this value does notchange when annotations are added or when the caption is modified. Don’t worry, I’ll cover annotations a little later.

Checking for Video Updates

Users cannot add video clips nor upload a custom soundtrack to an existing video. This means you can be confident that the video/audio portion will always be appropriate once it is reviewed by a moderator even after it has been edited. However, if you are displaying the title or description, you should check if either have been modified by querying the YouTube API before playing the video.  If the <updated> element indicates that the video has  been changed, you can run the title and description through an automated profanity filter such as CleanSpeak or have a moderator review the video again. In order to handle when videos are updated, we need to update our table to include the updated date returned from the YouTube API. Here is the new table definition:

create table youtube_video_approvals (
id varchar(255) not null,
approved boolean not null,
updated timestamp not null,
primary key (id)

When a new video is submitted or an approved video is about to be played, you must first query the YouTube API to retrieve the updated date. The following is an example cURL command  to retrieve the updated value for a YouTube video:

% curl "https://gdata.youtube.com/feeds/api/videos/OsGY8VHVUOQ?v=2" | 
tidy -xml

The XML result has been trimmed for brevity:


Parse the XML and store the <updated> value as a timestamp. Whenever a video is played from your application, use an onplay() event to check the <updated> value of the video by querying the API.

Once you have the updated value for the video, query the database to see if it has changed:

select approved, updated from youtube_video_approvals 
where id = ‘YouTube-ID-Here’;

If it has changed, run the title and description of the video through your profanity filter to see if it finds anything. The title and description of the video are part of the XML response from the YouTube API and are stored in these XML elements:

<media:description type='plain'>Fun day at the park!</media:description>

If your profanity filter finds a match, you can immediately set the approved flag of the video to false and remove the video from public display.

You may also chose to have a moderator review the content again. In this case,  the type of the approved column must be a tri-state. You can use the values approved, rejected, and pending to indicate the approved status of a particular video. Resubmit the video for moderator approval and set the approved column to pending.

Disable Annotations & Captions

YouTube Annotations are a way to layer text bubbles, links, and other content over a video. Captions provide the ability to add text for hearing-impaired or multilingual support and can be easily edited. When an annotation or caption is added/modified, the <updated> value does not change. To prevent inappropriate content, you must disable these features from being displayed.

Added text bubbles, but the id and <updated> values do not change

When playing YouTube videos within your application, you have a choice between an embedded player and a chromeless player. Annotations and captions are disabled in chromeless players. Since you will also be able to customize the look and feel of a chromeless player to match your interface, chromeless is a clear winner over embedded players.

Building a chromeless player is beyond the scope of this article, but there are numerous sources available online. A few are listed at the end of this post.

Note: Using an embedded player is tempting since it is very easy to add to your application compared to a chromeless player thus saving development time. You can disable annotations & captions by default when using an embedded player, but the user can easily reenable them. If YouTube modified the <updated> date and provided the ability to query their API to retrieve the content of annotations, the technique of checking the last updated date and using a text filter above could be applied. As of this writing, YouTube does not provide this ability.

What about Vimeo?

As of this writing, Vimeo does not provide any type of last-updated date or versioning as part of their API. After uploading a video and an ID is associated, the entire video can be very easily changed using their replace video feature. Since there is no ability to monitor whether a video will be appropriate or not even after it has been reviewed by a moderator, we do NOT recommend embedding Vimeo content in your site!

Allowing kids to engage by sharing YouTube videos within your application is a big win for user experience and repeat visitors. Be sure your brand is safe by following the steps outlined above:

      • Review each video prior to being public and store the ID as approved or rejected.
      • Immediately publish or reject new videos when they have already been reviewed to save moderator hours.
      • If displaying the title or description of a video, use the YouTube API to be sure the <updated> value has not changed prior to displaying the video.
      • If the <updated> value has changed, use a filter to check the title and description for inappropriate content.
      • Use a chromeless player to show YouTube content without annotations or captions.

Building a chromeless YouTube player