Wednesday, September 8, 2010

JPlayer Audio Playlist Generator (JPlayer Playlister)

The CD that launched 1000...lines of code

Update

[2014.11.23]
The new jPlaylister v0.70 was built on jPlayer 2.8.2, because 2.6 had some recent serious issues with mobile browsers. Fixing those and implementing a more mobile friendly theme for the fs/mobile mode.

[2014.08.31]
The new jPlaylister v0.68 adds support for auto-scrolling playlists and full-screen/mobile mode. Previous releases added playlist caching (a feature that significantly decreases load times on large playlists) and support for displaying album art, in case you missed them.

/update...resume original post

My brother sent me a CD full of MP3s when I was in Kuwait -- cut off from the internet -- and going into withdrawals from not being able to download music. It was a good mix and has turned me on to a few artists that I knew nothing about.

A week ago, my wife has to take my car for something and, realizing that my radio sucks (shhh...i didn't hook up the antennae so my radio-listening experience would be less than inviting), flipped down my sunvisor CD holder and picked the fabled blue cd from the small selection. She made it 20 tracks or so into the CD (love MP3 CDs..if only it had any type of anti-skip) before arriving home and not using my car again for as long as she lives if it was up to her.

I hop in the car the next morning and A Tribe Called Quest welcomes me to the drive to work. A nice way to start the day. I re-affirm my love for my wife due solely to this incident and decide to facebook about it later that day. I did (may have been the following day) and that was that, but someone mentioned that hearing the mix would be fun. All to eager to oblige, I start devising ways to make it happen. So what if I spend 30 hours on a project and only 2 people give a crap (me and me). I had made web pages that incorporated flash based audio players before...but that was before the up and coming HTML5, and the somewhat supported audio tag.

Let's get a web player

A quick internet search later and I see JPlayer, which looks familiar. I glance at the demos and one has a playlist -- perfect. It supports OGG Audio and MP3's via HTML5 and will fallback to Flash for unsupportive browsers, bras, or family members. Perfect.

Initial implementation (derived from the JPlayer with playlist demo) wasn't that bad. I took the demo code and just added the ability to automatically generate a playlist from all the files in a given location. I think it took me a couple of hours...taking snack breaks and probably food breaks and almost certainly bathroom, crying baby, and phlebotomy breaks.

I went to bed last night with a working player. In addition to deriving the playlist from the files at the location specified, I was also able to add the option of displaying filenames or ID3 information (via getID3 -- a PHP class)

I put a link on fb and probably got thousands of views.

Revisions / Additions

Tonight, I pushed back the list of things I need to do and worked more on this little project. At some point during the day, I had decided that the first song on the playlist was wearing on me. I usually paused within 5 seconds of loading the page, but it doesn't take much to wear a song out, for me. That's another reason I don't do the radio...20 songs on a loop with advertisements and lame DJs. No thanks. So I added the option to 'randomize' list via a clickable link on the page. It caused me to rewrite a fair amount of code. But, I am pretty happy with the turnout.

Current Situation

See 'Update' at the top of this article to link to the current version of JPlaylister. Thanks for your interest and support.

Tuesday, May 18, 2010

Extract Ogg (ogv) from Matroska (mkv)

The Story

I don't do much with video. I finally wrote a script which compresses all the files in a given folder using the handbrake cli...just for archiving my home videos that had been digitized; on import they were some slight compression avi. The cli lets me automate converting my videos to a patent free (afaik) format -- Ogg. I use both Theora and Vorbis in a Matroska container...I was going Ogg (Ogv) container, but handbrake didn't support that, and I hear Matroska is better...or far more capable. Even though Ogv would have been fine for my purposes. Oh well.

Anyway, I decide that I want to make a webpage on my development server (read: home computer) that allows my home videos to be seen by my family without the hassle of uploading them to youtube...and carefully optimizing them first or watchmaking Youtube butcher the already mediocre quality. I decided to embrace the future and use the upcoming html5's 'video' tag.

Ah, man...I JUST encoded/archived all my videos to Matroska...even though they were encoded with Theora/Vorbis, the Matroska container doesn't work. I need to extract (I don't want to transcode them and lose all that quality. are you kidding?) the streams from the Matroska format and put them in an Ogg (ogv) container...somehow. Can't be hard, right?

I tried loads of things. MKVToolnix, AVIMux GUI, VirtualDubMod...and I read loads of forums, mostly about people wanting to convert MKV (h.264) to AVI (xvid). I finally read something about ffmpeg...so I thought I could at least (since I encode to the original size AND to a half-size) transcode from the large .mkv to .ogv with that.

