What’s up everyone. I spent quite a bit of time developing my live streaming platform and I thought I’d share what I’ve learned. Why you ask? Well because I spent hours and hours researching this stuff - I must have Googled every possible term, Wordpress plugin, custom module out there… I’m not even kidding! I think my blood-pressure is permanently higher because of all this, and I’m most likely scarred for life. I should also mention a lot of what I learned simply didn’t exist before, at least not publicly or inexpensively. So I either had to code it myself, bootstrap things together, or bug Wowza support and consultants. My only hope is that I can save someone from some of the pain I endured through all this - and as a way to contribute back and help make this community even more awesome. I seriously wish I had all this when I started, so I’m going to do the “nice” (read: crazy) thing and do it myself. Seems like a stupid thing to do seeing as all this is info you literally have to pay for. Well stupid sounds right up my alley! Let’s do it!
Oh yeah, I should also mention that my methods are a bit unorthodox. There is probably a way better way to do things. So, use at your own risk. It’s also going to be long, boring, and confusing. Enjoy.
Let’s start at the beginning…
For some ungodly and idiotic reason I decided to use Wordpress as my content management system. So if you are familiar with Wordpress like I was, not good at coding like I am, you’re probably feeling like you should develop your platform on Wordpress. Makes sense, right? Well I am just going to warn you that Wordpress is definitely NOT made for a project such as this. That much should be obvious. You’re going to have to do a lot of hacking, testing, tweaking, bootstrapping, and hardcore headache medication to get things working. And you’ll end up with a mess of things that might even barely work! If you’re good with all that, feel free to use some of my tips.
I should also mention that I am super poor so I couldn’t just hire anyone (which is what I’d highly recommend you do if you are trying to create your own platform. Seriously, for the love of god and all that is good in this world, email Wowza support and ask for their consultant list).
So a lot of these resources you can use to create your platform up until the point to where you’re nearing launch. After that, you’re going to have to come up with the money to ignite the fuse.
Good? Good.
Ok.
Let’s do a little bit of pre-emptive checking.
You should know what kind of platform you want to make.
-
Is it just going to be you streaming?
-
Is it going to be a video conferencing service?
-
Are you going to let other people stream?
-
Are you going to charge them, or have it be free and monetize another way?
You need to know all this, because it’s going to really affect what you have to do.
Here’s what I wanted:
-A live streaming platform “one-to-many” model
-Let new people sign up and stream for free (this is important because if you charge, you can set things up a little differently)
-Have it generate a unique “channel” for each person that they can customize, but only they can stream to
-Include a live-chat for each channel
That is the gist of it. So if you are wanting something similar, it’s your lucky day.
Now, before I continue I should mention there are some pre-made solutions floating around. One in particular is a plugin called Video Whisper. You can actually install it from the Wordpess repository for free and see if it’s right for you. For me, it was definitely not right. If you’re wondering why, I found it way too confusing. It also seems to be more oriented for a “just you streaming” type of plugin, which is not what I wanted. It’s also like $500. I recommend you check it out anyway because hey, it might work for you. And kudos to them for making it.
Tip #1: licensing
The first thing you’ll want to do is get yourself a Wowza license if you don’t already. You are allowed to use their trial on Amazon EC2. I just got a small instance, but make sure you choose the Bring Your Own License Key (BYOL) AMI instance, or else your trial key will not work. Yeah, I actually chose the standard version and wondered why I was suddenly broke, so don’t do that. You could alternatively just install Wowza yourself, but there’s really no point in that when you could just do it in a couple clicks.
So head on over to the AWS Marketplace and create your instance. I just chose an m1.small because I didn’t know what I was doing and I’m retarded, but it served me pretty well for development. Later on when you want to get serious, you’re going to want the c1.medium instance as it’s the best bang for your buck - or so I’ve heard.
I’m actually not going to walk you through setting up the instance. Sorry. There’s plenty of Wowza documentation on that which is much better than anything I could write. And you know, if you’re going to be setting up a live-streaming platform you may as well familiarize yourself with the technology. You poor bastard, I feel sorry for you already.
Tip #2: plan for scaling
This was another thing I seriously messed up. When creating your platform, you’re going to be doing a lot of linking-it-with-your-server. And if you ignore that fact, when you’re done you realize that you need a CDN. The result? You have to go back through all your source code and relink everything with your CDN. Yeah, don’t do that. Sign up for your CDN now and get Wowza to work with it. The downside? You need a full Wowza license to do it. Whatever. You’ll need one sooner or later.
The next thing you want to do is install Wordpress. Big surprise there right? Go ahead and do that. But you also have to think about your web-host. I just did it on a shared hosting account because I’m a cheap bastard, so if you have a similar constitution to me a shared host is perfectly fine… for development. Later on you’re going to want at least a VPS. Since you’re on Wordpress you could even get with some glorious managed-hosting. One of the plus-sides for Wordpress. My favorite is WP-Engine, but you can do whatever you please.
Tip #3: your theme
So this was something I recently have been battling head-on with Wordpress. Your theme. Yeah, Wordpress is cool that you can make it look all pretty with relative ease. But it sucks for trying to implement custom PHP, which is really odd seeing as it’s made with PHP. So if you don’t know how to code, like I do, you’re in for a ride. My super-duper magic solution, which is going to save you so much time is… drumroll… Headway Themes.
Why Headway.
Well, it’s cool drag and drop, easy to learn for dummies like me, easy to customize. But the most important aspect is that you can implement PHP blocks. That saves you from having to use a plugin (the best undoubtedly being XYZ PHP by the way), and without it you’ll have to implement the code directly into your theme. That’s fine if you’re a developer / programmer / superstar, but if you aren’t – this is going to be your best option. The downside? It’s $59. Whatever, totally worth it.
Tip #4: channel creation
I spent like 3 whole months trying to figure out how I was going to do this. I needed a way for Wordpress to automatically create a channel for each person that only they can customize. It also needed to be locked-in to their username - so yoursite.com/username. At the end I finally decided that the best way would be to force Wordpress to make a new page every time a user signs up. I did that with this code (which you should place in your functions.php):
//this function creates a new page (or "channel") when a person signs up. only they have the ability to edit /* CREATE NEW POST WITH USER, GIVE POST USER'S NAME*/ function my_create_page($user_id){ $the_user = get_userdata($user_id); $new_user_name = $the_user->user_login; $my_post = array(); $my_post['post_title'] = $new_user_name; $my_post['post_type'] = 'page'; $my_post['post_content'] = ''; $my_post['post_author'] = $user_id; $my_post['post_status'] = 'publish'; wp_insert_post( $my_post ); } add_action('user_register', 'my_create_page');
About that. It grabs their username and sets it as the title. This effectively makes the permalink correct (yoursite.com/username). Oh yeah, you’ll want to make sure you have permalinks set to /%postname%/ (settings > permalinks).
Tip #5: permissions
Alright so now you might be wondering “hey schu, what’s to stop everyone from messing up each other’s channel?” A great question, Billy!
Here’s a big thing it does that you must understand. You know that code above? It sets the page to published. Why is this a big deal? Well if the page is already published, you can 1. deny people from creating new pages, and 2. only allow them to edit their own page.
I did all that by enforcing Wordpress roles. Basically, I set all new people as contributors with a handy plugin called WPFront User Role Editor (free):
http://i.imgur.com/FqnW7g5.png
Make sure you uncheck everything, EXCEPT for “read”, “upload_files”, “edit_published_pages”:
http://i.imgur.com/YQeqgev.png
And then the next thing I did was use the plugin Adminimize (also free).
So what you want to do with Adminimize is go through and deactivate EVERYTHING for contributors. Pay attention to the “page” section as that’s the most relevant, seeing that all our new users will get a page to serve as their channel. So go through and tick every. single. box. for contributors. Oh yeah, everything except “title”. They could get away with updating titles.
I didn’t like letting them see the dashboard at all, so I deactivated that for them too. You can do that with Adminimize. But thing you also want to do, especially if you’re using Headway is to drop all this into global custom class options:
#headway-admin-meta-box-template #headway-admin-meta-box-alternate-title #headway-admin-meta-box-post-thumbnail #headway-admin-meta-box-seo #headway-admin-meta-box-display
If you don’t do that, when they go to edit their channel they can seriously mess up your whole site. Basically Headway will include some “boxes” as extra functionality for admins making a new post. So things like seo, alternate titles, thumbnails. But there’s some key stuff in there that could really do damage if you leave it.
Pro-tip for Adminimize: you can literally disable ANY feature that you don’t want your users to see. You can do this by right-clicking and choosing inspect element (if you use Chrome), and then scrolling through all the code on the side until it highlights the feature you want to remove. Then you just copy the class-name and paste it into Adminimize:
http://i.imgur.com/HvQ0il4.png
Tip#6: check uploads
So I probably don’t have to tell you that you’re going to want to use Amazon S3 to store your files. But your people will also need to upload their own stuff. That also messes things up because they’ll be able to see everyone elses uploads, including YOURS and delete everything. People are jerks, they will do that. We fix that by adding this code into your functions.php:
// this function allows streamers to only see their own uploaded media add_filter( 'posts_where', 'devplus_attachments_wpquery_where' ); function devplus_attachments_wpquery_where( $where ){ global $current_user; if( is_user_logged_in() ){ // we spreken over een ingelogde user if( isset( $_POST['action'] ) ){ // library query if( $_POST['action'] == 'query-attachments' ){ $where .= ' AND post_author='.$current_user->data->ID; } } } return $where; }
Hopefully that’s self-explanatory.
Tip#7: check profile
So since we are using the users username as their channel name and permalink, we want to keep it that way. So that means we do not want them to be allowed to change their name, at all, ever.
You can do that by adding in all THIS code to your functions.php as well:
//remove fields from profile function add_twitter_contactmethod( $contactmethods ) { unset($contactmethods['aim']); unset($contactmethods['jabber']); unset($contactmethods['yim']); return $contactmethods; } add_filter('user_contactmethods','add_twitter_contactmethod',10,1); //remove 'change display name' from profile add_action('show_user_profile', 'remove_display_name'); add_action('edit_user_profile', 'remove_display_name'); function remove_display_name($user) { ?> <script> jQuery(document).ready(function() { jQuery('#display_name').parent().parent().hide(); }); </script> <?php } // remove nickname function prefix_hide_personal_options() { if (current_user_can('manage_options')) return false; ?> <script type="text/javascript"> jQuery(document).ready(function( $ ){ $("#nickname,#display_name").parent().parent().remove(); }); </script> <?php } if (is_admin()) add_action('personal_options', 'prefix_hide_personal_options'); ?>
What that does is removes nickname, username changes, and a couple other personal options. Word up.
Tip#7: channel content
So now you have a new page that’s made every time a user registers. That’s neat. But nothing is on their channel yet. You can fix that by adding JW Player on their channel. So the cool part is that since you’re hopefully using Headway themes, you can control what content goes there, even though you gave the user rights to edit the content. You can prevent them from removing things you don’t want, such as an instance of JW.
Why JW Player? Well it’s the best, and literally ONLY thing I managed to get working on Wordpress that supports RTMP streaming. Don’t even bother looking up anything else, seriously.
So on Headway themes what you want to do is create a new layout for PAGE (first I would create a new header for the front-page though, so your pages will automatically inherit it):
http://i.imgur.com/mkEDXIX.png
Then you can customize the page for how you want your channels to appear. Without going into too much depth, you do this by creating new “wrappers”, and then adding new “blocks” on those wrappers. If that didn’t make sense and I know it didn’t, you’ll have to read up on the Headway documentation.
So this is what my channel looks like:
http://i.imgur.com/mcCYsfB.png
Basically I just created a new block and selecting “custom code”:
http://i.imgur.com/GCjrWV3.png
And then you can do various fun things. The first is that I wanted the title to show so the user can update it:
<?php echo get_the_title(); ?>
The second is I wanted the content to appear for the users edits:
<?php the_content(); ?>
So basically that will pull their content but only to their specific block, but they won’t be able to edit or remove the other blocks.
Tip#8: mapping JW player
If you made it this far, you’re probably wondering how you can only make sure that the correct stream appears for each channel. So you don’t want Joe’s stream to appear on Bob’s channel. We do that with this custom code:
<?php global $post; $author_id=$post->post_author; $author = get_the_author_meta('user_nicename',$author_id); $link = "rtmp://yourwowza:1935/live/"; $video = $link . $author; ?> <div id="container"></div> <script src="/jwplayer/jwplayer.js"></script> <script type="text/javascript"> jwplayer("container").setup({ file: "<?php echo $video; ?>", width: "100%", aspectratio: "16:9", autostart: false }); </script>
What that does is it grabs the current author of the post, so Bob. Then it appends it to the end of the link. Anything else that is NOT Bob will not appear. But one thing you have to do is place the JW plugin on your host and set the path. Then take this line and put it in your header:
<script src="/jwplayer/jwplayer.js"></script>
Tip#9: the chat
So this is one of those things that there are a ton of options but not many work because not many people made chat options for Wordpress. Trust me, I’ve looked at every single plugin there is regarding chat and Wordpress.
So you really have 3 good options:
-
Ejabberd
-
IRCv3
-
Firechat / Firebase
The first 2 are a pain because you have to set up, run, and manage a server. But they also give you the most customization options. But you’re going to really struggle finding a front-end chat plugin that’s compatible with Wordpress. Which is why I personally decided to use Firechat:
https://firechat.firebaseapp.com/
The cool thing about Firechat is that it’s pretty easy to get running on your site:
<html> <head> <meta charset="utf-8" /> <!-- jQuery --> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <!-- Firebase --> <script src="https://cdn.firebase.com/js/client/2.0.2/firebase.js"></script> <!-- Firechat --> <link rel="stylesheet" href="https://cdn.firebase.com/libs/firechat/2.0.1/firechat.min.css" /> <script src="https://cdn.firebase.com/libs/firechat/2.0.1/firechat.min.js"></script> <!-- Custom CSS --> <style> #firechat-wrapper { height: auto; background-color: #fff; text-align: center; } </style> </head> <!-- Example: Anonymous Authentication This example uses Firebase Simple Login to create "anonymous" user sessions in Firebase, meaning that user credentials are not required, though a user has a valid Firebase authentication token and security rules still apply. Requirements: in order to use this example with your own Firebase, you'll need to do the following: 1. Apply the security rules at https://github.com/firebase/firechat/blob/master/rules.json 2. Enable the "Anonymous" authentication provider in Forge 3. Update the URL below to reference your Firebase 4. Update the room id for auto-entry with a public room you have created --> <body> <div id="firechat-wrapper"></div> <script type="text/javascript"> var chatRef = new Firebase("https://your-firebase.firebaseio.com"); var chat = new FirechatUI(chatRef, document.getElementById("firechat-wrapper")); chatRef.onAuth(function(authData) { if (authData) { chat.setUser(authData.uid, "Anonymous" + authData.uid.substr(10, 8)); } else { chatRef.authAnonymously(function(error, authData) { if (error) { console.log(error); } }); } }); </script> </body> </html>
That’s all it takes. The bad is that customizing it can get confusing if you aren’t a programmer. I don’t really have a solution for you as I’m actually still working on this part. Sorry (but if you ask nicely I might include it later).
Tip#10: stream protection
Now this is something that is pretty complex, and there’s a lot of answers. I may be even doing it wrong. There’s a lot of custom modules you can buy, and different ways to achieve this. But really in this situation you have to force Wowza to authenticate with your MySQL database. The reason is because we only want Bob to be able to stream to Bob’s channel, and not Joe. You see? So we have to give Bob some kind of password that’s unique to him that he can plug into his encoder. Wowza by default publisher passwords, but that doesn’t help us because it’s not automated. Your best bet is some kind of token, and adding a custom Wowza module to authenticate with your MySQL.
I’m going to go ahead and list the best options I found:
http://www.synapse.ws/wowza-flash-applications/#6 - $??
http://www.solid-thinking.com/product/sti-streaming-protection-for-wowza/ - $30 (this is by a guy name Graeme Bull. He’s great)
https://streamtoolbox.com/wrench - $200 (by Balazs. He is super cool and actually got on Skype with me to help)
http://www.clavain.com/wowzasolutions.html - $15 (note: it’s JUST the custom module, there is no authentication provided, so you’ll have to make it yourself)
I ended up going with STI as it was more in my price range and already had what I need right from the box. Your mileage may vary. I would highly recommend you look into Wrench as well. It is the most flexible and well documented, and Balazs is helpful. Unfortunately it didn’t end up working for me as I needed a custom PHP mechanism for authentication.
Things to look out for
-You’ll probably want a custom-login feature that uses the front-end of your site rather than Wordpress default. There are so many plugins for this, just check out codecanyon.
-You might want something to get connection information in order to show who is connected per each stream. I haven’t found a way to do this yet, but am playing with some options.
Summary
Well that pretty much wraps it up. I’m sure I’m forgetting some things, but all the important parts are here. Lesson learned? You probably shouldn’t use Wordpress.
I hope this helped someone, and if anyone has input for me I would LOVE to hear it. Thank you and have a good day.