Skip to content

Commit

Permalink
Merge pull request #112 from katagomo/main
Browse files Browse the repository at this point in the history
增加致谢页面及弹幕效果等
  • Loading branch information
HisAtri authored Jan 20, 2025
2 parents bd31668 + dd26a60 commit 2db293d
Show file tree
Hide file tree
Showing 7 changed files with 345 additions and 41 deletions.
101 changes: 101 additions & 0 deletions api/lyrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@
from . import *

import os
import re

from flask import request, abort, jsonify
from urllib.parse import unquote_plus
from openai import OpenAI

from mod import lrc
from mod import searchx
from mod import tools
from mod import tag
from mod.auth import require_auth_decorator
from mod.args import args


def read_file_with_encoding(file_path: str, encodings: list[str]):
Expand Down Expand Up @@ -95,3 +98,101 @@ def lrc_json():
_response = jsonify(response)
_response.headers['Content-Type'] = 'application/json; charset=utf-8'
return jsonify(response)


@app.route('/translate', methods=['POST'])
@v1_bp.route('/translate', methods=['POST'])
@require_auth_decorator(permission='r')
def lyrics_translate():
data = request.get_json()
lyrics = data.get('lyrics')
BASE_URL = args('ai', 'base_url')
API_KEY = data.get('token') or args('ai', 'api_key')
MODEL = args('ai', 'model')

if not BASE_URL or not API_KEY or not MODEL:
return jsonify({"error": "Missing required parameters"}), 400
PROMPT = """You are a lyric translator, tasked with employing exquisite prose to render lines that evoke deep emotions and possess a profound resonance.目标语言是简体中文。
Attention
-保持原文的LRC文本格式;禁止翻译专辑/作者/注释等任何非歌词内容
-不要直接翻译,基于整体进行意译
-结合上下文内容,充分理解歌词中部分词语的隐喻
-注意音韵美
-歌词可能存在重复,请照常翻译,禁止省略。
-**禁止对中文歌词做任何翻译和修改**
-和制汉字不是中文
Use emotional expressions instead of literal translations
Example:
Life's passing by
- positive:时光匆匆流逝
- negative:生活在流逝
Contact Context
Example
And after the party's done
I keep on going missing the moments
- positive:派对过后
我只顾向前,错过了那些美好时刻
- negative:派对结束后
我依然在错过那些瞬间
Example
Caught in a landslide No escape from reality
- positive:受困在塌方之中,无法逃离**现实**的囚笼
- negative:被泥石流吞没,无法逃离**真实**
Translation may be interspersed as necessary.
Example:
I'm a Ferrari
Pulled off on Mulholland Drive
- positive:我就像在穆兰大道上
疾速飞奔的法拉利
- negative:我是一辆法拉利
驶离穆赫兰德大道
Infer the meaning of the statement through context.
Example(Bohemian Rhapsody):
I'm just a poor boy, (oooh, poor boy)
I need no sympathy
**Because I'm easy come, easy go**
**Little high, little low**
- positive: 因为我总是被人呼来唤去,时而高亢,时而低迷
- negative: 因为我来去自如,时高时低
理解文化背景下的隐喻
Example
- "I'm gonna tear this city down without you \ I'm goin' Bonnie and Clyde without you"
- positive:在没有你的城市里纵情徘徊,做孤独的无畏侠客
- negative:我要在没有你的情况下摧毁这座城市,我要成为没有你的"邦妮与克莱德"
英语国家文化背景:Bonnie 和 Clyde 是美国历史上著名的犯罪情侣,他们在大萧条时期进行了一系列的抢劫和逃亡,象征着反叛和不羁的爱情。
然而,由于翻译的目标语言是简体中文,邦妮与克莱德的典故可能并不容易被理解,因此,更恰当的方式是直接使用比喻义进行翻译,即“做一个孤独且无畏的侠客”
你需要遵守以下思维链:
- Firstly, Infer the country of the author of this song based on the language. Such as [language: en], [language: th], [language: fr], etc.
- If the language is Chinese, please output [language: zh], ignore all the steps after this, then use [FINAL] tags to enclose the original lyrics and end the translation.
- Next, translate the complete lyrics, encapsulating your LRC format within the [PRE]...[/PRE] tags.
- Then, analyze the emotional undertones of the lyrics and provide a brief overview of their central theme.
- And, assess the shortcomings of the initial translation based on the aforementioned insights.
- Before the final translation, you must ensure that you DID NOT translate any lyrics that are in Chinese. If the Chinese part is translated, please restore it.
- Finally, drawing from this analysis, deliver a refined and high-quality translation of the lyrics, one that remains faithful to the original while evoking deep emotions and possessing poignant resonance, using the [FINAL]...[/FINAL] tags to enclose the ultimate LRC format translation.
**禁止对中文歌词做任何翻译**"""
client = OpenAI(api_key=API_KEY, base_url=BASE_URL)
response = client.chat.completions.create(
model=MODEL,
messages=[{"role": "system", "content": PROMPT}, {"role": "user", "content": lyrics}]
)
raw_output = response.choices[0].message.content

