Skip to content

Commit

Permalink
temp
Browse files Browse the repository at this point in the history
  • Loading branch information
xuancong84 committed Mar 7, 2024
1 parent 987952c commit e78adc5
Show file tree
Hide file tree
Showing 26 changed files with 1,541 additions and 624 deletions.
150 changes: 101 additions & 49 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,51 @@
import signal, subprocess, threading, time, traceback, webbrowser
from functools import wraps

import cherrypy
import psutil
import psutil, tempfile
from unidecode import unidecode
from flask import *
from flask.logging import logging
from pydub import AudioSegment as AudSeg
from flask_sock import Sock
from flask_paginate import Pagination, get_page_parameter

import karaoke
from constants import VERSION
from collections import defaultdict
from lib.get_platform import *
from lib.vlcclient import get_default_vlc_path
from lib.NLP import *

try:
from urllib.parse import quote, unquote
except ImportError:
from urllib import quote, unquote

app = Flask(__name__)
app.config['TEMPLATES_AUTO_RELOAD'] = True ##DEBUG
app.secret_key = os.urandom(24)
site_name = "PiKaraoke"
admin_password = K = None
admin_password = K = args = None
sock = Sock(app)
os.texts = defaultdict(lambda: "")
getString = lambda ii: os.texts[ii]
getString1 = lambda lang, ii: os.langs[lang].get(ii, os.langs['en_US'][ii])
ip2websock = {}


# Websocket handler
@sock.route('/ws_init')
def ws_init(sock):
global ip2websock
key = sock.sock.getpeername()[0]
ip2websock[key] = sock
while sock.connected:
try:
cmd = sock.receive()
wscmd(key, cmd)
except:
traceback.print_exc()
ip2websock.pop(key)


# Define global symbols for Jinja templates
Expand Down Expand Up @@ -76,6 +96,26 @@ def is_admin():


@app.route("/")
def root():
s = K.get_state()
return render_template(
"index.html",
getString1 = lambda ii: getString1(request.client_lang, ii),
site_title = site_name,
title = "Home",
show_transpose = K.use_vlc,
transpose_value = K.now_playing_transpose,
volume = s['volume'],
admin = is_admin(),
seektrack_value = s['time'],
seektrack_max = s['length'],
audio_delay = s['audiodelay'],
play_speed = s['rate'],
vocal_info = K.get_vocal_info(),
)


@app.route("/home")
def home():
s = K.get_state()
return render_template(
Expand Down Expand Up @@ -514,7 +554,7 @@ def splash():
"splash.html",
getString1 = lambda ii: getString1(request.client_lang, ii),
blank_page=True,
url="http://" + request.host
url=request.url_root
)

@app.route("/info")
Expand Down Expand Up @@ -578,14 +618,39 @@ def info():
)


def wscmd(key, cmd):
pass

def _add_spoken():
global args
with open(f'{K.tmp_dir}/rec.mp3', 'rb') as f:
r = requests.post(args.cloud+'/run_asr/base', files={'file': f}, timeout=6)
asr_output = json.loads(r.text) if r.status_code==200 else {}

print(f'ASR result: {asr_output}', file=sys.stderr)
if asr_output=={} or type(asr_output)==str:
return logging.error(f'ASR error: HTTP status code = {r.status_code} ()')
elif not asr_output['text']:
return logging.error(f'Warning: ASR output is empty')

res = findMedia(K.download_path, asr_output['text'], lang=asr_output['language'])


@app.route('/add_spoken', methods=['POST'])
def add_spoken():
with open(f'{K.tmp_dir}/rec.webm', 'wb') as fp:
fp.write(request.data)
AudSeg.from_file(f'{K.tmp_dir}/rec.webm', format='webm').export(f'{K.tmp_dir}/rec.mp3', 'mp3')
threading.Thread(target=_add_spoken).start()
return 'OK'


