Getting Audio Information in Python

Want to grab some basic audio file information in your Python program?

Let’s use Mutagen to look at the type, length, and size of an audio element.

import mutagen

class Audio:
    pass

f = "some_audio.m4a"
element = mutagen.File(f)

if element:
    Audio.format_list = element._mimes
    Audio.size = element.size
    Audio.length = element.length
else:
    Audio.error = "Invalid audio file."

Here, we could have imported the M4A handler, but using the File class we don’t have to make audio type assumptions a priori. If the audio format cannot be handled or is invalid, we will simply get a None Type return when sending our file to the File class.

Game Recommendations : Round 1

Try to throw up rudimentary, sometimes cringe-worthy quality recommendations on Steam of the PC games I’m playing. Figured that with my minimalist friends list on Steam that there may be some more benefit reaped from those inexpertly written reviews by posting them here as well. So without further ado, here are the first batch:

Osmos
  • Great little game with some fun physics (think elliptical orbits). Soundtrack is superb!

 

 

Steal Storm: Burning Retribution
  • Great arcade feel and tight controls, engaging soundtrack, strong visuals and explosion sprites accompanied by well done sound effects. Addictive.

 

 

Crayon Physics Deluxe
  • Fun. Each level can be as easy or complex as you wish… Can be pretty tricky to flag levels. Cute.

 

 

Borderlands
  • Amazing! Cell shaded FPS in all it’s glory… doesn’t get much better than this for an RPG/FPS. Tough game.

 

 

Chessmaster Challenge
  • The old chessmaster I remember from systems like Gameboy but now with really great tutorials. Also has a mode that teaches you advanced strategies (openings, defenses, etc) from chess champions in a tutorial format.

 

Prince of Persia
  • Ubisoft+PoP+cell shading … greatness all around. Beautiful game and supremely enjoyable adventure. Very relaxing!

BUT — broken with steam. Overlay won’t work and does not register any playtime, etc, with steam. Can buy and launch through steam just fine though. A 3+ year issue that hasn’t been fixed but don’t let it hinder you from buying and playing the game… just a heads up.

 

Sid Meier's Civilization V
  • Total crack… that’s all I’ll say. If you don’t mind countless, back to back all-nighters then go ahead and play, you won’t be disappointed.

 

 

Trine
  • One of the most beautiful games I’ve ever played. Excellent gameplay, engaging story and characters, a lot of depth across each of the 3 playable characters, and did I mention it was insanely beautiful?

Got this game on sale and actually felt really bad playing it and realizing how little I paid for it. That says everything you need to know. Buy it, play it, love it!

More to come…

Netflix Stock Dives

I have recently vetted some frustration with Netflix of late; you can catch up on here.

Today, according to the NYTimes, Netflix stock has taken quite the dive on news of a huge loss in customer subscriptions. You can read that article here.

The company on Thursday morning revised downward, incrementally, its subscriber estimates for the quarter of the year that ends in two weeks. It did not change its financial guidance for the quarter. Still, its stock dropped almost 15 percent in heavy trading when the market opened Thursday.
– BRIAN STELTER NYTimes

Seems to me that these issues need to be more publicly addressed or this could be the legitimate start of Netflix’ fall from the top.

 

Uploading Images to imgur with Python

That time again. Code snippet time.

UPDATE: See the bottom of the post for the most up-to-date version of the code.

Another brief one. We are going to start working on a class to upload images to imgur.com. There are many ways we can go about doing this, but to start things off, we’ll use the simplest way which is to use the public/anonymous API. This means that anyone can view our images and that we do not need to worry about authentication just yet.

We will use pycurl for the url handling and parameter passing and to decipher our results we will utilize the XML minidom.

Let’s jump right in and see the code. You will need an API key, available here, that you will need to substitute for the key parameter string “YOUR_API_KEY_HERE”.

