New Sheet Music Library: The Story

After nearly two years of planning, false starts, and development, I finally launched a new sheet music library. In this post, I’ll discuss the development and implementation process, design decisions, and how I created this project in a way that the source code will be available for anyone to use for free.

History

I started posting my cello ensemble compositions and arrangements online in early 2012, when I first set up celloexpressions.com as the website for my high school cello quartet, Cello Expressions. A series of separate WordPress installs represented each distinct site when I transitioned the domain to be the home for my projects in August of that year. I moved the original site to the music subdirectory and built a new system to display sheet music in a more structured way.

Because I spent the summer of 2012 developing Euclid’s Muse, basing the code off of a horribly-written BuddyPress plugin, I thought that the best approach a directly-queried custom database would be the best approach. I didn’t have the time to build a posting or editing UI, so I decided I would just make edits directly in the database with PHPMyAdmin. That worked for a few months, and in November 2012, I redesigned the site’s theme (poorly). But I would last post a new piece in January 2013. It was clear that I needed an entirely different system, and that I would probably need to migrate all of my existing content (now 60 pieces) manually.

Cello Expressions Sheet Music Library, from January 2013 to December 2014.
Cello Expressions Sheet Music Library, from January 2013 to December 2014.

Goals

My primary goal for the sheet music library is to make free music, primarily for cello-oriented ensembles, widely available and accessible. I also want to get my works out there for people to play.

But my goals for making the sheet music library easy to use were much harder to accomplish with the old system. All pieces needed to have PDF downloads, preferably with the ability to have separate score and parts PDFs. I needed to display previews of the PDFs in a browser-agnostic way, rather than hoping that it would work to put a PDF in an iframe. Pieces needed to have a way to upload and display recordings, both via MP3s and via YouTube videos. Pieces needed to have fields for composers, difficulties, genres, and instrumentations, and values should cross-link between different pieces. And most importantly, I needed everything to be searchable, both internally and via search engines.

A WordPress Plugin

One of my first decisions was to build the sheet music library functionality in a plugin. That way I could use an existing WordPress theme and redesign much more easily. Over time, additional benefits became clear – others could use this plugin as well. The Boulder Cello Project will use it, plus an add-on plugin, to power their internal members site, where they post sheet music for their meetups for members to practice in advance. The plugin will be released on WordPress.org once the initial implementation for the Cello Expressions Sheet Music Library is complete.

Custom Post Type & Taxonomies

It also became clear that I should create a sheet music custom post type, with custom taxonomies providing relationships between pieces. Composers, instrumentations, difficulties, and genres are each custom taxonomies for the sheet_music post type. PDFs for the score and parts and audio file uploads would be stored as attachments, with the attachment post ids stored as post meta in sheet_music posts. I also stored YouTube videos by their URLs as post meta.

PDFs to Images

The solution to displaying PDF previews in a reusable way ended up being surprisingly simple. By converting the first page of the score PDF to an image, the front-end and admin can display an image preview of the PDF pretty easily. Converting PDFs to images is actually pretty simple in most modern server environments with WordPress’ image editor.

Diving briefly into code, WP_Image_Editor’s ImageMagick implementation makes it incredibly easy to convert PDFs to Images:

/**
 * When a PDF is uploaded, generate a thumbnail image and save it in the attachment meta.
 */
add_filter( 'wp_generate_attachment_metadata', 'prefix_generate_pdf_thumbnail_metadata', 10, 2 );
function prefix_generate_pdf_thumbnail_metadata( $metadata, $attachment_id ) {
	$attachment = get_post( $attachment_id );
	if ( 'application/pdf' === get_post_mime_type( $attachment ) ) {
		// Create a png from the pdf.
		$file = get_attached_file( $attachment_id );
		$pdf = wp_get_image_editor( $file );
		if ( ! is_wp_error( $pdf ) ) { // Most likely cause for error is that ImageMagick is not available.
			$filename = $pdf->generate_filename( 'image', null, 'png' );
			$uploaded = $pdf->save( $filename, 'image/png' );
			if ( ! is_wp_error( $uploaded ) ) {
				$upload_dir = wp_upload_dir();
				update_post_meta( $attachment_id, 'pdf_thumbnail_url', $upload_dir['url'] . '/' . $uploaded['file'] );
			}
		}
	}
	return $metadata;
}

Unfortunately, not all servers have ImageMagick installed. I don’t have it installed locally, and when I went to test on the celloexpressions.com server (hosted by GoDaddy for historical reasons), it wasn’t there. I contacted support and they said I had to upgrade to a newer account, which would involve manually migrating everything (or they could do it for a fee). I’d been wanting to get off of that server for a while anyway. So, I took to opportunity to move everything onto one of my existing Bluehost accounts. I also cleaned up some old stuff that was living on celloexpressions.com in the process. Once I switched the domain over to the new server, everything worked exactly how I had wanted.