# Delay system commands to allow redirect to render first
def delayed_halt(cmd):
time.sleep(3)
if K.vocal_process is not None and K.vocal_process.is_alive():
K.vocal_process.terminate()
K.queue_clear() # stop all pending omxplayer processes
cherrypy.engine.stop()
cherrypy.engine.exit()
K.stop()
if cmd == 0:
os.system('(sleep 2 && tmux kill-session -t PiKaraoke) &')
Expand Down Expand Up @@ -683,16 +748,15 @@ def expand_fs():
return redirect(url_for("home"))


# Handle sigterm, apparently cherrypy won't shut down without explicit handling
# Handle sigterm
signal.signal(signal.SIGTERM, lambda signum, stack_frame: K.stop())


def get_default_dl_dir(platform):
if platform == "raspberry_pi":
return "/usr/lib/pikaraoke/songs"
else:
legacy_directory = os.path.expanduser("~/pikaraoke/songs")
return legacy_directory if os.path.exists(legacy_directory) else os.path.expanduser("~/pikaraoke-songs")
def get_default_dl_dir():
return os.path.expanduser("~/pikaraoke-songs")

def get_default_tmp_dir():
return '/dev/shm' if os.path.isdir('/dev/shm') else tempfile.gettempdir()


def get_default_browser_cookie(platform):
Expand Down Expand Up @@ -731,7 +795,7 @@ def get_default_browser_cookie(platform):
default_splash_delay = 3
default_log_level = logging.INFO

