Flash and Flash Video EPiServer Dynamic Content
Posted on November 17, 2009 by Frederik Vig in EPiServerI’ve extended Allan Thræn’s Insert Flash elements in the Editor as Dynamic Content, to now use swfobject for a more standards-friendly way of embedding Flash. I’ve also added support for videos, by using Flowplayer, which is a popular Flash Video Player.
Flowplayer
Edit mode
Solution
Update 18.11.2009
I’ve updated the code to now also use fallback content for users that do not have Flash or JavaScript installed/enabled. When using the fallback content with regular Flash files (.swf), whenever someone who doesn’t have Flash or JavaScript installed/enabled it will display.
For Flowplayer it behaves a bit differently, the fallback content will be displayed when the page loads, when someone clicks it, the video will start. So with no fallback content, the video plays automatically when the page loads. With fallback content (could be an image for instance), the user has to click the image (in this case), to start the video. Here’s an example.
The code is almost identical to Allan’s, the only thing I’ve changed is the Render method and I’ve added an extra text field for the id (must be unique for the page).
Since the fallback content contains HTML code I had to update the code for getting and setting the State. Previously I just used Allan’s code, which used | to separate the different values. But now I had to use XML and Serialization. It was a little tricky at first, but thankfully I came across Anders’ post Dynamic content and State attribute.
using System; using System.Globalization; using System.Xml.Linq; using EPiServer; using EPiServer.Core; using EPiServer.DynamicContent; using EPiServer.Editor; using EPiServer.SpecializedProperties; namespace FlashDynamicContent { public class FlashDynamicContent : IDynamicContent { protected PropertyDocumentUrl flash; protected PropertyNumber width; protected PropertyNumber height; protected PropertyXhtmlString fallbackContent; /// <summary> /// Setup properties /// </summary> public FlashDynamicContent() { flash = new PropertyDocumentUrl { Name = "Flash file " }; width = new PropertyNumber(300) { Name = "Width" }; height = new PropertyNumber(300) { Name = "Height" }; fallbackContent = new PropertyXhtmlString { Name = "Fallback content", EditorToolOptions = EditorToolOption.All ^ EditorToolOption.Font ^ EditorToolOption.DynamicContent }; } public System.Web.UI.Control GetControl(PageBase hostPage) { throw new NotImplementedException(); } public PropertyDataCollection Properties { get { return new PropertyDataCollection { flash, width, height, fallbackContent }; } } public string Render(PageBase hostPage) { if (flash.ToString().EndsWith(".swf", true, CultureInfo.InvariantCulture)) { if (!hostPage.ClientScript.IsClientScriptIncludeRegistered("swfobject")) { hostPage.ClientScript.RegisterClientScriptInclude("swfobject", "http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"); } hostPage.ClientScript.RegisterStartupScript(GetType(), "swfobject" + this.GetHashCode(), string.Format("swfobject.embedSWF(\"{0}\", \"flash{3}\", \"{1}\", \"{2}\", \"9.0.0\", false);", flash, width, height, this.GetHashCode()), true); return string.Format("<div id=\"flash{0}\">{1}</div>", this.GetHashCode(), fallbackContent); } if (!hostPage.ClientScript.IsClientScriptIncludeRegistered("flowplayer")) { hostPage.ClientScript.RegisterClientScriptInclude("flowplayer", "/Flowplayer/flowplayer-3.1.4.min.js"); } hostPage.ClientScript.RegisterStartupScript(GetType(), "flowplayer" + this.GetHashCode(), string.Format("flowplayer(\"flash{0}\", \"/Flowplayer/flowplayer-3.1.5.swf\", \"{1}\");", this.GetHashCode(), flash), true); return string.Format("<div style=\"width:{0}px;height:{1}px\" id=\"flash{2}\">{3}</div>", width, height, this.GetHashCode(), fallbackContent); } public bool RendersWithControl { get { return false; } } public string State { get { return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(new XElement("flashcontent", new XElement("flash", flash), new XElement("width", width), new XElement("height", height), new XElement("fallbackcontent", new XCData(fallbackContent.ToString()))).ToString(SaveOptions.DisableFormatting))); } set { if (value == null) { return; } byte[] toDecodeByte = Convert.FromBase64String(value); var encoder = new System.Text.UTF8Encoding(); System.Text.Decoder utf8Decode = encoder.GetDecoder(); int charCount = utf8Decode.GetCharCount(toDecodeByte, 0, toDecodeByte.Length); var decodedChar = new char[charCount]; utf8Decode.GetChars(toDecodeByte, 0, toDecodeByte.Length, decodedChar, 0); var flashContent = XElement.Parse(new string(decodedChar)); flash.ParseToSelf((string)flashContent.Element("flash")); width.ParseToSelf((string)flashContent.Element("width")); height.ParseToSelf((string)flashContent.Element("height")); fallbackContent.ParseToSelf((string)flashContent.Element("fallbackcontent")); } } } } |
In the Render method I check if the file ends with .swf, depending on that I either add the code for swfobject, or for flowplayer.
Update 19.11.2009
Thanks to Martins comment, I’ve removed the id field and replaced it with the HashCode and a prefix of flash (HTML id have to start with a letter in the roman alphabet). One less thing for the editor to worry about :).
Installation
- Download the code
- Unzip, and copy the FlashDynamicContent.dll into your sites bin folder, and the Flowplayer folder into your sites root folder
- Register it in your web.config file
<dynamicContent> <controls> ... <add description="Insert Flash or Flash Video" name="FlashDynamicContent" type="FlashDynamicContent.FlashDynamicContent, FlashDynamicContent"/> </controls> </dynamicContent>
Martin Emanuelsson says:
Post Author November 18, 2009 at 22:53Hello Frederik,
Good improvements to Allan’s dynamic content. Just wanted to give a suggestion regarding the id that you add manually here. We’ve done similar updates to Allan’s code, without the flash video option but with for instance swfobject, like you have, and also the possibility to feed xml to the flash for localization and such things. But regarding the id, we’ve solved this by adding the following code to the places where this has to be unique:
this.GetHashCode().ToString()
This way the editor doesn’t have to add id manually but instead this is handled automatically for them, just a suggestion 🙂
Best regards
Martin
Frederik Vig says:
Post Author November 19, 2009 at 10:13Hi Martin!
Good suggestion on the GetHashCode method. I’ve updated the code now, and removed the id field. One thing to remember though is that HTML id attributes cannot start with a digit, they have to start with a letter in the roman alphabet (I just added the flash prefix for this).
Frederik
Andrey Lazarev says:
Post Author November 24, 2009 at 19:41Hello, Fredrik!
I found your player compilation very useful but got two major ‘bugs’:
1. Player is unable to play anything except SWF-files. I followed your steps in ‘Installation’ section but it seems that more verbose installation procedure is required for me 🙁
2. I can’t see any controls at all for the movie. Is it normal?
Frederik Vig says:
Post Author November 25, 2009 at 10:39Hi Andrey!
Make sure that you copied the Flowplayer folder, and placed it in your sites root folder (http://example.com/Flowplayer). I’ve been testing with this file http://flowplayer.org/video/flowplayer-700.flv, though I know Flowplayer supports other formats as well (see http://flowplayer.org/documentation/technical-facts.html) – your best bet is to convert your movies to .flv.
Hope this helps.
Frederik
C-J Berg says:
Post Author November 29, 2009 at 02:19You shouldn’t use the GetHashCode value for building the id, since it doesn’t guarantee uniqueness; it only aims to distribute its values uniformly. A lot of developers get this wrong.
It would be better to allow the user to optionally enter a specific id, should she want to (like you first did). Who knows, perhaps it’s needed by some custom JavaScript code the user also adds to the page. When it’s not filled in, you could automatically generate a request unique id by utilizing a counter in Context.Items.
Better yet is to replace the fugly built-in editor with some decent alternative, such as TinyMCE that already has a media plug-in. 🙂
Andrey Lazarev says:
Post Author December 21, 2009 at 17:59////////////////////////////////
Hi Andrey!
Make sure that you copied the Flowplayer folder, and placed it in your sites root folder (http://example.com/Flowplayer). I’ve been testing with this file http://flowplayer.org/video/flowplayer-700.flv, though I know Flowplayer supports other formats as well (see http://flowplayer.org/documentation/technical-facts.html) – your best bet is to convert your movies to .flv.
Hope this helps.
Frederik
////////////////////////////////
Sorry, but – no luck 🙁
It’s not working. I’ve tried different ways to provide the path to FLV-file in plugin interface, but got only the black square with “Movie not loaded” in the context menu. Are you sure it’s wotking with the EPiServer CMS of 5 version? Maybe there should be some pre-requisites or some web.config-tuning for the application?
Frederik Vig says:
Post Author December 22, 2009 at 12:55Should work fine with EPiServer CMS 5 R2 and later. Have you tried using the test movie I linked to in my comment above?
Mårten Berg says:
Post Author March 11, 2010 at 15:07Works great, thanks for the post.
Jon Haakon Ariansen says:
Post Author May 26, 2011 at 09:55Hi,
This plugin seems like what I need. Or at least my problem is how to get Flowplayer to run on Ipad. I’ve added .mp4 as mimetype to the site, I’ve tested to move the movies in a seperate VPP directory based on EPiServer.Web.Hosting.VirtualPathNativeProvider, but with no luck. The site is running well, but I’m not able to run the video on Ipad. The flowplayer screen is black. Androide is fine. I’ve adjusted the settings in your code to more recent values. I’m using flowplayer-3.2.6.min.js and /Flowplayer/flowplayer-3.2.7.swf
All our videos are in .mp4, I tried to change this but with no luck. I guess there need to be additional changes to the code to support .mp4.
And adding this plugin seems to remove the tinymce editor for xhtml properties.
I’ve tried to put the file on the root of the websites directory and load it from there. That is fine. Both with url and uri, but when the file is loaded from VPP, the flowplayer is black (doesn’t load).
Any suggestions?? In advance thank you very much for your reply!!
Jon Haakon
Frederik Vig says:
Post Author May 26, 2011 at 19:38Hi Jon Haakon,
Afaik by default Flowplayer should have fallback for iPad, iPhones etc. You do need to make sure your .mp4 file is H.264 encoded though (you can test with sample from here: http://support.apple.com/kb/HT1425). If you want some more options there’s also an iPad plugin for flowplayer: http://flowplayer.org/plugins/javascript/ipad.html.
Hope this helps.
Frederik
Jon Haakon Ariansen says:
Post Author May 27, 2011 at 08:34Thank you very much for your reply!
I downloaded the sample .mp4 file from the page you provided and uploaded to my site (Episerver CMS 6 R2 / MS Framework 4)
and created a testpage.
What I find interesting is that the result was the same as on Ipad. When testing in Internet Explorer 9 (9.0.8080.16413) 64-bit OS,
flowplayer was all black. I thought at first that it was supposed to be like this but runnin the sample local I saw the animation.
Episerver is therefore not compatible with this movie or at least some kind of configuration has to be made to make it work.
Thank you very much for your help!
Kind regards,
Jon Haakon