fix: support non-ascii languages in the spectrogram

This commit is contained in:
frederik
2025-05-01 19:49:52 +02:00
parent 0eab5428e4
commit ce38e3c5ad
3 changed files with 36 additions and 10 deletions
+1
View File
@@ -14,3 +14,4 @@ suntime==1.3.2
inotify inotify
requests requests
matplotlib matplotlib
pillow
+16
View File
@@ -12,6 +12,22 @@ _settings = None
DB_PATH = os.path.expanduser('~/BirdNET-Pi/scripts/birds.db') DB_PATH = os.path.expanduser('~/BirdNET-Pi/scripts/birds.db')
ANALYZING_NOW = os.path.expanduser('~/BirdSongs/StreamData/analyzing_now.txt') ANALYZING_NOW = os.path.expanduser('~/BirdSongs/StreamData/analyzing_now.txt')
FONT_DIR = os.path.expanduser('~/BirdNET-Pi/homepage/static')
def get_font():
conf = get_settings()
if conf['DATABASE_LANG'] == 'ar':
ret = {'font.family': 'Noto Sans Arabic', 'path': os.path.join(FONT_DIR, 'NotoSansArabic-Regular.ttf')}
elif conf['DATABASE_LANG'] in ['ja', 'zh']:
ret = {'font.family': 'Noto Sans JP', 'path': os.path.join(FONT_DIR, 'NotoSansJP-Regular.ttf')}
elif conf['DATABASE_LANG'] == 'ko':
ret = {'font.family': 'Noto Sans KR', 'path': os.path.join(FONT_DIR, 'NotoSansKR-Regular.ttf')}
elif conf['DATABASE_LANG'] == 'th':
ret = {'font.family': 'Noto Sans Thai', 'path': os.path.join(FONT_DIR, 'NotoSansThai-Regular.ttf')}
else:
ret = {'font.family': 'Roboto Flex', 'path': os.path.join(FONT_DIR, 'RobotoFlex-Regular.ttf')}
return ret
class PHPConfigParser(ConfigParser): class PHPConfigParser(ConfigParser):
+19 -10
View File
@@ -5,23 +5,18 @@ import logging
import os import os
import sqlite3 import sqlite3
import subprocess import subprocess
import tempfile
from time import sleep from time import sleep
import requests import requests
from PIL import Image, ImageDraw, ImageFont
from .helpers import get_settings, ParseFileName, Detection, DB_PATH from .helpers import get_settings, ParseFileName, Detection, get_font, DB_PATH
from .notifications import sendAppriseNotifications from .notifications import sendAppriseNotifications
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def get_safe_title(title):
result = subprocess.run(['iconv', '-f', 'utf8', '-t', 'ascii//TRANSLIT'],
check=True, input=title.encode('utf-8'), capture_output=True)
ret = result.stdout.decode('utf-8')
return ret
def extract(in_file, out_file, start, stop): def extract(in_file, out_file, start, stop):
result = subprocess.run(['sox', '-V1', f'{in_file}', f'{out_file}', 'trim', f'={start}', f'={stop}'], result = subprocess.run(['sox', '-V1', f'{in_file}', f'{out_file}', 'trim', f'={start}', f'={stop}'],
check=True, capture_output=True) check=True, capture_output=True)
@@ -50,15 +45,29 @@ def extract_safe(in_file, out_file, start, stop):
def spectrogram(in_file, title, comment, raw=False): def spectrogram(in_file, title, comment, raw=False):
fd, tmp_file = tempfile.mkstemp(suffix='.png')
os.close(fd)
args = ['sox', '-V1', f'{in_file}', '-n', 'remix', '1', 'rate', '24k', 'spectrogram', args = ['sox', '-V1', f'{in_file}', '-n', 'remix', '1', 'rate', '24k', 'spectrogram',
'-t', f'{get_safe_title(title)}', '-c', f'{comment}', '-o', f'{in_file}.png'] '-t', '', '-c', '', '-o', tmp_file]
args += ['-r'] if raw else [] args += ['-r'] if raw else []
result = subprocess.run(args, check=True, capture_output=True) result = subprocess.run(args, check=True, capture_output=True)
ret = result.stdout.decode('utf-8') ret = result.stdout.decode('utf-8')
err = result.stderr.decode('utf-8') err = result.stderr.decode('utf-8')
if err: if err:
raise RuntimeError(f'{ret}:\n {err}') raise RuntimeError(f'{ret}:\n {err}')
return ret img = Image.open(tmp_file)
height = img.size[1]
width = img.size[0]
draw = ImageDraw.Draw(img)
title_font = ImageFont.truetype(get_font()['path'], 13)
_, _, w, _ = draw.textbbox((0, 0), title, font=title_font)
draw.text(((width-w)/2, 6), title, fill="white", font=title_font)
comment_font = ImageFont.truetype(get_font()['path'], 11)
_, _, _, h = draw.textbbox((0, 0), comment, font=comment_font)
draw.text((1, height - (h + 1)), comment, fill="white", font=comment_font)
img.save(f'{in_file}.png')
os.remove(tmp_file)
def extract_detection(file: ParseFileName, detection: Detection): def extract_detection(file: ParseFileName, detection: Detection):