default_dl_dir = get_default_dl_dir(platform)
default_dl_dir = get_default_dl_dir()
default_omxplayer_path = "/usr/bin/omxplayer"
default_adev = "both"
default_vlc_path = get_default_vlc_path(platform)
Expand All @@ -746,8 +810,8 @@ def get_default_browser_cookie(platform):
default = None,
)
parser.add_argument(
"-p", "--port",
help = f"Desired http port (default: {default_port})",
"-p", "--port", type=int,
help = f"Desired http/https port (default: {default_port})",
default = default_port,
)
parser.add_argument(
Expand Down Expand Up @@ -880,13 +944,19 @@ def get_default_browser_cookie(platform):
default = None,
)
parser.add_argument(
"--developer-mode",
help = "Run in flask developer mode. Only useful for tweaking the web UI in real time. Will disable the splash screen due to pygame main thread conflicts and may require FLASK_ENV=development env variable for full dev mode features.",
action = "store_true",
"--ssl", "-ssl",
help = "Use HTTPS instead of HTTP (browser microphone access requires HTTPS)",
action = 'store_true'
)
parser.add_argument('--cloud', '-C',
parser.add_argument(
"--temp", "-tp",
default = None,
help = "Temporary folder location",
)
parser.add_argument(
'--cloud', '-C',
default='',
help='full URL for cloud decoding',
help='cloud URL for DNN-based vocal split and speech recognition',
)
args = parser.parse_args()

Expand All @@ -898,6 +968,9 @@ def get_default_browser_cookie(platform):
app.jinja_env.globals.update(filename_from_path = filename_from_path)
app.jinja_env.globals.update(url_escape = quote)

args.tmp_dir = os.path.expanduser(args.temp or get_default_tmp_dir())
args.cloud = args.cloud.rstrip('/')

# Set browser cookies location for YouTube downloader
if args.browser_cookies.lower() == 'none':
args.cookies_opt = []
Expand Down Expand Up @@ -933,9 +1006,7 @@ def get_default_browser_cookie(platform):
sys.exit(1)

# setup/create download directory if necessary
args.dl_path = os.path.expanduser(args.download_path)
if not args.dl_path.endswith("/"):
args.dl_path += "/"
args.dl_path = os.path.expanduser(args.download_path).rstrip('/')+'/'
if platform == 'windows': # on Windows, VLC cannot open filenames containing '/'
args.dl_path = escape_win_filename(args.dl_path)
if not os.path.exists(args.dl_path):
Expand All @@ -951,31 +1022,12 @@ def get_default_browser_cookie(platform):
elif args.save_delays == 'no':
args.save_delays = None

if args.developer_mode:
logging.warning("Splash screen is disabled in developer mode due to main thread conflicts")
args.hide_splash_screen = True

# Configure karaoke process
os.K = K = karaoke.Karaoke(args)

if (args.developer_mode):
th = threading.Thread(target = K.run)
th.start()
app.run(debug = True, port = args.port)
else:
# Start the CherryPy WSGI web server
cherrypy.tree.graft(app, "/")
# Set the configuration of the web server
cherrypy.config.update(
{
"engine.autoreload.on": False,
"log.screen": True,
"server.socket_port": int(args.port),
"server.socket_host": "0.0.0.0",
}
)
cherrypy.engine.start()
K.run()
cherrypy.engine.exit()

sys.exit()
if not args.ssl:
threading.Thread(target=lambda:app.run(host='0.0.0.0', port=args.port+1, threaded = True, ssl_context=('cert.pem', 'key.pem'))).start()
threading.Thread(target=lambda:app.run(host='0.0.0.0', port=args.port, threaded = True, ssl_context=('cert.pem', 'key.pem') if args.ssl else None)).start()

K.run()
os._exit(0) # force-stop all flask threads and exit
22 changes: 22 additions & 0 deletions cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDrTCCApWgAwIBAgIUCYazL4hmpC1STPDhDnGm1gmjdhowDQYJKoZIhvcNAQEL
BQAwZjELMAkGA1UEBhMCU0cxEjAQBgNVBAgMCVNpbmdhcG9yZTESMBAGA1UEBwwJ
U2luZ2Fwb3JlMQ0wCwYDVQQKDARNT0hUMQwwCgYDVQQLDANEU1QxEjAQBgNVBAMM
CWxvY2FsaG9zdDAeFw0yNDAyMjAwMjM0NDNaFw0zNDAyMTcwMjM0NDNaMGYxCzAJ
BgNVBAYTAlNHMRIwEAYDVQQIDAlTaW5nYXBvcmUxEjAQBgNVBAcMCVNpbmdhcG9y
ZTENMAsGA1UECgwETU9IVDEMMAoGA1UECwwDRFNUMRIwEAYDVQQDDAlsb2NhbGhv
c3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIbkCFUznTbnoyVcnl
BBVo59KRxX88fmwzz5ZKs77UMXsgXIyr2hM12qISpSRq94HoQNCTC2apkb03iizd
ZQ6uF/lnGxstykCnhmDEh7nAGbAWCCeGRKi2WtKVmlamfF9pfm4Pxn2NWi9HBWyq
fYw9ipbg4BfGyStEW8JDqBSW0MoNdmoBSjQiCRy1yQvVk4JeidVyNoufA5WNu5gj
3UlZDBvLxh682kDNj93BKFFIY3Xf5oisAXfMZx97TvdznBim3y+z1pqbno0cyrYC
c9auCx3FYP3NQVJDt6I4gYTZBxq0cVza28rEeOb0vEJn06aerMbTelNLxARjLXwE
Lj/pAgMBAAGjUzBRMB0GA1UdDgQWBBS5CF9MG9pNxwqesiVU3Es/IxviWTAfBgNV
HSMEGDAWgBS5CF9MG9pNxwqesiVU3Es/IxviWTAPBgNVHRMBAf8EBTADAQH/MA0G
CSqGSIb3DQEBCwUAA4IBAQBU+cha1J8iW0JaT/5a3J9vLlRid1esk65X9zRmRWXA
KqKiO2+WHEWUx+PQD3yCCbm01brodDnnRCMZtWizr81WMTF4q/E/m/azy3i6Sqaq
rDvWkjWw+FVUvFZpwxLq+4+9HesXZHVu9ut1mhBShvzzEFu5dK4ukr5STl1ZJCzV
F2/v/XjN0zkik3/q++P1KbMta6cztJ5d2Y5EhJpf7CPteB/SWPxXp6CC7caxMsHS
pIc+ycofhwOWMjom1Q5gSpVU8/KvFM2GU8SCJhfAd0Yo1VQyPQDqA5QkM4R9aqee
HVFwdWyAF+0MgX+mmzXprkyc43DX22Lxp4+oXZJDhgJv
-----END CERTIFICATE-----
Loading

0 comments on commit e78adc5

Please sign in to comment.