Skip to content

Commit

Permalink
增加下载蓝牙话筒音频信号的功能;完善webui并发布
Browse files Browse the repository at this point in the history
  • Loading branch information
AuYang261 committed May 29, 2024
1 parent 55fc1df commit b6ff142
Show file tree
Hide file tree
Showing 14 changed files with 220 additions and 182 deletions.
35 changes: 25 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,17 @@

![image-20231018204208066](md/README/image-20231018204208066.png)

### 直观的交互方式
### 网页

双击运行`webui_interface.exe`文件打开网页服务器,按住`ctrl`点击命令行中的地址,或直接在浏览器中输入该地址打开。

![image-20240529174653840](md/README/image-20240529174653840.png)

而后在打开的网页中新建任务即可。

![image-20240529174739174](md/README/image-20240529174739174.png)

### 命令行GUI交互

打开命令行(在`release_downloader.zip`解压的文件夹地址栏中搜索cmd),在命令行中输入`gui.exe`文件运行。直接双击运行可能会有字符对不齐的问题,导致难以识别文字。最好将命令行窗口最大化以免字符显示不全。

Expand All @@ -28,25 +38,29 @@

按键盘上下键移动光标,按空格选择/取消选择,至少需要选择一个视频。选择完成后按回车确认。若想退出按q键即可。

确认后,选择要下载的信号,可选摄像头(即教室后的摄像头录像)或电脑屏幕(即教室电脑的屏幕信号),同样只要需要选择一个信号。选择完成后按回车确认,开始下载。按`ctrl+c`停止
确认后,选择要下载的信号,可选摄像头(即教室后的摄像头录像)或电脑屏幕(即教室电脑的屏幕信号),同样至少需要选择一个信号,选择完成后按回车确认

![image-20240413002242979](md/README/image-20240413002242979.png)

下载完成的文件在`output/`目录下以`课程名-video/screen`格式命名的文件夹中。

![image-20230926124922726](md/README/image-20230926124922726.png)

### 原始交互方式
而后选择是否下载教室蓝牙话筒信号,若老师未使用蓝牙话筒则该信号没有声音。选择完成后按回车确认。开始下载。按`ctrl+c`停止。

![image-20240529171709402](md/README/image-20240529171709402.png)

双击运行`main.exe`文件,并输入你想下载的课程编号(40524)。输出课程视频列表:
![image-20240529171253980](md/README/image-20240529171253980.png)

![image-20240413002857964](md/README/image-20240413002857965.png)
下载完成的文件在`output/`目录下以`课程名-video/screen`格式命名的文件夹中。若下载了蓝牙音频则保存在和视频同目录同名的`.aac`文件中。

输入想下载的视频编号,用英文逗号(,)分隔,回车。接着输入数字选择下载摄像头信号还是下载屏幕信号,默认为摄像头信号。回车即开始下载:
![image-20230926124922726](md/README/image-20230926124922726.png)

### 原始交互方式

![image-20240413002857964](md/README/image-20240413002857964.png)
若使用上述GUI显示有问题,可直接使用原始交互方式。双击运行`main.exe`文件,并输入你想下载的课程编号(40524)。输出课程视频列表:

![image-20240529171540279](md/README/image-20240529171540279.png)

输入想下载的视频编号,用英文逗号(,)分隔,回车。接着输入数字选择下载摄像头信号还是下载屏幕信号,默认为摄像头信号。而后选择是否下载蓝牙话筒信号。回车即开始下载。

## 自动生成字幕

