Merge branch 'saas-dev' into saas-dev-publishing

Conflicts:
	airtime_mvc/application/controllers/ApiController.php
This commit is contained in:
Albert Santoni 2015-11-18 12:38:18 -05:00
commit 965a78c54a
16 changed files with 191 additions and 26 deletions

View file

@ -28,12 +28,38 @@ class CuePointAnalyzer(Analyzer):
try:
results_json = subprocess.check_output(command, stderr=subprocess.STDOUT, close_fds=True)
silan_results = json.loads(results_json)
metadata['length_seconds'] = float(silan_results['file duration'])
# Conver the length into a formatted time string
track_length = datetime.timedelta(seconds=metadata['length_seconds'])
metadata["length"] = str(track_length)
metadata['cuein'] = format(silan_results['sound'][0][0], 'f')
metadata['cueout'] = format(silan_results['sound'][0][1], 'f')
# Defensive coding against Silan wildly miscalculating the cue in and out times:
silan_length_seconds = float(silan_results['file duration'])
silan_cuein = format(silan_results['sound'][0][0], 'f')
silan_cueout = format(silan_results['sound'][0][1], 'f')
# Sanity check the results against any existing metadata passed to us (presumably extracted by Mutagen):
if 'length_seconds' in metadata:
# Silan has a rare bug where it can massively overestimate the length or cue out time sometimes.
if (silan_length_seconds - metadata['length_seconds'] > 3) or (float(silan_cueout) - metadata['length_seconds'] > 2):
# Don't trust anything silan says then...
raise Exception("Silan cue out {0} or length {1} differs too much from the Mutagen length {2}. Ignoring Silan values."
.format(silan_cueout, silan_length_seconds, metadata['length_seconds']))
# Don't allow silan to trim more than the greater of 3 seconds or 5% off the start of a track
if float(silan_cuein) > max(silan_length_seconds*0.05, 3):
raise Exception("Silan cue in time {0} too big, ignoring.".format(silan_cuein))
else:
# Only use the Silan track length in the worst case, where Mutagen didn't give us one for some reason.
# (This is mostly to make the unit tests still pass.)
# Convert the length into a formatted time string.
metadata['length_seconds'] = silan_length_seconds #
track_length = datetime.timedelta(seconds=metadata['length_seconds'])
metadata["length"] = str(track_length)
''' XXX: I've commented out the track_length stuff below because Mutagen seems more accurate than silan
as of Mutagen version 1.31. We are always going to use Mutagen's length now because Silan's
length can be off by a few seconds reasonably often.
'''
metadata['cuein'] = silan_cuein
metadata['cueout'] = silan_cueout
except OSError as e: # silan was not found
logging.warn("Failed to run: %s - %s. %s" % (command[0], e.strerror, "Do you have silan installed?"))

View file

@ -67,8 +67,11 @@ class MetadataAnalyzer(Analyzer):
track_length = datetime.timedelta(seconds=info.length)
metadata["length"] = str(track_length) #time.strftime("%H:%M:%S.%f", track_length)
# Other fields for Airtime
metadata["cueout"] = metadata["length"]
metadata["cueout"] = metadata["length"]
# Set a default cue in time in seconds
metadata["cuein"] = 0.0;
if hasattr(info, "bitrate"):
metadata["bit_rate"] = info.bitrate

View file