class UploadImage():
	"""
	Upload images to imgur
	"""

	# Not very verbose at the moment in terms of errors - will build on that later
	def __init__(self,image,upload_method="anon"):
		import pycurl
		from xml.dom import minidom
		import cStringIO

		# setup some initial items we will need
		self.c = pycurl.Curl()
		self.response = cStringIO.StringIO()
		self.minidom = minidom
		self.image = image
		self.imageURL = ""
		self.error = ""

		# provide some various methods for uploading
		# by default - at least for now in testing - we will use anonymous upload method
		if upload_method == "anon":
			self.anon_upload()
		# later or on-demand we can switch to oauth based uploads
		elif upload_method == "oauth":
			self.auth_upload()

	# anonymous upload method
	def anon_upload(self):
		"Upload anonymously to imgur"

		# setup the basic parameters
		params = [
				("key", "YOUR_API_KEY_HERE"),
				("image", (self.c.FORM_FILE, self.image))
			]

		# setup the url and pipe in our key and image
		self.c.setopt(self.c.URL, "http://api.imgur.com/2/upload.xml")
		self.c.setopt(self.c.HTTPPOST, params)

		# we want to capture the output so lets set the write output to go to our cStringIO so we can parse it
		self.c.setopt(self.c.WRITEFUNCTION, self.response.write)

		# run it
		self.c.perform()
		self.c.close()

		try:
			# parse the XML return string and get the URL of our image
			xml = self.minidom.parseString(self.response.getvalue())
			self.imageURL = xml.getElementsByTagName("original")[0].firstChild.data

		except:
			self.error = "Problem uploading anonymously."

		return self.imageURL,self.error

	# oauth-based upload method
	def oauth_upload(self):
		"Upload using oauth to imgur"

		### Not coded yet but we will use python-oauth2
		pass

To use our uploader, all we have to do is something like the following:

In [1]: from handlers import UploadImage as U

In [2]: a = U('roosevelt.jpg')

In [3]: a.imageURL
Out[3]: u'http://i.imgur.com/cUWzn.jpg'

In [4]: a.error
Out[4]: ''

As you can surmise, we could simply check that there was no error and then utilize the returned URL of our newly uploaded image. Pretty simple stuff and very handy for some quick public/disposable image uploads.

Next time, we will expand our uploader to include an oAuth method that we can utilize for private uploads. Additionally, we will explore our XML returns a little deeper for methods to delete our files or grab some basic view statistics.

Updated code: Here, we are using things in the context of Django, hence the settings call for pulling in the API key and so forth.

class UploadImage():
	"""
	Upload images to imgur
	  returns either .error or .imageURL

	TO DO:

	POSSIBLE TO DO:
		- add stats and image info functions
		- allow for full JSON responses instead of having to manually parse XML

	"""

	# Not very verbose at the moment in terms of errors - will build on that later
	def __init__(self,image="",dhash="",delete=False):

		# setup some initial items and placeholders we will need
		self.c = pycurl.Curl()
		self.response = cStringIO.StringIO()
		self.minidom = minidom
		self.image = image
		self.dhash = dhash.__str__()
		self.delete = delete
		self.message = ""
		self.imageURL = {}
		self.error = []

		if self.dhash and self.delete:
			# if we have a hash and a delete trigger, lets try to wipe the image
			self.wipe()

		else:
			# fire away an upload - we will return an imageURL dictionary with attributes or an error
			self.upload()


	def upload(self):
		"Upload anonymously to imgur"

		# setup the basic parameters
		params = [
				("key", settings.imgur["anon_key"]),
				("image", (self.c.FORM_FILE, self.image))
			]

		# setup the url and pipe in our key and image
		self.c.setopt(self.c.URL, "http://api.imgur.com/2/upload.xml")
		self.c.setopt(self.c.HTTPPOST, params)

		# we want to capture the output so lets set the write output to go to our cStringIO so we can parse it
		self.c.setopt(self.c.WRITEFUNCTION, self.response.write)

		try:
			# run it
			self.c.perform()
			self.c.close()

		except:
			self.error.append("Problem uploading image.")

		if not self.error:
			# parse the xml
			self.parseXML()


		return self.message,self.imageURL,self.error


	def wipe(self):
		"Wipe an anonymouse image from imgur"

		deleteURL = "http://api.imgur.com/2/delete/%s" % self.dhash

		self.c.setopt(self.c.URL, deleteURL)

		self.c.setopt(self.c.WRITEFUNCTION, self.response.write)

		try:
			self.c.perform()
			self.c.close()

		except:
			self.error.append("Problem deleting image.")

		if not self.error:
			self.parseXML(delete=True)


	def parseXML(self,delete=False):
		"Parse the XML ouput from IMGUR and write to the imageURL dictionary"

		try:
			# parse the XML string into the dom
			xml = self.minidom.parseString(self.response.getvalue())

			if delete:
				self.message = xml.getElementsByTagName("message")[0].firstChild.data

			else:
				# grab out some helpful/interesting data and setup in the imageURL dictionary
				self.imageURL['url'] = xml.getElementsByTagName("original")[0].firstChild.data
				self.imageURL['hash'] = xml.getElementsByTagName("hash")[0].firstChild.data
				self.imageURL['deletehash'] = xml.getElementsByTagName("deletehash")[0].firstChild.data
				self.imageURL['smallthumb'] = xml.getElementsByTagName("small_square")[0].firstChild.data
				self.imageURL['bigthumb'] = xml.getElementsByTagName("large_thumbnail")[0].firstChild.data

		except:
			self.error.append("Problem parsing XML output.")