Expand Down Expand Up @@ -110,6 +124,7 @@ pip install pyinstaller
# 打包
pyinstaller -F main.py
pyinstaller -F gui.py
pyinstakker -F webui_interface.py --add-data webui:webui
pyinstaller -F gen_caption.py
```
打包`gen_caption.py`时可能会失败,提示递归过深:
Expand All @@ -132,4 +147,4 @@ pyinstaller --clean .\gen_caption.spec

![image-20240409095831766](md/README/image-20240409095831766.png)

解决方法参考[这个](https://blog.csdn.net/qq_42324086/article/details/118280341),将项目`hooks`目录下的`hook-whisper.py``hook-zhconv.py`文件复制到pyinstaller的hook目录下(通常在`python根目录\Lib\site-packages\PyInstaller\hooks`
解决方法参考[这个](https://blog.csdn.net/qq_42324086/article/details/118280341),将项目`hooks`目录下的`hook-whisper.py``hook-zhconv.py`文件复制到pyinstaller的hook目录下(通常在`python根目录\Lib\site-packages\PyInstaller\hooks`)。
44 changes: 24 additions & 20 deletions gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
professor = ""
selected_videos = []
selected_signal = []
download_audio = []

align = 0

Expand All @@ -30,10 +31,11 @@ def draw_line(stdscr, text, row):
stdscr.addnstr(row, align, new_text, get_cmd_window_size(stdscr)[1])


def draw_menu(stdscr, options, checked, title, current_row):
def draw_menu(stdscr, options, checked, title, subtitle, current_row):
stdscr.clear()
height, width = get_cmd_window_size(stdscr)
draw_line(stdscr, title, 0)
draw_line(stdscr, subtitle, 1)
msg = []
for idx, option in enumerate(options):
checkmark = "[X]" if checked[idx] else "[ ]"
Expand All @@ -50,7 +52,7 @@ def draw_multi_select(stdscr, messages: list, center_row):

# 计算消息的开始位置以使其居中
total_messages = len(messages)
visible_messages = min(height - 4, total_messages) # 屏幕可以显示的最大消息数
visible_messages = min(height - 5, total_messages) # 屏幕可以显示的最大消息数
start_row = max(2, (height // 2) - (visible_messages // 2))

# 确定要显示的消息的范围
Expand All @@ -68,12 +70,12 @@ def draw_multi_select(stdscr, messages: list, center_row):
)


def multi_select(stdscr, options, title):
def multi_select(stdscr, options, title, subtitle=""):
# curses.curs_set(0) # 隐藏光标
checked = [False] * len(options)
current_row = 0
while True:
draw_menu(stdscr, options, checked, title, current_row)
draw_menu(stdscr, options, checked, title, subtitle, current_row)
key = stdscr.getch()

if key == curses.KEY_DOWN:
Expand All @@ -92,7 +94,7 @@ def multi_select(stdscr, options, title):


def config(stdscr):
global videoList, courseName, professor, selected_videos, selected_signal
global videoList, courseName, professor, selected_videos, selected_signal, download_audio

height, width = get_cmd_window_size(stdscr)

Expand Down Expand Up @@ -137,11 +139,6 @@ def config(stdscr):
else:
break

# 清除屏幕并显示输入的内容
prompt = ["已选择以下视频:\n"]
for index in selected_videos:
prompt.append(f"{videoList[index]['title']}\n")

selected_signal = []

while True:
Expand All @@ -155,6 +152,13 @@ def config(stdscr):
else:
break

download_audio = multi_select(
stdscr,
["下载蓝牙音频"],
"选择是否下载教室蓝牙话筒的音频(如果有的话):",
"若教师未使用教室蓝牙话筒则该音频无声音",
)

stdscr.clear()


Expand All @@ -174,17 +178,17 @@ def main():
print(name)
try:
if 1 in selected_signal:
m3u8dl.M3u8Download(
c["videos"][0]["vga"],
"output/" + courseName + "-screen",
name,
)
path = f"output/{courseName}-screen"
m3u8dl.M3u8Download(c["videos"][0]["vga"], path, name)
if 0 in selected_signal:
m3u8dl.M3u8Download(
c["videos"][0]["main"],
"output/" + courseName + "-video",
name,
)
path = f"output/{courseName}-video"
m3u8dl.M3u8Download(c["videos"][0]["main"], path, name)
if download_audio:
audio_url = utils.get_audio_url(c["video_ids"][0])
if audio_url:
print("Downloading audio...")
utils.download_audio(audio_url, path, name)
print("Download audio successfully.")
except Exception as e:
print(e)
fail.append(name)
Expand Down
46 changes: 16 additions & 30 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,25 @@
}


# courseID = 31425
def main():
if len(sys.argv) == 1:
courseID = input("输 入 课 程 ID: ")
else:
courseID = sys.argv[1]

videoList, courseName, professor = utils.get_course_info(courseID=courseID)
# course = requests.get(
# f"https://cbiz.yanhekt.cn/v1/course?id={courseID}&with_professor_badges=true",
# headers=headers,
# )
# req = requests.get(
# f"https://cbiz.yanhekt.cn/v2/course/session/list?course_id={courseID}",
# headers=headers,
# )
# if course.json()["code"] != "0" and course.json()["code"] != 0:
# print(course.json()["code"])
# print(course.json()["message"])
# raise Exception(
# "Please Check your course ID, note that it should be started with yanhekt.cn/course/***, not yanhekt.cn/session/***"
# )
# print(course.json()["data"]["name_zh"])
# videoList = req.json()["data"]
# print(json.dumps(videoList, indent=2))

for i, c in enumerate(videoList):
print(f"[{i}]: ", c["title"])

index = eval(
"[" + input("选择课程编号(用 英 文 逗 号 ','分 隔, 例 如: 0,2,4): ") + "]"
"[" + input("选 择 课 程 编 号 (用 英 文 逗 号 ','分 隔, 例 如: 0,2,4): ") + "]"
)
vga = input(
"选 择 下 载 摄 像 头 (1) 还 是 电 脑 屏 幕(2)?(输 入 1 或 2, 默 认 摄 像 头):"
"选 择 下 载 摄 像 头 (1) 还 是 电 脑 屏 幕 (2)?(输 入 1 或 2, 默 认 摄 像 头):"
)
audio = input(
"是 否 下 载 教 室 蓝 牙 话 筒 的 音 频 ?若 教 师 未 使 用 蓝 牙 话 筒 则 该 音 频 无 声 音 (输 入 1不 下 载, 默 认 下 载):"
)
if not os.path.exists("output/"):
os.mkdir("output/")
Expand All @@ -57,19 +43,19 @@ def main():
name = courseName + "-" + professor + "-" + c["title"]
print(name)
if vga == "2":
path = f"output/{courseName}-screen"
print("Downloading screen...")
m3u8dl.M3u8Download(
c["videos"][0]["vga"],
"output/" + courseName + "-screen",
name,
)
m3u8dl.M3u8Download(c["videos"][0]["vga"], path, name)
else:
path = f"output/{courseName}-video"
print("Downloading video...")
m3u8dl.M3u8Download(
c["videos"][0]["main"],
"output/" + courseName + "-video",
name,
)
m3u8dl.M3u8Download(c["videos"][0]["main"], path, name)
if audio == "" and c["video_ids"]:
audio_url = utils.get_audio_url(c["video_ids"][0])
if audio_url:
print("Downloading audio...")
utils.download_audio(audio_url, path, name)
print("Download audio successfully.")


if __name__ == "__main__":
Expand Down
Binary file removed md/README/image-20240413002857964.png
Binary file not shown.
Binary file removed md/README/image-20240413002857965.png
Binary file not shown.
Binary file added md/README/image-20240529171253980.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added md/README/image-20240529171540279.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added md/README/image-20240529171709402.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added md/README/image-20240529174653840.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added md/README/image-20240529174739174.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 22 additions & 5 deletions utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
import m3u8dl


headers = {
"Origin": "https://www.yanhekt.cn",
"Authorization": "Bearer 6277e60fa9e86fdcdd2411ce86a54f47",
"xdomain-client": "web_user",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.26",
}


def get_course_info(courseID):
courseID = courseID.strip()
headers = {
"Origin": "https://www.yanhekt.cn",
"xdomain-client": "web_user",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.26",
}

course = requests.get(
f"https://cbiz.yanhekt.cn/v1/course?id={courseID}&with_professor_badges=true",
Expand Down Expand Up @@ -42,3 +45,17 @@ def get_course_info(courseID):
else "未知教师"
),
)


def get_audio_url(video_id):
res = requests.get(
f"https://cbiz.yanhekt.cn/v1/video?id={video_id}",
headers=headers,
)
return res.json()["data"].get("audio", "")


def download_audio(url, path, name):
res = requests.get(url, headers=headers)
with open(f"{path}/{name}.aac", "wb") as f:
f.write(res.content)
Loading

0 comments on commit b6ff142

Please sign in to comment.