Realizing how straightforward it is to create images from PDFs in PHP, and how much room for improvement WordPress has with regards to PDF uploads (both in terms of administration and presentation), I’m going to propose some improvements there for core once I finish this project.

Media & Embeds

In addition to digging into the intricacies of WordPress’ handling of PDFs, I spent some time working on my JavaScript skills to implement previews of uploaded audio and linked videos in the admin. Since I planned to use the plugin at large scale, the admin UI needed to be highly efficient and functional. I implemented Audio and video previewing based on the media wpviews in the core WordPRess editor. While the result is somewhat hacky and buggy, most of the integration relies on core functions rather than extensive custom logic, and I rarely encounter the bugs in my workflows.

On the front-end, wp_audio|video_shortcode( array( ‘src’ => $url ) ); gives browser-compatible HTML5 audio and video via MediaElement.js. That also provides a skinned player for YouTube videos that matches the audio player and can be customized with CSS. WordPress 4.2 will also add support for skinned Vimeo embeds; the sheet music library plugin won’t require any changes to support Vimeo and YouTube equally.

In a future update, I plan to explore the possibilities with creating a “collection” of PDFs with the media library, similarly to galleries, audio playlists, and video playlists. If I’m successful with collections, they could allow uploading separate files for each part of a piece. In the current workflow I manually merge the separate parts into a single PDF before upload. A PDF collection would also conceivably include a dynamically-combined PDF file, if ImageMagick supports something like that.

Templates

While a custom post type with several custom fields and taxonomies would normally work best with custom theme templates, I wanted the sheet music library to be as theme-compatible as possible. So I implemented default templates for single and archive views by filtering the_content. It works pretty well on many themes, and could look decent on nearly any theme with a little custom CSS. For more advanced implementations, custom templates and adding theme support for ‘sheet_music_library’ will do the trick. I also created a shortcode that outputs the table view that I use on the homepage.

Search, taxonomies, archives, etc. all work well with the content filtering. The sheet music post type also supports featured images, so the theme’s templates display them to match other content types. I only use images on a few pieces in my library;they really stand out in search, custom taxonomies, and post navigation with Twenty Fifteen.

Themes & Design

I planned to start with a WordPress.org theme, then design a purpose-built companion theme to the sheet music library plugin. But after exploring numerous potential themes (while testing the theme compatibility of the plugin), I ultimately selected Twenty Fifteen. And I’m doubting that I will even need a child theme (I currently have some custom CSS, but that’s it). While I’m not happy with every element, its strong, scalable typography and its sticky sidebar functionality provide an excellent foundation. CelloExpressions.com features a global header on all sites in the network; with a widgetized theme sidebar and no header, I can offer robust site navigation in a simple layout. In fact, I ended up without a menu for the library, leveraging search and custom taxonomy widgets for content discovery.

My biggest problems with Twenty Fifteen were lack of color contrast, and areas with excessive whitespace (inefficient use of space). I initially planned to use Twenty Fourteen, since it provides so much space for navigation and is very space-efficient. But upon further investigation, the homepage table view is the primary element that needs horizontal space. I removed some margins to uncover space for the table views. The Twenty Fifteen’s custom color options offered a quick fix for color contrast, alongside the dark “global” Cello Expressions header.

I also designed a new logo for myself and Cello Expressions as part of this process. I started out on paper, from doodles sketches while trying to stay awake during class. My final result works great in vector format and contains several implied meanings that I’ll detail in a future post. Currently, I’m using it in the header and as the site icon. I’ll use it elsewhere as opportunities arise.

Cello Expressions Logo

Migration & New Content

Once the new plugin was finally complete and I’d settled on using Twenty Fifteen, it was time for content. In addition to migrating the 60+ pieces from the old site to the new site, I needed to add two productive years work of music that never made it into the old system.

Because the old implementation was so bad, and most of the old fields wouldn’t translate cleanly to the new taxonomies for composers, instruments, difficulties, and genres, I manually migrated all of the content. This also gave me the opportunity to remove some pieces that weren’t up to my current standards.

I started by moving the entire contents of my old server to the new Bluehost server, renaming the /music/ directory to /music-archive/. Then, once I moved the nameservers, I created a new site in the celloexpressions.com multisite network, at /music/. After putting some text in the homepage and setting up my plugins, I started migrating content.

After nearly two weeks and countless hours, I ended up with 104 pieces in the new sheet music library. I migrated about half of the pieces from the old library, and newly published the other half. At a rough estimate, two-thirds have an audio or video recording, or both. They all have scores, terms in four taxonomies, and publication dates back-dated to the original publication time. I will audit the actual musical content for quality and usage over time.

Despite a colossal effort that’s still not quite complete, this project was very much worth it. And the best part is that the work, from the software behind the scenes to the music it contains, is free for anyone to use in the spirit of open source.

One thought on “New Sheet Music Library: The Story

Comments are closed.