Amazon Prime Streaming – Another Netflix Alternative for Linux?

Amazon announced this week that Prime users would now have access to a pool of free content to stream instantly from the video-on-demand portion of their website.

While the content might not be the latest and greatest blockbuster movies and shows, it is a substantial amount of content and worthy to be considered a viable contender for the streaming market. Take a look at the Netflix instant content pool. It’s pretty substantial now, but it still does not contain the latest movies (which are home rental only for the most part). Also consider that when Netflix instant started it was a rather meager offering of mostly meh content. Given such, it might be a sign of possible things to come for Amazon streaming.

Prime being a $79 a year opt-in might seem steep. If you are already a prime member, then it’s a moot point or better, further validates your spending $79 a year so you can get that video game on release date for free or so you can get that $10 paperback second day without having to pay the sub-$25 shipping penalty. If you aren’t a prime member, this seems like a great time to jump in. Along with awesome shipping, you can now stream movies and television instantly as well.

Still not sold? Here’s the cool part for us linux (or *BSD, etc) guys and girls: streaming is system independent, and so far seems to also be browser independent. Can you view Flash? Then you should be ready to roll watching Amazon’s instant content.

Now with Hulu (and Hulu-desktop) and Amazon instant being friends of an operating system independent approach, will that push Netflix along to allow all of us paying customers with Linux to utilize the instant features? Or will Netflix keep it’s head buried in the sand and stay cozy with Microsoft? Remember when we thought Flash was so evil, well looks like Silverlight has trumped that by leaps and bounds.

Before ending, I’ll make a quick note on performance. As of now, streaming is around 480p (supposedly). I’ve tested it out on two media PCs both running linux; Fedora setup connected to a 50″ plasma via HDMI and an Xubuntu setup connected to a 32″ CRT via s-video. Both setups streamed very nicely, and while it obviously isn’t in HD, even on the 50″ television, the quality was just fine. The big positive performance point (sorry) was that there was not a single buffer wait, stutter, or hiccup in the stream. Granted, this isn’t a very scientific comparison, but I wouldn’t be surprised to see the power of Amazon shining through in the technical side of the streaming business. I mean they already figured out a nice way to stream content without sleeping with Microsoft to keep the bad guys from ripping content. [Update: There are HD options available. The Best of NOVA #6 and Yellowstone are both offered in an HD version and looked and streamed great.]

Prime member? Check it out. Not a Prime member? Seems like  a great time to join in, especially if you are a frequent Amazon shopper.