20 minutes into it, my Ogg (.ogv) files were looking horrible and coming out at half the size of the (same resolution) input, I did a few searches for optimal settings .ogv or something and came across a post that mentioned something I hadn't seen in the documentation (although I'd imagine it's there)...the ability to 'copy' the audio and video stream. Someone was just using ffmpeg to extract a 1 minute segment from a video file without re-encoding. That's what I want to do!!!

Long story short, this code did it for me:

The Code

ffmpeg -i mysourcevideo.mkv -vcodec copy -acodec copy myoutvideo.ogv

A straight 'Direct Stream Copy' (i used to use VirtualDub -- pardon me), essentially...with no loss in quality and a container change. Now I can make a quick script...I'm not sure if I'll do it for all my videos or just the half-sizes...as I don't really wanna stream the large ones, which I make available for download.

Be End.

Software


ffmpeg

Epilogue


Now I'm just wondering if Handbrake CLI has any advantage (for my use, anyway) over ffmpeg?

Saturday, April 17, 2010

Photo Feed (RSS/Atom) Display Widget

Flickr / Picasa / ZenPhoto / Plogger / Gallery2/3 Photo Feed (RSS/Atom) Widget

Check it Out!

Update

The HTML version seems to get way more interest than the PHP version, so I'm focusing development on that (the Widget). I just added a means to specify border color and size, in addition to the spacing which was added a while ago. I've also added a 'Widget Builder' to the site, so you can customize and embed with even less html knowledge than before. Hope you love it!

I want to display my most recent Flickr photos on another page of mine. Easy enough, right? There are plenty of widgets and code snippets displaying Flickr Photos in all sorts of creative ways.

Well, what if I want them formatted/styled a certain way?

Not as easy.

What if I want to display a Picasa Web Album Feed as well? And perhaps a ZenPhoto RSS Feed. Am I the only lame PHP coder who uses all of these Photo storage / display / socialization mediums?

I decided to create a widget. While the implementation is limited in how it can format your images (for html coders; PHP coders should have more advanced options soon), it does work with a large number of RSS Feeds -- provided the feed has items with images.

Demo




This is a simple widget call referencing my Flickr PhotoStream RSS Feed. The widget creates thumbnails of each of the most recent items and displays them in a row, linking back to each item's source page.

Options

While the straight HTML call is pretty limited, there are some options which can be requested such as the ability to specify thumbnail size, disable square thumbs (prevent standard cropping), and specify the number of photos to be displayed. (Updates have been made which allow spacing, border size and color, and limited link options to be specified)

PHP users will soon be able to request an array of information so the photos can be formatted in any way they see fit. [Visit the project page and post a comment if this would be useful -- so I know there is an interest] Alternately, they can download the source code and host it on their own server -- changing it as they see fit.

Limitations

The HTML Widget call can only return a row of images which link to their source. There is currently no fancy customization (aside the options mentioned) for this type of call. Likewise, currently iframes are the suggested way to implement/embed the widget.

Compatibility

The widget has been tested on Flickr, Picasa Web Album, ZenPhoto, Gallery2, Gallery3, Plogger, and various other (RSS/Atom) Feeds (the list keeps growing). It employs the use of SimplePie for the basic Feed parsing, then does some further work to create thumbnails of the pictures and link back to them.

Sunday, January 10, 2010

Last FM Widget Found

Dotaloc's Last.FM Recently Played Songs - Widget












Maybe it's just me, but I had the hardest time finding this thing. What thing? Oh, let me start from the beginning...

Skip straight to the code

Backstory


I signed up with last.fm, a music streaming/information aggregation and listening habit analyzation site a couple of years ago. I have a scrobbler running on my computer, and it sends information about what I play in winamp to last.fm. They take that information and compare it to what other people who listen to some of the same bands listen to...recommend other artists to you, stuff like that.

You don't have to scrobble to enjoy. I sometimes just go to the website, type in an artist I like, and listen to a 'station' last.fm creates based on the artist, and others they have determined are similar or listened to by people who like the artist. I've been turned on to a few bands this way...as information about the current band/song is displayed on the website or in the standalone player (great for bypassing streaming radio site blocks, which are sometimes implemented by employers/etc. in order to cut down on excessive bandwidth usage).

