1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-12-22 17:06:17 +00:00

Transcoding

This commit is contained in:
spl0k 2013-10-15 13:14:20 +02:00
parent 92add62a7c
commit 2d0774abeb
2 changed files with 68 additions and 13 deletions

View File

@ -1,14 +1,23 @@
# coding: utf-8 # coding: utf-8
from flask import request, send_file from flask import request, send_file, Response
import os.path import os.path
from PIL import Image from PIL import Image
import subprocess
import config import config, scanner
from web import app from web import app
from db import Track, Folder, User, now, session from db import Track, Folder, User, now, session
from api import get_entity from api import get_entity
def prepare_transcoding_cmdline(base_cmdline, input_file, input_format, output_format, output_bitrate):
if not base_cmdline:
return None
ret = base_cmdline.split()
for i in xrange(len(ret)):
ret[i] = ret[i].replace('%srcpath', input_file).replace('%srcfmt', input_format).replace('%outfmt', output_format).replace('%outrate', str(output_bitrate))
return ret
@app.route('/rest/stream.view', methods = [ 'GET', 'POST' ]) @app.route('/rest/stream.view', methods = [ 'GET', 'POST' ])
def stream_media(): def stream_media():
status, res = get_entity(request, Track) status, res = get_entity(request, Track)
@ -19,20 +28,58 @@ def stream_media():
if format: if format:
format = format.lower() format = format.lower()
if format != 'raw': do_transcoding = False
src_suffix = res.suffix()
dst_suffix = res.suffix()
dst_bitrate = res.bitrate
dst_mimetype = res.content_type
if format != 'raw': # That's from API 1.9.0 but whatever
if maxBitRate: if maxBitRate:
try: try:
maxBitRate = int(maxBitRate) maxBitRate = int(maxBitRate)
except: except:
return request.error_formatter(0, 'Invalid bitrate value') return request.error_formatter(0, 'Invalid bitrate value')
if res.bitrate > maxBitRate: if dst_bitrate > maxBitRate and maxBitRate != 0:
# TODO transcode do_transcoding = True
pass dst_bitrate = maxBitRate
if format and format != res.suffix(): if format and format != src_suffix:
# TODO transcode do_transcoding = True
pass dst_suffix = format
dst_mimetype = scanner.get_mime(dst_suffix)
if do_transcoding:
transcoder = config.get('transcoding', 'transcoder_{}_{}'.format(src_suffix, dst_suffix))
decoder = config.get('transcoding', 'decoder_' + src_suffix) or config.get('transcoding', 'decoder')
encoder = config.get('transcoding', 'encoder_' + dst_suffix) or config.get('transcoding', 'encoder')
if not transcoder and (not decoder or not encoder):
transcoder = config.get('transcoding', 'transcoder')
if not transcoder:
return request.error_formatter(0, 'No way to transcode from {} to {}'.format(src_suffix, dst_suffix))
transcoder, decoder, encoder = map(lambda x: prepare_transcoding_cmdline(x, res.path, src_suffix, dst_suffix, dst_bitrate), [ transcoder, decoder, encoder ])
if transcoder:
proc = subprocess.Popen(transcoder, stdout = subprocess.PIPE)
else:
dec_proc = subprocess.Popen(decoder, stdout = subprocess.PIPE)
proc = subprocess.Popen(encoder, stdin = dec_proc.stdout, stdout = subprocess.PIPE)
def transcode():
while True:
data = proc.stdout.read(8192)
if not data:
break
yield data
proc.terminate()
proc.wait()
response = Response(transcode(), mimetype = dst_mimetype)
else:
response = send_file(res.path)
# TODO handle estimateContentLength
res.play_count = res.play_count + 1 res.play_count = res.play_count + 1
res.last_play = now() res.last_play = now()
@ -40,10 +87,7 @@ def stream_media():
request.user.last_play_date = now() request.user.last_play_date = now()
session.commit() session.commit()
if estimateContentLength == 'true': return response
return send_file(res.path), 200, { 'Content-Length': os.path.getsize(res.path) }
return send_file(res.path)
@app.route('/rest/download.view', methods = [ 'GET', 'POST' ]) @app.route('/rest/download.view', methods = [ 'GET', 'POST' ])
def download_media(): def download_media():

View File

@ -5,6 +5,17 @@ import time, mimetypes
import mutagen import mutagen
import db import db
def get_mime(ext):
ret = mimetypes.guess_type('dummy.' + ext, False)[0]
if ret:
return ret
try:
module = __import__('mutagen.' + ext, fromlist = [ 'Open' ])
inst = module.Open()
return inst.mime[0]
except:
return None
class Scanner: class Scanner:
def __init__(self, session): def __init__(self, session):
self.__session = session self.__session = session