Monday, August 23, 2010

Embedding Internal Streaming Videos in Your Organization with Confluence

At my company, we run a seminar series where presenters get to show off some of the cool stuff they're working on. Often, these are outside speakers sharing their latest research. We also use it as an opportunity for our own staff to share knowledge with the company or use it as a broadcast mechanism for informing staff about a new policy or procedure.

This sort of thing isn't new, pretty much all organizations do it. Google posts their technical talks online and shares it with the rest of the world.

The trouble is, within our company, if you're not available to be present for the talk, you've lost out. Well, that's not cool. What if it was really critical to what you're working on? Or, what if you attended, but can't remember that one brilliant point the speaker made? What about new hires who weren't around at the time of the talk? Why does that knowledge have to be lost?

Quite simply, it doesn't. We recently started recording our seminars, purchasing a Flip Mino HD for the task. Simple to use, it produces wonderful videos in clear h.264 encoded MP4 files.

But here comes the problem, where to put these videos for everyone to find?

Brainstorming a Solution

Well, we could just put them on the file system, organize them in subdirectories and try to give them easy to remember names. But who's going to go navigate through a maze of a file system directory hierarchy? There's gotta be a better way. Oh wait, there is... the wiki!

Attaching Videos to the Wiki

How about we just attach these video files to a wiki page and just embed the video as easy as an image? Well, a few problems. First, while Confluence supports embedding a number of multimedia formats (e.g., Flash, Windows Media, AVI files), MP4 with h.264 encoding is not one of them. We could post-process our media files and covert them to a format that Confluence supports, but we run into another problem, large file sizes. Our seminars run 45-60 minutes in length, generating a video file in the 1-2 gigabyte range. If we kept uploading them and attaching them to pages, we'd quickly run out of space. Furthermore, every time someone hit that page, they'd be downloading 1-2 gigs of data, which could be a nasty hit to our network.

Linking to Videos on the File System from the Wiki

Instead, we could simply link to the video file on the file system from the wiki. But, that doesn't feel too satisfying. Furthermore, while it might work for some users who are using Internet Explorer, Mozilla Firefox users would have to take extra steps because Firefox forbids linking to your local file system as a security precaution.

Using Video Hosting Services and the Widget Macro

So what other solutions exist out there? What we want is our own YouTube. Wait, why not just use YouTube? And there are a whole bunch of other services out there like Vimeo and Episodic if YouTube isn't to our liking. Furthermore, we can embed them directly using the Widget Macro. Sounds like a great solution. Unfortunately, most organizations (including my own) don't feel comfortable putting internal content out on the web, either for all to see or even if it's private.

Using a Hosted Media Server and a Custom Macro

So we're back to wanting our own YouTube. Well, what options exist out there? There's a few, but most of them cost money. For example, the Adobe Flash Media Server suite of products is pretty popular, but we were looking for a lost-cost alternative, free being even better. Red5 is an Open Source Flash Server that handles streaming media. But, is there something even easier for us to use? After some searching, we found that we could simply run our own Apache web server with the h.264 streaming module and JW Player. Then all we had to do was implement a custom macro to serve it up.

Implementing a Solution

So we decided to run an Apache web server with the h.264 streaming module and using JW Player with a custom user macro. It was actually pretty simple to do. Let me show you how.

Installing Apache and h.264 Streaming Module

First up, go ahead and download and install Apache HTTP Server and the h.264 streaming module for Apache. You could also run a different web server, but we went with Apache. Also, note that the h.264 module is free to use for non-commercial usage. So, if you're planning on using this for commercial purposes, then you'll have to purchasing their commercial license (which is pretty inexpensive).

You might want to name your HTTP server something like http://video.mycompany.com/ or http://media.mycompany.com/.

Next, download the JW Player by Longtail Video. You'll need to drop the player.swf and swfobject.js into a specific web accessible directory in your Apache installation. Similar to the h.264 streaming module, JW Player is only free for non-commercial usage. So, if you're going to use it for commercial purposes, purchase a commercial license (again, really cheap).