This services, or similar ones such as Pandora are not new to lots of people...but this is my blog and I will ramble if I want.

That said, what good is it to scrobble all day if you can't integrate with all these awesome social networking sites and show your fans what songs listen to via an interactive widget? Not much. I found one that I was able to put on my dog's myspace page a while back and was pretty happy with it. I don't have a myspace...or facebook...account. My wife handles that stuff.

I wanted that widget on my personal website, though...seems appropriate. I have personal information...links to pictures...information about important happenings in my life like my son being born on October 9th...and the likes. Why not tell the world what songs I'm listening to so people will have a chance to learn some amazing new bands thanks to my chronic listening and hard work. Exactly.

Situation


So I want that same type of thing...on my personal site. Shouldn't be hard...the 'widget' wasn't myspace specific. I googled something like 'last.fm widget'...which actually searched 'last.fm' for the word 'widget'. This didn't end up doing what I needed. Let me re-arrange my search terms...'widget last.fm'. This was what I wanted to do...but didn't show me what I wanted. Last.fm has some type of page that seems like it is supposed to offer the type of list i was looking for with themes and all of that, but it has been broken for at least two days...probably more. I don't like waiting. Even though they have an API (Application Program Interface)...accessing the information I want surely has been done loads of times...there is no reason for me to write brand new code to do this, even if I am able, when I can just use someone else's. No luck...there are some scripts that use the API and pull up some fancy information...but I just want the list of the most frequent songs I've scrobbled. Nothing. You try. See.

*facepalm*

I guess I can reference my, still working, myspace code. At this point, I didn't remember if I had access to the code or if it was a clickable option myspace had enabled or something. Nope...the code was listed plain as day when I went to edit my profile. The 'widget' links to the broken last.fm page...but actually works.

I took the code and put it on my page. It didn't fit my color scheme, so I dug through the code a little and changed some of the 'red' graphics to 'black'...hoping it'd work. It did.

Moral


I tried this the hard way and wasted a few hours of my life. Boo to that. Don't be like me. Attempt easiest solution first, especially if you can determine if it'll work or not within a few minutes.

Want the Widget for Yourself


Hopefully this'll help someone else. I'll provide the straight JavaScript first, then the php that I use.

JavaScript


