From cb8b8b4a61950839591e750ebc09e6d31a4a8cb3 Mon Sep 17 00:00:00 2001 From: Bui Date: Wed, 17 Oct 2018 22:16:53 +0100 Subject: [PATCH 1/4] generate previews for songs --- app.py | 80 +++++++++++++++++++++++++++++++------ public/src/js/songselect.js | 11 ++--- 2 files changed, 73 insertions(+), 18 deletions(-) diff --git a/app.py b/app.py index 2235372..2c5ebbb 100644 --- a/app.py +++ b/app.py @@ -1,10 +1,13 @@ #!/usr/bin/env python2 +from __future__ import division + import json import sqlite3 import re import os -from flask import Flask, g, jsonify, render_template +from flask import Flask, g, jsonify, render_template, request, abort, redirect +from ffmpy import FFmpeg app = Flask(__name__) DATABASE = 'taiko.db' @@ -60,6 +63,21 @@ def get_osu_key(osu, section, key, default=None): return default +def get_preview(song_id, song_type): + preview = 0 + + if song_type == "tja": + if os.path.isfile('public/songs/%s/main.tja' % song_id): + preview = get_tja_preview('public/songs/%s/main.tja' % song_id) + else: + osus = [osu for osu in os.listdir('public/songs/%s' % song_id) if osu in ['easy.osu', 'normal.osu', 'hard.osu', 'oni.osu']] + if osus: + osud = parse_osu('public/songs/%s/%s' % (song_id, osus[0])) + preview = int(get_osu_key(osud, 'General', 'PreviewTime', 0)) + + return preview + + def get_tja_preview(tja): tja_lines = open(tja, 'r').read().replace('\x00', '').split('\n') @@ -95,6 +113,24 @@ def route_index(): return render_template('index.html', version=version) +@app.route('/api/preview') +def route_api_preview(): + song_id = request.args.get('id', None) + if not song_id or not re.match('^[0-9]+$', song_id): + abort(400) + + song_row = query_db('select * from songs where id = ? and enabled = 1', (song_id,)) + if not song_row: + abort(400) + + song_type = song_row[0][10] + prev_path = make_preview(song_id, song_type) + if not prev_path: + return redirect(''.join([request.host_url, '/songs/%s/main.mp3' % song_id])) + + return redirect(''.join([request.host_url, '/songs/%s/preview.mp3' % song_id])) + + @app.route('/api/songs') def route_api_songs(): songs = query_db('select * from songs where enabled = 1') @@ -107,18 +143,7 @@ def route_api_songs(): for song in songs: song_id = song[0] song_type = song[10] - if song_type == "tja": - if os.path.isfile('public/songs/%s/main.tja' % song_id): - preview = get_tja_preview('public/songs/%s/main.tja' % song_id) - else: - preview = 0 - else: - osus = [osu for osu in os.listdir('public/songs/%s' % song_id) if osu in ['easy.osu', 'normal.osu', 'hard.osu', 'oni.osu']] - if osus: - osud = parse_osu('public/songs/%s/%s' % (song_id, osus[0])) - preview = int(get_osu_key(osud, 'General', 'PreviewTime', 0)) - else: - preview = 0 + preview = get_preview(song_id, song_type) category_out = categories[song[9]] if song[9] in categories else def_category songs_out.append({ @@ -138,5 +163,34 @@ def route_api_songs(): return jsonify(songs_out) +def make_preview(song_id, song_type): + song_path = 'public/songs/%s/main.mp3' % song_id + prev_path = 'public/songs/%s/preview.mp3' % song_id + + if os.path.isfile(song_path) and not os.path.isfile(prev_path): + preview = get_preview(song_id, song_type) / 1000 + if not preview or preview <= 0.1: + print 'Skipping #%s due to no preview' % song_id + return False + + print 'Making preview.mp3 for song #%s' % song_id + ff = FFmpeg(inputs={song_path: '-ss %s' % preview}, + outputs={prev_path: '-codec:a libmp3lame -b:a 128k -y -loglevel panic'}) + ff.run() + + return prev_path + + +def check_song_previews(): + with app.app_context(): + songs = query_db('select * from songs where enabled = 1') + + for song in songs: + make_preview(song[0], song[10]) + + +check_song_previews() + + if __name__ == '__main__': app.run(port=34801) diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index 61a4641..27741f9 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -1263,16 +1263,17 @@ class SongSelect{ } var songObj = assets.songs.find(song => song.id == id) - if(songObj.sound){ + if(songObj.preview_sound){ if(!loadOnly){ - this.preview = songObj.sound + this.preview = songObj.preview_sound this.preview.gain = snd.previewGain this.previewLoaded(startLoad, prvTime) } }else{ - snd.previewGain.load("/songs/" + id + "/main.mp3").then(sound => { + var previewFilename = prvTime > 0.1 ? "/preview.mp3" : "/main.mp3" + snd.previewGain.load("/songs/" + id + previewFilename).then(sound => { if(currentId === this.previewId){ - songObj.sound = sound + songObj.preview_sound = sound this.preview = sound this.previewLoaded(startLoad, prvTime) } @@ -1285,7 +1286,7 @@ class SongSelect{ var difference = endLoad - startLoad var minDelay = 300 var delay = minDelay - Math.min(minDelay, difference) - this.preview.playLoop(delay / 1000, false, prvtime / 1000) + this.preview.playLoop(delay / 1000, false, 0) } endPreview(){ this.previewId++ From 592e54dc9ba215cc2e19bb2e1ebd844c02bf3304 Mon Sep 17 00:00:00 2001 From: Bui Date: Thu, 18 Oct 2018 00:11:14 +0100 Subject: [PATCH 2/4] adjust ffmpeg command, remove startup preview checks --- app.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/app.py b/app.py index 2c5ebbb..59cf450 100644 --- a/app.py +++ b/app.py @@ -167,6 +167,9 @@ def make_preview(song_id, song_type): song_path = 'public/songs/%s/main.mp3' % song_id prev_path = 'public/songs/%s/preview.mp3' % song_id + if os.path.isfile(prev_path): + os.remove(prev_path) + if os.path.isfile(song_path) and not os.path.isfile(prev_path): preview = get_preview(song_id, song_type) / 1000 if not preview or preview <= 0.1: @@ -175,22 +178,11 @@ def make_preview(song_id, song_type): print 'Making preview.mp3 for song #%s' % song_id ff = FFmpeg(inputs={song_path: '-ss %s' % preview}, - outputs={prev_path: '-codec:a libmp3lame -b:a 128k -y -loglevel panic'}) + outputs={prev_path: '-codec:a libmp3lame -ar 32000 -b:a 92k -y -loglevel panic'}) ff.run() return prev_path -def check_song_previews(): - with app.app_context(): - songs = query_db('select * from songs where enabled = 1') - - for song in songs: - make_preview(song[0], song[10]) - - -check_song_previews() - - if __name__ == '__main__': app.run(port=34801) From c2ea4514ca0f3256b716af0101e429f36c34d308 Mon Sep 17 00:00:00 2001 From: Bui Date: Thu, 18 Oct 2018 00:11:59 +0100 Subject: [PATCH 3/4] remove debug lines --- app.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/app.py b/app.py index 59cf450..1fa7c94 100644 --- a/app.py +++ b/app.py @@ -167,9 +167,6 @@ def make_preview(song_id, song_type): song_path = 'public/songs/%s/main.mp3' % song_id prev_path = 'public/songs/%s/preview.mp3' % song_id - if os.path.isfile(prev_path): - os.remove(prev_path) - if os.path.isfile(song_path) and not os.path.isfile(prev_path): preview = get_preview(song_id, song_type) / 1000 if not preview or preview <= 0.1: From 0b757c0983c7dbdfd558ea72eb869310399cd7af Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Thu, 18 Oct 2018 02:54:00 +0300 Subject: [PATCH 4/4] Allow preview to start when there is an error converting --- public/src/js/songselect.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index 27741f9..f14f22d 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -1267,26 +1267,35 @@ class SongSelect{ if(!loadOnly){ this.preview = songObj.preview_sound this.preview.gain = snd.previewGain - this.previewLoaded(startLoad, prvTime) + this.previewLoaded(startLoad, songObj.preview_time) } }else{ var previewFilename = prvTime > 0.1 ? "/preview.mp3" : "/main.mp3" - snd.previewGain.load("/songs/" + id + previewFilename).then(sound => { + + var loadPreview = previewFilename => { + return snd.previewGain.load("/songs/" + id + previewFilename) + } + + songObj.preview_time = 0 + loadPreview(previewFilename).catch(() => { + songObj.preview_time = prvTime + return loadPreview("/main.mp3") + }).then(sound => { if(currentId === this.previewId){ songObj.preview_sound = sound this.preview = sound - this.previewLoaded(startLoad, prvTime) + this.previewLoaded(startLoad, songObj.preview_time) } }) } } } - previewLoaded(startLoad, prvtime){ + previewLoaded(startLoad, prvTime){ var endLoad = this.getMS() var difference = endLoad - startLoad var minDelay = 300 var delay = minDelay - Math.min(minDelay, difference) - this.preview.playLoop(delay / 1000, false, 0) + this.preview.playLoop(delay / 1000, false, prvTime / 1000) } endPreview(){ this.previewId++