User Macro

Finally, you'll want to create a user macro in your Confluence installation. At my company, we set this up as {video}. The video macro takes a few required parameters. First, you'll need to give your video a unique name using the name parameter. This is just to give Confluence a way to reference where to put video in your page. The more important required parameter is url. You'll want to replace this with the full url of where your video file is (e.g., url=http://video.mycompany.com/path/to/videofile.mp4). In addition to the required parameters, you can also specify a custom width and height in pixels. And there you have it. You'll be able to embed h.264 files (and other files that JW Player supports) as streaming videos directly in Confluence. If you want to get fancy, there are a bunch of specialized parameters you can add to JW Player such as skinning, fullscreen, autoplay, etc.). Take a look at the JW Player documentation for the full range of options.
#set($width=400)
#set($height=300)
#if($paramwidth)
#set($width=$paramwidth)
#end
#if($paramheight)
#set($height=$paramheight)
#end
{html}
<div id="$paramname">
The player will show in this paragraph</div>

<script src="http://video.mycompany.com/swfobject.js" type="text/javascript"></script>
<script type="text/javascript">

var s1 = new SWFObject('http://video.mycompany.com/player.swf','player','$width','$height','9.0.115');
s1.addParam('allowfullscreen','true');
s1.addParam('allowscriptaccess','always');
s1.addParam('flashvars','file=$paramurl');
s1.write('$paramname');

</script>

{html}
That's our solution to embed streaming video into a Confluence installation. Our seminars (and other videos, like software demos and walkthroughs) are now captured. That knowledge is kept safe and secure behind our own firewall where we can share those videos internally without exposing them to the external network. Users can skip to any point in the video without having to buffer the whole video first.

Using Apache, the h.264 streaming module, and JW Player is just one solution. How do you share your videos at your company? Share your experiences in the comments.

