import requests
import gradio as gr
from tqdm import tqdm
from pydub import AudioSegment
from datetime import datetime, timedelta
from utils import timestamp, extract_fst_int, rm_dir, mk_dir, TMP_DIR, EN_US
ZH2EN = {
"输入声音页 URL": "Enter the sound page URL",
"按格式输入声音发布日期": "Enter sound publication date in format",
"下载 MP3": "Download MP3",
"荔枝FM音频解析下载": "Lizhi FM Audio Direct URL Parsing Tool",
"推荐辅助工具 日期计算器": "The datecalc is highly recommanded.",
"状态栏": "Status",
}
def _L(zh_txt: str):
return ZH2EN[zh_txt] if EN_US else zh_txt
def get_prev_day(date_str):
date_format = "%Y/%m/%d"
date_obj = datetime.strptime(date_str, date_format)
previous_day = date_obj - timedelta(days=1)
return previous_day.strftime(date_format)
def rm_end_seconds(input_file: str, output_file="", seconds=3.1):
print("移除音频水印...")
if not output_file:
output_file = input_file
audio = AudioSegment.from_file(input_file)
remove_ms = seconds * 1000
new_audio = audio[:-remove_ms]
new_audio.export(output_file, format="mp3")
return output_file
def download_mp3(url: str, local_file: str):
response = requests.get(url, stream=True)
retcode = response.status_code
if retcode == 200:
total_size = int(response.headers.get("Content-Length", 0)) + 1
time_stamp = timestamp()
progress_bar = tqdm(
total=total_size,
unit="B",
unit_scale=True,
desc=f"[{time_stamp}] {local_file}",
)
with open(local_file, "wb") as f:
for chunk in response.iter_content(chunk_size=8192):
if chunk: # 确保 chunk 不为空
f.write(chunk) # 更新进度条
progress_bar.update(len(chunk))
return rm_end_seconds(local_file)
elif retcode == 404:
bad_date = "/".join(url.split("/audio/")[-1].split("/")[:-1])
fixed_date = get_prev_day(bad_date)
fixed_url = url.replace(bad_date, fixed_date)
return download_mp3(fixed_url, local_file)
else:
raise ConnectionError(f"错误: {retcode}, {response.text}")
# outer func requires try except
def infer(page_url: str, date: str, cache=f"{TMP_DIR}/lizhi"):
status = "Success"
outpath = None
try:
rm_dir(cache)
if not page_url:
raise ValueError("声音链接或ID为空")
if ("http" in page_url and ".lizhi" in page_url) or page_url.isdigit():
sound_id = extract_fst_int(page_url.split("/")[-1])
else:
raise ValueError("无效的声音链接或ID")
voice_time = date.strip().replace("-", "/")
mp3_url = f"http://cdn5.lizhi.fm/audio/{voice_time}/{sound_id}_hd.mp3"
mk_dir(cache)
outpath = download_mp3(mp3_url, f"{cache}/{sound_id}.mp3")
except Exception as e:
status = f"{e}"
return status, outpath
def lizhifm_parser():
return gr.Interface(
fn=infer,
inputs=[
gr.Textbox(
label=_L("输入声音页 URL"),
placeholder="https://www.lizhi.fm/*/*",
),
gr.Textbox(label=_L("按格式输入声音发布日期"), placeholder="YYYY-MM-DD"),
],
outputs=[
gr.Textbox(label=_L("状态栏"), show_copy_button=True),
gr.Audio(label=_L("下载 MP3"), show_download_button=True),
],
flagging_mode="never",
title=_L("荔枝FM音频解析下载"),
description=_L(
"推荐辅助工具 日期计算器"
),
examples=[
["https://www.lizhi.fm/voice/3136401036767886342", "2025-04-05"],
["https://www.lizhifm.com/voice/3136401036767886342", "2025-04-05"],
["https://m.lizhi.fm/voice/3136401036767886342", "2025-04-05"],
["https://m.lizhifm.com/voice/3136401036767886342", "2025-04-05"],
["3136401036767886342", "2025-04-05"],
],
)