replace 'dotaloc' with your last.fm username
<span style="font-style:italic;">replace 'dotaloc' with your last.fm username</span>
<style>table.lfmWidget346494d0b5f3a8b580d15b4053d6d02a td {margin:0 !important;padding:0 !important;border:0 !important;}table.lfmWidget346494d0b5f3a8b580d15b4053d6d02a tr.lfmHead a:hover {background:url(http://cdn.last.fm/widgets/images/en/header/chart/recenttracks_regular_red.png) no-repeat 0 0 !important;}table.lfmWidget346494d0b5f3a8b580d15b4053d6d02a tr.lfmEmbed object {float:left;}table.lfmWidget346494d0b5f3a8b580d15b4053d6d02a tr.lfmFoot td.lfmConfig a:hover {background:url(http://cdn.last.fm/widgets/images/en/footer/red.png) no-repeat 0px 0 !important;;}table.lfmWidget346494d0b5f3a8b580d15b4053d6d02a tr.lfmFoot td.lfmView a:hover {background:url(http://cdn.last.fm/widgets/images/en/footer/red.png) no-repeat -85px 0 !important;}table.lfmWidget346494d0b5f3a8b580d15b4053d6d02a tr.lfmFoot td.lfmPopup a:hover {background:url(http://cdn.last.fm/widgets/images/en/footer/red.png) no-repeat -159px 0 !important;}</style>
<table class="lfmWidget346494d0b5f3a8b580d15b4053d6d02a" cellpadding="0" cellspacing="0" border="0" style="width:184px;"><tbody><tr class="lfmHead"><td><a title="dotaloc: Recently Listened Tracks" href="http://www.msplinks.com/MDFodHRwOi8vd3d3Lmxhc3QuZm0vdXNlci9kb3RhbG9jLw==" target="_blank" style="display:block;overflow:hidden;height:20px;width:184px;background:url(http://cdn.last.fm/widgets/images/en/header/chart/recenttracks_regular_red.png) no-repeat 0 -20px;text-decoration:none;"></a></td></tr><tr class="lfmEmbed"><td><object type="application/x-shockwave-flash" allowscriptaccess="never" allownetworking="internal" height="199" width="184" data="http://cdn.last.fm/widgets/chart/friends_4.swf">
<param name="allowScriptAccess" value="never">
<param name="allowNetworking" value="internal">
<param name="movie" value="http://cdn.last.fm/widgets/chart/friends_4.swf">
<param name="flashvars" value="type=recenttracks&amp;user=dotaloc&amp;theme=red&amp;lang=en&amp;widget_id=346494d0b5f3a8b580d15b4053d6d02a">
<param name="bgcolor" value="#d01f3c">
<param name="quality" value="high">
</object></td></tr><tr class="lfmFoot"><td style="background:url(http://cdn.last.fm/widgets/images/footer_bg/red.png) repeat-x 0 0;text-align:right;"><table cellspacing="0" cellpadding="0" border="0" style="width:184px;"><tbody><tr><td class="lfmConfig"><a href="http://www.msplinks.com/MDFodHRwOi8vd3d3Lmxhc3QuZm0vd2lkZ2V0cy8/Y29sb3VyPXJlZCZhbXA7Y2hhcnRUeXBlPXJlY2VudHRyYWNrcyZhbXA7dXNlcj1kb3RhbG9jJmFtcDtjaGFydEZyaWVuZHM9MSZhbXA7ZnJvbT1jb2RlJmFtcDt3aWRnZXQ9Y2hhcnQ=" title="Get your own widget" target="_blank" style="display:block;overflow:hidden;width:85px;height:20px;float:right;background:url(http://cdn.last.fm/widgets/images/en/footer/red.png) no-repeat 0px -20px;text-decoration:none;"></a></td><td class="lfmView" style="width:74px;"><a href="http://www.msplinks.com/MDFodHRwOi8vd3d3Lmxhc3QuZm0vdXNlci9kb3RhbG9jLw==" title="View dotaloc's profile" target="_blank" style="display:block;overflow:hidden;width:74px;height:20px;background:url(http://cdn.last.fm/widgets/images/en/footer/red.png) no-repeat -85px -20px;text-decoration:none;"></a></td><td class="lfmPopup" style="width:25px;"><a href="http://www.msplinks.com/MDFodHRwOi8vd3d3Lmxhc3QuZm0vd2lkZ2V0cy9wb3B1cC8/Y29sb3VyPXJlZCZhbXA7Y2hhcnRUeXBlPXJlY2VudHRyYWNrcyZhbXA7dXNlcj1kb3RhbG9jJmFtcDtjaGFydEZyaWVuZHM9MSZhbXA7ZnJvbT1jb2RlJmFtcDt3aWRnZXQ9Y2hhcnQmYW1wO3Jlc2l6ZT0x" title="Load this chart in a pop up" target="_blank" style="display:block;overflow:hidden;width:25px;height:20px;background:url(http://cdn.last.fm/widgets/images/en/footer/red.png) no-repeat -159px -20px;text-decoration:none;"></a></td></tr></tbody></table></td></tr></tbody></table>


PHP


edit the variables accordingly. the colors should probably be plain html written out word colors (blue, green, red) for the best chance of them working. check the PHP out and you can probably fine-tune it to your liking.
//set lastfm widget color and widget hover color -- these should be very basic for the highest probability they will work as some reference graphics
$lfmwc='black';
$lfmwhc='black';

//right-float last.fm widget
$lastfmwidget='<div class="floatright" style="margin-top: 15px; border: 1px solid #222; ">'

//taken from old myspace widget -- can't find anymore
.'<style>table.lfmWidget346494d0b5f3a8b580d15b4053d6d02a td {margin:0 !important;padding:0 !important;border:0 !important;}table.lfmWidget346494d0b5f3a8b580d15b4053d6d02a tr.lfmHead a:hover {background:url(http://cdn.last.fm/widgets/images/en/header/chart/recenttracks_regular_'.$lfmwhc.'.png) no-repeat 0 0 !important;}table.lfmWidget346494d0b5f3a8b580d15b4053d6d02a tr.lfmEmbed object {float:left;}table.lfmWidget346494d0b5f3a8b580d15b4053d6d02a tr.lfmFoot td.lfmConfig a:hover {background:url(http://cdn.last.fm/widgets/images/en/footer/'.$lfmwhc.'.png) no-repeat 0px 0 !important;;}table.lfmWidget346494d0b5f3a8b580d15b4053d6d02a tr.lfmFoot td.lfmView a:hover {background:url(http://cdn.last.fm/widgets/images/en/footer/'.$lfmwhc.'.png) no-repeat -85px 0 !important;}table.lfmWidget346494d0b5f3a8b580d15b4053d6d02a tr.lfmFoot td.lfmPopup a:hover {background:url(http://cdn.last.fm/widgets/images/en/footer/'.$lfmwhc.'.png) no-repeat -159px 0 !important;}</style>
<table class="lfmWidget346494d0b5f3a8b580d15b4053d6d02a" cellpadding="0" cellspacing="0" border="0" style="width:184px;"><tr class="lfmHead"><td><a title="dotaloc: Recently Listened Tracks" href="http://www.msplinks.com/MDFodHRwOi8vd3d3Lmxhc3QuZm0vdXNlci9kb3RhbG9jLw==" target="_blank" style="display:block;overflow:hidden;height:20px;width:184px;background:url(http://cdn.last.fm/widgets/images/en/header/chart/recenttracks_regular_'.$lfmwc.'.png) no-repeat 0 -20px;text-decoration:none;"></a></td></tr><tr class="lfmEmbed"><td><object type="application/x-shockwave-flash" allowScriptAccess="never" allowNetworking="internal" height="199" width="184" data="http://cdn.last.fm/widgets/chart/friends_4.swf">
<param name="allowScriptAccess" value="never" />
<param name="allowNetworking" value="internal" />
<param name="movie" value="http://cdn.last.fm/widgets/chart/friends_4.swf" />
<param name="flashvars" value="type=recenttracks&user=dotaloc&theme='.$lfmwc.'&lang=en&widget_id=346494d0b5f3a8b580d15b4053d6d02a" />
<param name="bgcolor" value="#FF6600'.x/*#d01f3c*/.'" />
<param name="quality" value="high" />
</object></td></tr><tr class="lfmFoot"><td style="background:url(http://cdn.last.fm/widgets/images/footer_bg/'.$lfmwc.'.png) repeat-x 0 0;text-align:right;"><table cellspacing="0" cellpadding="0" border="0" style="width:184px;"><tr><td class="lfmConfig"><a href="http://www.msplinks.com/MDFodHRwOi8vd3d3Lmxhc3QuZm0vd2lkZ2V0cy8/Y29sb3VyPXJlZCZhbXA7Y2hhcnRUeXBlPXJlY2VudHRyYWNrcyZhbXA7dXNlcj1kb3RhbG9jJmFtcDtjaGFydEZyaWVuZHM9MSZhbXA7ZnJvbT1jb2RlJmFtcDt3aWRnZXQ9Y2hhcnQ=" title="Get your own widget" target="_blank" style="display:block;overflow:hidden;width:85px;height:20px;float:right;background:url(http://cdn.last.fm/widgets/images/en/footer/'.$lfmwc.'.png) no-repeat 0px -20px;text-decoration:none;"></a></td><td class="lfmView" style="width:74px;"><a href="http://www.msplinks.com/MDFodHRwOi8vd3d3Lmxhc3QuZm0vdXNlci9kb3RhbG9jLw==" title="View dotaloc\'s profile" target="_blank" style="display:block;overflow:hidden;width:74px;height:20px;background:url(http://cdn.last.fm/widgets/images/en/footer/'.$lfmwc.'.png) no-repeat -85px -20px;text-decoration:none;"></a></td><td class="lfmPopup" style="width:25px;"><a href="http://www.msplinks.com/MDFodHRwOi8vd3d3Lmxhc3QuZm0vd2lkZ2V0cy9wb3B1cC8/Y29sb3VyPXJlZCZhbXA7Y2hhcnRUeXBlPXJlY2VudHRyYWNrcyZhbXA7dXNlcj1kb3RhbG9jJmFtcDtjaGFydEZyaWVuZHM9MSZhbXA7ZnJvbT1jb2RlJmFtcDt3aWRnZXQ9Y2hhcnQmYW1wO3Jlc2l6ZT0x" title="Load this chart in a pop up" target="_blank" style="display:block;overflow:hidden;width:25px;height:20px;background:url(http://cdn.last.fm/widgets/images/en/footer/'.$lfmwc.'.png) no-repeat -159px -20px;text-decoration:none;"></a></td></tr></table></td></tr></table>'
//end div
.'</div>';


Conclusion


Contact me if you need any help. Contact info at http://nick.chapmanit.com or chapmanit.com.

References


To post code to blogger, I followed instruction here: http://thoughtsomething.blogspot.com/2008/11/display-html-javascript-code-in-blogger.html