1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-09-19 19:01:03 +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
from flask import request, send_file
from flask import request, send_file, Response
import os.path
from PIL import Image
import subprocess
import config
import config, scanner
from web import app
from db import Track, Folder, User, now, session
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' ])
def stream_media():
status, res = get_entity(request, Track)
@ -19,20 +28,58 @@ def stream_media():
if format:
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:
try:
maxBitRate = int(maxBitRate)
except:
return request.error_formatter(0, 'Invalid bitrate value')
if res.bitrate > maxBitRate:
# TODO transcode
pass
if dst_bitrate > maxBitRate and maxBitRate != 0:
do_transcoding = True
dst_bitrate = maxBitRate
if format and format != res.suffix():
# TODO transcode
pass
if format and format != src_suffix:
do_transcoding = True
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.last_play = now()
@ -40,10 +87,7 @@ def stream_media():
request.user.last_play_date = now()
session.commit()
if estimateContentLength == 'true':
return send_file(res.path), 200, { 'Content-Length': os.path.getsize(res.path) }
return send_file(res.path)
return response
@app.route('/rest/download.view', methods = [ 'GET', 'POST' ])
def download_media():

View File

@ -5,6 +5,17 @@ import time, mimetypes
import mutagen
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:
def __init__(self, session):
self.__session = session