lang_match = re.search(r'\[language:\s*(\w+)\]', raw_output)
lang_tag = lang_match.group(0) if lang_match else "[language: unknown]"

# 提取最终翻译
final_lyric = re.search(r'\[FINAL\](.*?)\[/FINAL\]', raw_output, re.DOTALL)
if final_lyric:
extracted = f"[Model Name: {MODEL}]\n" + lang_tag + "\n" + final_lyric.group(1).strip()
return jsonify({"data": extracted, "status": "success", "raw_output": raw_output})
else:
return jsonify({"raw_output": raw_output, "status": "failed"}), 500
5 changes: 5 additions & 0 deletions api/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ def redirect_to_welcome():
return redirect('/src')


@app.route('/acknowledgments')
def acknowledgments():
return send_from_directory(src_path, 'acknowledgments.html')


@app.route('/favicon.ico')
def favicon():
"""
Expand Down
3 changes: 2 additions & 1 deletion app.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ def run_server(debug=False):
app.register_blueprint(v1_bp)
# 启动
run_server(args.debug)

exit()

50 changes: 40 additions & 10 deletions mod/args/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
parser.add_argument("--debug", action="store_true", help="Enable debug mode")
parser.add_argument('--ip', type=str, default='*', help='服务器监听IP,默认*')
parser.add_argument('--token', type=str, default='', help='用于翻译歌词的API Token')
parser.add_argument('--ai-type', type=str, default='openai', help='AI类型,默认openai')
parser.add_argument('--ai-model', type=str, default='gpt-4o-mini', help='AI模型,默认gpt-4o-mini')
parser.add_argument('--ai-base-url', type=str, default='https://api.openai.com/v1', help='AI基础URL,默认https://api.openai.com/v1')
parser.add_argument('--ai-api-key', type=str, default='', help='AI API Key,默认空')
kw_args, unknown_args = parser.parse_known_args()
arg_auths: dict = {kw_args.auth: "rwd"} if kw_args.auth else None

Expand Down Expand Up @@ -116,8 +120,14 @@ def permission(self, key) -> str:
"ip": "*",
"port": 28883
},
"auth": {}
}
"auth": {},
"ai": {
"type": "openai",
"model": "gpt-4o-mini",
"base_url": "https://api.openai.com/v1",
"api_key": ""
}
}

class Args():
def __init__(self, data=None, default=None):
Expand Down Expand Up @@ -171,22 +181,35 @@ def __load_yaml() -> dict|None:
def __load_env(self):
auth = os.environ.get('API_AUTH', None)
port = os.environ.get('API_PORT', None)
token = os.environ.get('API_TOKEN', None)
ai_type = os.environ.get('API_AI_TYPE', None)
ai_model = os.environ.get('API_AI_MODEL', None)
ai_base_url = os.environ.get('API_AI_BASE', None)
ai_api_key = os.environ.get('API_AI_KEY', None)
if auth:
self.__data["auth"] = {auth: "all"}
if port:
# 确保 server 是一个字典
if not isinstance(self.__data.get("server"), dict):
self.__data["server"] = {"ip": "*"}
self.__data["server"]["port"] = port
if token:
self.__data["token"] = token
if not isinstance(self.__data.get("ai"), dict):
self.__data["ai"] = {}
if ai_type:
self.__data["ai"]["type"] = ai_type
if ai_model:
self.__data["ai"]["model"] = ai_model
if ai_base_url:
self.__data["ai"]["base_url"] = ai_base_url
if ai_api_key:
self.__data["ai"]["api_key"] = ai_api_key

def __load_arg(self):
auth = kw_args.auth
port = kw_args.port
ip = kw_args.ip
token = kw_args.token
ai_type = kw_args.ai_type
ai_model = kw_args.ai_model
ai_base_url = kw_args.ai_base_url
ai_api_key = kw_args.ai_api_key
logger.info(f"Auth: {auth}; Port: {port}; IP: {ip}")
if auth:
self.__data["auth"] = {auth: "all"}
Expand All @@ -198,9 +221,16 @@ def __load_arg(self):
if not isinstance(self.__data.get("server"), dict):
self.__data["server"] = {"ip": "*"}
self.__data["server"]["ip"] = ip
if token:
self.__data["token"] = token
#logger.info(f"Final config data: {self.__data}")
if not isinstance(self.__data.get("ai"), dict):
self.__data["ai"] = {}
if ai_type:
self.__data["ai"]["type"] = ai_type
if ai_model:
self.__data["ai"]["model"] = ai_model
if ai_base_url:
self.__data["ai"]["base_url"] = ai_base_url
if ai_api_key:
self.__data["ai"]["api_key"] = ai_api_key

def __call__(self, *args):
data = self.__data
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ Pillow~=10.1.0
pyaes~=1.6.1
Werkzeug~=3.0.1
mygo~=1.0.0
PyYAML~=6.0.2
PyYAML~=6.0.2
openai~=1.59.8
Loading

0 comments on commit 2db293d

Please sign in to comment.