39 comments:

  1. We had the same issue and initially went down the user macro route. But eventually encapsulated this into a full blown plugin and gave the option to overlay the video in a fancybox. One thing I think would be nice would be able to include the player as web resource (in a full blown plugin) but sadly only js and css file types can be included.

    We either stream from http or a helix flash server.
    Nice write up thanks for sharing

    ReplyDelete
  2. @Shaun

    Thanks Shaun! Yeah, I had thought about packaging up this user macro into a plugin, but it does take some extra installation outside of just the plugin framework. Also, I have it on good authority that an upcoming release of Confluence may allow user macros to show up in the Macro Browser, which will help out with the discovery problem.

    Would love hearing more about how much more customization went into your full blown plugin. Do you have any details anywhere?

    ReplyDelete
  3. One question... can you control "autoplay" with this set up? In other words, do the videos start playing automatically when the wiki page loads? If so, can you control that behavior?

    Thanks.

    ReplyDelete
  4. @Rob

    The video does not start playing automatically. It does, however, begin to buffer. You can configure a whole bunch of variables: http://developer.longtailvideo.com/trac/wiki/Player5FlashVars . There's even a wizard on their website http://www.longtailvideo.com/support/jw-player-setup-wizard

    ReplyDelete
  5. Brad, this write up was very helpful. My organization was faced with an almost identical situation that you described with only one addition:

    We also want to prevent our employees from downloading a copy of the video file.

    Also, I encountered a bug with your implementation here -- namely that you're not actually streaming your videos from what I can tell.

    Based on the user macro you wrote you have not configured your JW player to "stream" the movie. It's just buffering the whole movie as a file download.

    Here's a modified section of your (sorry, the comment editor wouldn't allow me to post the whole macro due to the use of included html tags.) user macro which adds the "http pseudo-streaming" protocol to the JW player.


    var so = new SWFObject('http://videos.mycompany.com/jwplayer/player.swf','playerID','$width','$height','9.0.115');

    so.addParam('allowfullscreen','true');
    so.addParam('allowscriptaccess','always');
    so.addVariable('file', '$paramurl');
    so.addVariable('provider','http');
    so.write('$paramname');

    The important bit is the addition of the "provider = http" variable.

    There's more information on the JW site about this protocol: http://www.longtailvideo.com/support/jw-player/jw-player-for-flash-v5/12534/video-delivery-http-pseudo-streaming

    Once the player is setup to utilize the streaming feature from your streaming http server you should notice two changes:

    1) Your apache logs will show that the jw player is requesting offsets (of xx.xx seconds) of the video file as users jump around the clip.

    2) Your player will allow you to jump to unbuffered sections of the video.

    The second modification I made was a set of apache rewrite rules that redirect the user to a static Copyright Warning html page if they attempt to download the raw .mp4 file.

    For security reasons I cannot share the implementation details of those rewrite rules since that knowledge could be used to help bypass the restrictions.

    Again, thank you for doing the bulk of the work finding all the right tools to pull together into a free streaming solution, it saved me a ton of time and I'm very happy with the final result.

    Thanks!

    ReplyDelete
  6. @Alex Thanks for the tip! (Sorry your original comment got caught in the spam filter, but I fixed it). Didn't realize about the provider=http issue, we can certainly jump around to unbuffered sections of the video, but I'll do some testing to make sure.

    ReplyDelete
  7. Brad,

    Thank you for an informative post. I followed your steps, but keep on getting a window with "task queue failed at step 5: playlist could not be loaded due to crossdomain policy restrictions.". Have you ever seen this problem? Thank you!

    ReplyDelete
  8. @Asya Hrmm, haven't run into that problem before. However, the JWPlayer website has some information on that here: http://www.longtailvideo.com/support/jw-player/jw-player-for-flash-v5/12541/crossdomain-file-loading-restrictions

    ReplyDelete
  9. Thank you, Brad. This worked for me:

    {videos:url=http://URL/videos/file.mp4}

    When I was adding it using macros, url= wasn't part of the line.. Thanks again!

    ReplyDelete
  10. Morgan RobertsonMay 1, 2012 at 7:55 PM

    I just set this up for our company. It works great.

    The user macro no longer works though as confluence has changed and I believe jwplayer has too. This is the macro I am using (remove spaces from script/div tags:

    ## @param filename:title=File Name|type=string|desc=Enter name of file copied to \\vidstream\videos|required=true|multiple=false
    ## @param vidname:title=Video Name|type=string|desc=A unique element name is required (alphanumeric only, no spaces)|required=true|multiple=false

    < script type="text/javascript" src="http://video.mycompany.com/jwplayer/jwplayer.js"> 

    < div id="$paramvidname">Streaming Video:< /div>

    < script type="text/javascript">
    jwplayer("$paramvidname").setup({
    flashplayer: "http://video.mycompany.com/jwplayer/player.swf",
    file: "http://video.mycompany.com/videos/$paramfilename",
    provider: 'http',
    height: 270,
    width: 480
    });

    ReplyDelete
  11. Thanks I set this up and works great.

    One thing I wanted on the Wiki though was Chapters. We have long presentations (1hr +) So I'd like to incorporate chapters like this:

    http://www.longtailvideo.com/support/jw-player/jw-player-for-flash-v5/17248/providing-video-chapter-markers

    Anyone have any ideas on how I could get this to work in Confluence?

    ReplyDelete
  12. Thank you for this post. It has let me find the missing links.

    I did it with Adobe Store Media Player. http://www.osmf.org/strobe_mediaplayback.html

    and Adobe HTTP Dynamic Streaming module for Apache HTTPD. http://help.adobe.com/en_US/HTTPStreaming/1.0/Using/index.html

    Works great!

    ReplyDelete
  13. WOW, thanks a lot! Do you know how to embed an html5 player in to Confluence? Tried googling, but my skills are lacking.

    ReplyDelete
  14. @Dmitriy I believe that the JWPlayer as listed also has an HTML5 option if the browser supports it. I'd look into the documentation there about how to configure things.

    ReplyDelete
  15. If you like to use a html5 video player, feel free to take my videojs macro:

    ## @param MP4:title=MP4 Video Pfad|type=string|required=false|desc=IE 9+, Safari 3+, Chrome 5+, iOS 3+, Android 2+
    ## @param WebM:title=WebM Video Pfad|type=string|required=false|desc=IE 9+, Firefox 4+, Chrome 6+, Opera 10.6+, Android 2.3+
    ## @param OGG:title=OGG Video Pfad|type=string|required=false|desc=Firefox 3.5+, Chrome 5+, Opera 10.5+

    ## @param Poster:title=Vorschaubild Pfad|type=string|required=false|desc=Als JPG, PNG oder GIF

    ## @param Width:title=Videobreite|type=string|required=true|desc=Angabe in px
    ## @param Height:title=Videohöhe|type=string|required=true|desc=Angabe in px

    #set($preload="Ja")
    ## @param Preload:title=Preload|type=enum|enumValues=none,metadata,auto|default=Ja|desc=Soll das Video vorab geladen werden?
    #if($paramPreload)
    #set($preload=$paramPreload)
    #end

    #set($controls="Ja")
    ## @param Controls:title=Controls|type=enum|enumValues=Ja,Nein|default=Ja|desc=Sollen die Controls unterhalb des Videos angezeigt werden?
    #if($paramControls)
    #set($controls=$paramControls)
    #end

    ## @param Loop:title=Loop|type=enum|enumValues=Ja,Nein|default=Nein|desc=Soll das Video endlos oft abgespielt werden?

    ## @param Autoplay:title=Autoplay|type=enum|enumValues=Ja,Nein|default=Nein|desc=Soll das Video automatisch abgespielt werden?

    < div class="html5videoplayer">
    < link href="http://vjs.zencdn.net/4.0/video-js.css" rel="stylesheet">
    < script src="http://vjs.zencdn.net/4.0/video.js">< /script>

    < video
    id="html5video"
    class="video-js vjs-default-skin"

    preload="$preload"

    #if($controls == "Ja")
    controls
    #end

    #if($paramLoop == "Ja")
    loop
    #end

    #if($paramAutoplay == "Ja")
    autoplay
    #end

    width="$paramWidth"
    height="$paramHeight"

    #if($paramPoster && $paramPoster.length()>0)
    poster="$paramPoster"
    #end

    data-setup="{}">
    #if($paramMP4 && $paramMP4.length()>0)
    < source src="$paramMP4" type='video/mp4'>
    #end

    #if($paramWebM && $paramWebM.length()>0)
    < source src="$paramWebM" type='video/webm'>
    #end

    #if($paramOGG && $paramOGG.length()>0)
    < source src="$paramOGG" type='video/ogg'>
    #end

    ReplyDelete
    Replies
    1. Thanks for the macro Philipp.
      I am trying to play a video attached to a Confluence page using a html 5 player.
      It is working fine except that I cannot jump ahead in the video like I can if the video is stored on an apache webserver.
      Has anyone experienced that problem? Does anyone has a solution?
      Thanks!

      Delete
  16. This comment has been removed by a blog administrator.

    ReplyDelete
  17. There is a basic HMTL5 video solution at https://answers.atlassian.com/questions/203119/answers/12166696 which uses an external webserver with Confluence and its built-in HTML add-on to do this fairly easily using any standard HTML5 script.

    ReplyDelete
  18. Incredibly helpful, thanks so much for sharing your solution Brad!

    ReplyDelete
  19. Can any one tell me that is there any on the web classes for Search engine marketing, because I wish for to learn more on the topic of Search engine marketing.

    --------------------
    Leaders

    ReplyDelete
  20. Why YouTube movies are shared everywhere? I think one motive is that these are trouble-free to obtain embed code and paste that code anyplace you would like.Elo Boosting

    ReplyDelete
  21. It's definitely not hard to find any matter on web when appeared differently in relation to books, as I wellspring this article at this website.Cheap Elo Boost

    ReplyDelete
  22. Greetings friends, lovely post and not too bad promising commented at this spot, I am as a general rule getting a charge out of by these.Lol Boost

    ReplyDelete
  23. On every weekend, we all mates jointly used to watch movie, because enjoyment is also essential in life.Web application service singapore

    ReplyDelete
  24. I am keen of learning Flash, is there any piece of writing related to Flash, if okay, then please post it, thanks.Web development company singapore

    ReplyDelete
  25. This is great! It really shows me where to expand my blog. I think, in future I must try to write a book to go along with my blog, but we will see. In the end, it’s a good post with useful tips and ideas.

    Dissertation state

    ReplyDelete
  26. Wonderful, what a blog it is! This webpage provides useful data to us, keep it up.

    Mobile repairing franchise

    ReplyDelete
  27. Hi, i read your site sporadically and i claim a comparative one and i was simply thinking about whether you get a great deal of spam comments? On the off chance that so how would you stop it, any module or anything you can exhort? I get so much of late it's making me crazy so any help is especially valued.Seo services singapore

    ReplyDelete
  28. Its pleasant humorous YouTube video, I always go to go to see YouTube web page designed for comical videos, since there is much more stuff available.

    Blood Sugar Monitoring: Why and When to check it

    ReplyDelete
  29. We need more info like this on a daily basis. Hope you'll regularly update this web in the future. This article is pretty interesting since there's so many useful info inside. Thank you.


    Zenith nutrition green coffee bean

    ReplyDelete
  30. Howdy, its particular post concerning media print, we in general understand media is a magnificent wellspring of assurances.
    Tdock

    ReplyDelete
  31. Hurrah, that is the thing that I was investigating for, what a stuff! existing here at this online journal, thanks administrator of this site.
    Honda car showroom in Thane

    ReplyDelete
  32. It’s always so sweet and also full of a lot of fun for me personally and my office colleagues to search your blog a minimum of thrice in a week to see the new guidance you have got.
    Retaining Wall Contractors Rancho Mirage

    ReplyDelete
  33. Do you have a spam issue on this website; I also am a blogger, and I was wanting to know your situation; many of us have developed some nice methods and we are looking to trade methods with others, why not shoot me an e-mail if interested.
    Mac Photo Editor

    ReplyDelete
  34. It seems basically as it was a shocking day in Alaska.I think you benefitting however much as could be normal from your time there in light of the way that it is so cool to meet knew people all over the place all through the world and they can leave best review in your site.
    Phone repair franchise

    ReplyDelete
  35. I am grateful to you in light of the way that your article is astoundingly critical for me to proceed with my examination in same zone. Your refered to blueprints are all that much essential to my examination field.This is phenomenal! It truly shows to me where to develop my online journal. I verify that at last on I may attempt to make a book to oblige my web journal, yet we will see.Good post with steady tips and considerations.
    zwangerschapsmassage amsterdam

    ReplyDelete
  36. In no time I am set up to do my breakfast, while having my breakfast returning again to examine further news.
    Fiscalist amsterdam

    ReplyDelete
  37. I'm thoroughly impressed with this place! Every article I've read has been very intriguing and interesting, kudos! Do keep it coming. If you are looking for help with company incorporation singapore check out the best company incorporationprovider!

    ReplyDelete
  38. happy to observed this blog. i have some statistics associated with this weblog and that i would love to share with all its readers. sincerely it is going to help all people and aware human beings with a few greater informed factors.

    =====================================================
    best web development software Company in Kanpur

    ReplyDelete