mirror of
https://github.com/spl0k/supysonic.git
synced 2024-12-22 17:06:17 +00:00
Transcoding
This commit is contained in:
parent
92add62a7c
commit
2d0774abeb
70
api/media.py
70
api/media.py
@ -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():
|
||||||
|
11
scanner.py
11
scanner.py
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user