@ -27,7 +27,7 @@ setup(name='airtime_analyzer',
packages=['airtime_analyzer'],
scripts=['bin/airtime_analyzer'],
install_requires=[
'mutagen',
'mutagen==1.31', # The Mutagen guys change stuff all the time that break our unit tests. Watch out for this.
'pika',
'daemon',
'python-magic',

View file

@ -24,7 +24,7 @@ def test_mp3_mono():
metadata = MetadataAnalyzer.analyze(u'tests/test_data/44100Hz-16bit-mono.mp3', dict())
check_default_metadata(metadata)
assert metadata['channels'] == 1
assert metadata['bit_rate'] == 64000
assert metadata['bit_rate'] == 64876
assert abs(metadata['length_seconds'] - 3.9) < 0.1
assert metadata['mime'] == 'audio/mp3' # Not unicode because MIMEs aren't.
assert metadata['track_total'] == u'10' # MP3s can have a track_total
@ -34,7 +34,7 @@ def test_mp3_jointstereo():
metadata = MetadataAnalyzer.analyze(u'tests/test_data/44100Hz-16bit-jointstereo.mp3', dict())
check_default_metadata(metadata)
assert metadata['channels'] == 2
assert metadata['bit_rate'] == 128000
assert metadata['bit_rate'] == 129757
assert abs(metadata['length_seconds'] - 3.9) < 0.1
assert metadata['mime'] == 'audio/mp3'
assert metadata['track_total'] == u'10' # MP3s can have a track_total
@ -43,7 +43,7 @@ def test_mp3_simplestereo():
metadata = MetadataAnalyzer.analyze(u'tests/test_data/44100Hz-16bit-simplestereo.mp3', dict())
check_default_metadata(metadata)
assert metadata['channels'] == 2
assert metadata['bit_rate'] == 128000
assert metadata['bit_rate'] == 129757
assert abs(metadata['length_seconds'] - 3.9) < 0.1
assert metadata['mime'] == 'audio/mp3'
assert metadata['track_total'] == u'10' # MP3s can have a track_total
@ -52,7 +52,7 @@ def test_mp3_dualmono():
metadata = MetadataAnalyzer.analyze(u'tests/test_data/44100Hz-16bit-dualmono.mp3', dict())
check_default_metadata(metadata)
assert metadata['channels'] == 2
assert metadata['bit_rate'] == 128000
assert metadata['bit_rate'] == 129757
assert abs(metadata['length_seconds'] - 3.9) < 0.1
assert metadata['mime'] == 'audio/mp3'
assert metadata['track_total'] == u'10' # MP3s can have a track_total
@ -109,7 +109,7 @@ def test_mp3_utf8():
assert metadata['genre'] == u'Я Б Г Д Ж Й'
assert metadata['track_number'] == u'1'
assert metadata['channels'] == 2
assert metadata['bit_rate'] == 128000
assert metadata['bit_rate'] == 129757
assert abs(metadata['length_seconds'] - 3.9) < 0.1
assert metadata['mime'] == 'audio/mp3'
assert metadata['track_total'] == u'10' # MP3s can have a track_total
@ -153,7 +153,7 @@ def test_mp3_bad_channels():
metadata = MetadataAnalyzer.analyze(filename, dict())
check_default_metadata(metadata)
assert metadata['channels'] == 1
assert metadata['bit_rate'] == 64000
assert metadata['bit_rate'] == 64876
assert abs(metadata['length_seconds'] - 3.9) < 0.1
assert metadata['mime'] == 'audio/mp3' # Not unicode because MIMEs aren't.
assert metadata['track_total'] == u'10' # MP3s can have a track_total

View file

@ -1,6 +1,6 @@
from threading import Thread
import urllib2
import xml.dom.minidom
import defusedxml.minidom
import base64
from datetime import datetime
import traceback
@ -64,7 +64,7 @@ class ListenerStat(Thread):
else:
url = 'http://%(host)s:%(port)s/admin/stats.xml' % ip
document = self.get_stream_server_xml(ip, url)
dom = xml.dom.minidom.parseString(document)
dom = defusedxml.minidom.parseString(document)
sources = dom.getElementsByTagName("source")
mount_stats = None
@ -87,7 +87,7 @@ class ListenerStat(Thread):
def get_shoutcast_stats(self, ip):
url = 'http://%(host)s:%(port)s/admin.cgi?sid=1&mode=viewxml' % ip
document = self.get_stream_server_xml(ip, url, is_shoutcast=True)
dom = xml.dom.minidom.parseString(document)
dom = defusedxml.parseString(document)
current_listeners = dom.getElementsByTagName("CURRENTLISTENERS")
timestamp = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")

View file

@ -58,7 +58,8 @@ setup(name='airtime-playout',
'pyinotify',
'pytz',
'requests',
'wsgiref'
'wsgiref',
'defusedxml'
],
zip_safe=False,
data_files=data_files)