- 新增websocket客户端和服务端实现 - 添加图片压缩工具和快速压缩脚本 - 实现学生信息处理相关API - 添加MQTT客户端和消息处理功能 - 更新.gitignore忽略更多文件类型 - 添加数据库操作工具和示例 - 实现多个测试脚本和工具类
15 KiB
15 KiB
In [1]:
from requests import get,postIn [ ]:
from api import randomPic,getShiIn [7]:
token="Bearer f8bdd800-c1d5-4865-901c-0b52925462d6"
headers={
"Authorization":token,
}
ip = "http://192.168.0.209:9999"In [3]:
from faker import Faker
import random
from datetime import datetime, timedelta
import json
# 初始化Faker,设置为中文环境
fake = Faker('zh_CN')
def getFengjing():
data = get("https://api.btstu.cn/sjbz/api.php?lx=fengjing&format=json").json()["imgurl"]
return data
# ===================== 核心编码映射(对应Java枚举类) =====================
# 学段编码:1=小学,2=初中,3=高中
EDUCATION_STAGE_MAP = {
1: "小学",
2: "初中",
3: "高中"
}
# 年级编码:按学段分组,保证逻辑关联
GRADE_MAP = {
1: [101, 102, 103, 104, 105, 106], # 小学:一年级到六年级
2: [201, 202, 203], # 初中:初一到初三
3: [301, 302, 303] # 高中:高一到高三
}
# 年级编码对应中文(可选,用于注释/调试)
GRADE_NAME_MAP = {
101: "一年级", 102: "二年级", 103: "三年级", 104: "四年级", 105: "五年级", 106: "六年级",
201: "初一", 202: "初二", 203: "初三",
301: "高一", 302: "高二", 303: "高三"
}
# 学科编码:1=语文,2=数学,3=英语,4=物理,5=化学,6=生物,7=历史,8=地理,9=政治
SUBJECT_MAP = {
1: "语文",
2: "数学",
3: "英语",
4: "物理",
5: "化学",
6: "生物",
7: "历史",
8: "地理",
9: "政治"
}
# 状态编码:0=草稿,1=发布,2=下架(保持不变)
STATUS_LIST = [0, 1, 2]
def generate_video_info(id_num: int) -> dict:
"""
生成单条视频信息模拟数据(数字编码版)
:param id_num: 用于生成唯一ID的序号
:return: 视频信息字典
"""
# 随机生成时间(近1年内)
start_date = datetime.now() - timedelta(days=365)
create_time = fake.date_time_between(start_date=start_date, end_date="now")
update_time = create_time if random.random() < 0.3 else fake.date_time_between(start_date=create_time, end_date="now")
# 1. 随机选学段编码(1/2/3)
education_stage_code = random.choice(list(EDUCATION_STAGE_MAP.keys()))
# 2. 根据学段编码选对应年级编码(保证逻辑一致)
grade_code = random.choice(GRADE_MAP[education_stage_code])
# 3. 随机选学科编码(1-9)
subject_code = random.choice(list(SUBJECT_MAP.keys()))
# 生成贴合场景的视频标题(用编码对应中文,让标题更易读)
grade_name = GRADE_NAME_MAP[grade_code]
subject_name = SUBJECT_MAP[subject_code]
title_prefix = [f"{grade_name}{subject_name}", f"{subject_name}同步讲解", f"{subject_name}考点解析", f"{grade_name}{subject_name}易错点总结"]
title = f"{random.choice(title_prefix)}"
randomPicUrl = getFengjing()
return {
"title": title,
"coverUrl": randomPicUrl,
"videoUrl": randomPicUrl,
"categoryId": random.randint(1, 50), # 分类ID 1-50
"teacherId": random.randint(1000, 9999), # 教师ID 1000-9999
"subject": subject_code, # 学科编码(1-9)
"grade": grade_code, # 年级编码(101/102...303)
"educationStage": education_stage_code, # 学段编码(1/2/3)
"description": getShi()['content'], # 5句左右的简介
"duration": random.randint(300, 3600), # 时长5分钟到1小时(秒)
"viewCount": random.randint(0, 1000000), # 播放量0-100万
"likeCount": random.randint(0, 100000), # 点赞数0-10万
"commentCount": random.randint(0, 10000), # 评论数0-1万
"status": random.choice(STATUS_LIST),
"createTime": create_time.strftime("%Y-%m-%d %H:%M:%S"), # 适配LocalDateTime格式
"updateTime": update_time.strftime("%Y-%m-%d %H:%M:%S"),
"videoUploadUrl": f"https://storage.example.com/videos/{fake.uuid4()}.mp4",
}
def generate_video_data(count: int) -> list:
"""
生成指定数量的视频模拟数据(数字编码版)
:param count: 生成数据的条数
:return: 视频数据列表
"""
video_list = []
for i in range(1, count + 1):
video_list.append(generate_video_info(i))
return video_list
# if __name__ == "__main__":
# # 生成10条测试数据(可自行修改数量)
# video_data = generate_video_data(1)
# # 打印编码映射说明(方便对照)
# print("===== 编码映射说明 =====")
# print(f"学段编码:{EDUCATION_STAGE_MAP}")
# print(f"年级编码:{GRADE_NAME_MAP}")
# print(f"学科编码:{SUBJECT_MAP}")
# print("===== 生成的测试数据 =====")
# # 方式1:打印格式化后的JSON数据
# print(json.dumps(video_data, ensure_ascii=False, indent=4))
# print("\n数据已保存到 video_info_test_data_code.json 文件")In [ ]:
for i in range(10):
video_data = generate_video_data(1)
post(f"{ip}/video/videoInfo",headers=headers,json=video_data[0]).json()
In [ ]:
# post(f"{ip}/api/video",json=video_data[0])
# video_dataIn [8]:
get(f"{ip}/admin/team-org/tree",headers=headers).json()
Out [8]:
{'code': 0,
'msg': None,
'data': [{'id': '1',
'parentId': '0',
'weight': 1,
'name': '教研组',
'isLock': True,
'createTime': None,
'children': [{'id': '2',
'parentId': '1',
'weight': 1,
'name': '语文组',
'isLock': True,
'createTime': None}]},
{'id': '3',
'parentId': '0',
'weight': 1,
'name': '行政组',
'isLock': True,
'createTime': None}],
'ok': True}In [ ]:
get(f"{ip}/video/videoChapter/tree",params={
"subjectId":"15",
"deptId":0,
},headers=headers).json()
In [ ]:
get(f"{ip}/video/videoCourse/page",headers=headers,params={
"current":1,
"size":10,
}).json()
In [ ]:
post(f"{ip}/video/videoInfo",headers=headers,json={
"coverUrl": "/api/admin/sys-file/oss/file?fileName=d52e43ce433e44da91d248a5aecaf16e.png",
"description": "测试课程",
"gradeId": "102",
"stageId": "1",
"subjectId": "19",
"title": "ces",
"videoUploadUrl": "http://192.168.0.244:9000/s3demo/video/live/522e4c55fc804decafdd0a62e5a1bf74.mp4"
}).text
In [ ]:
In [7]:
post(f"{ip}/video/videoInfo/uploadImg",headers=headers,files={"file":open("1.png","rb")}).json()Out [7]:
{'code': 0,
'msg': None,
'data': 'http://192.168.0.244:9000/s3demo/video/couer/5ac9f3a8061a4eea938272ce0a34bb3b.png',
'ok': True}In [12]:
get("http://192.168.0.244:18081/api/common/channel/play?channelId=1",headers={"api-key":"eyJhbGciOiJSUzI1NiIsImtpZCI6IjNlNzk2NDZjNGRiYzQwODM4M2E5ZWVkMDlmMmI4NWFlIn0.eyJqdGkiOiIzRjFJQ2xhRzNscm9zVEdZTUlNanZRIiwiaWF0IjoxNzcyNjA1NzA5LCJuYmYiOjE3NzI2MDU3MDksInN1YiI6ImxvZ2luIiwiYXVkIjoiQXVkaWVuY2UiLCJ1c2VyTmFtZSI6ImFkbWluIiwiYXBpS2V5SWQiOjF9.YxFVDE6czLSqUZtLXnW7mWzkk0EG6lfHgJpykP_eZ_-COve8_tfLLRs_Gqip64EiGrAWTuw98TRToIzF2TKAqOHYD3XtaTlzcrCUWXHT-d70DYz9qniStrXimwIqeyuYKzgyweiGkkbmkn6y6SRrvGkQmGZWltHNLtp_Iy9DToBQr6adA8Jt23mGazZDueewJEofp54FeirB7Uorwb8XXFX-u9X33HbB3RIX5GS3AmOCchWOwhaBH4ZyeZDCJO7W1ziD_UPzzo4GG1GIc7sAnjGO0poGXs3-oCyBJ0gwsapJcSB6n-S8qW_JvIp7qk0GGo8KyBLE2ILRHX6BYULiww"}).textOut [12]:
'{"code":0,"msg":"成功","data":{"app":"rtp","stream":"34020000001320000002_34020000001320000002","ip":null,"flv":"http://192.168.0.244:85/rtp/34020000001320000002_34020000001320000002.live.flv?originTypeStr=rtp_push","https_flv":"https://192.168.0.244:443/rtp/34020000001320000002_34020000001320000002.live.flv?originTypeStr=rtp_push","ws_flv":"ws://192.168.0.244:85/rtp/34020000001320000002_34020000001320000002.live.flv?originTypeStr=rtp_push","wss_flv":"wss://192.168.0.244:443/rtp/34020000001320000002_34020000001320000002.live.flv?originTypeStr=rtp_push","fmp4":"http://192.168.0.244:85/rtp/34020000001320000002_34020000001320000002.live.mp4?originTypeStr=rtp_push","https_fmp4":"https://192.168.0.244:443/rtp/34020000001320000002_34020000001320000002.live.mp4?originTypeStr=rtp_push","ws_fmp4":"ws://192.168.0.244:85/rtp/34020000001320000002_34020000001320000002.live.mp4?originTypeStr=rtp_push","wss_fmp4":"wss://192.168.0.244:443/rtp/34020000001320000002_34020000001320000002.live.mp4?originTypeStr=rtp_push","hls":"http://192.168.0.244:85/rtp/34020000001320000002_34020000001320000002/hls.m3u8?originTypeStr=rtp_push","https_hls":"https://192.168.0.244:443/rtp/34020000001320000002_34020000001320000002/hls.m3u8?originTypeStr=rtp_push","ws_hls":"ws://192.168.0.244:85/rtp/34020000001320000002_34020000001320000002/hls.m3u8?originTypeStr=rtp_push","wss_hls":"wss://192.168.0.244:443/rtp/34020000001320000002_34020000001320000002/hls.m3u8?originTypeStr=rtp_push","ts":"http://192.168.0.244:85/rtp/34020000001320000002_34020000001320000002.live.ts?originTypeStr=rtp_push","https_ts":"https://192.168.0.244:443/rtp/34020000001320000002_34020000001320000002.live.ts?originTypeStr=rtp_push","ws_ts":"ws://192.168.0.244:85/rtp/34020000001320000002_34020000001320000002.live.ts?originTypeStr=rtp_push","wss_ts":null,"rtmp":"rtmp://192.168.0.244:1935/rtp/34020000001320000002_34020000001320000002?originTypeStr=rtp_push","rtmps":null,"rtsp":"rtsp://192.168.0.244:554/rtp/34020000001320000002_34020000001320000002?originTypeStr=rtp_push","rtsps":null,"rtc":"http://192.168.0.244:85/index/api/webrtc?app=rtp&stream=34020000001320000002_34020000001320000002&type=play&originTypeStr=rtp_push","rtcs":"https://192.168.0.244:443/index/api/webrtc?app=rtp&stream=34020000001320000002_34020000001320000002&type=play&originTypeStr=rtp_push","mediaServerId":"zlmediakit-local","mediaInfo":{"app":"rtp","stream":"34020000001320000002_34020000001320000002","mediaServer":{"id":"zlmediakit-local","ip":"192.168.0.244","hookIp":"127.0.0.1","sdpIp":"192.168.0.244","streamIp":"192.168.0.244","httpPort":85,"httpSSlPort":443,"rtmpPort":1935,"flvPort":0,"flvSSLPort":443,"mp4Port":0,"wsFlvPort":0,"wsFlvSSLPort":443,"rtmpSSlPort":0,"rtpProxyPort":10000,"jttProxyPort":0,"rtspPort":554,"rtspSSLPort":0,"autoConfig":false,"secret":"TWSYFgYJOQWB4ftgeYut8DW4wbs7pQnj","hookAliveInterval":10.0,"rtpEnable":true,"status":true,"rtpPortRange":"40000,45000","sendRtpPortRange":"50000,55000","recordAssistPort":0,"createTime":"2026-01-04 17:59:07","updateTime":"2026-03-04 14:45:29","lastKeepaliveTime":null,"defaultServer":true,"recordDay":7,"recordPath":"","type":"zlm","transcodeSuffix":null,"serverId":"000000"},"schema":"rtsp","readerCount":0,"videoCodec":"H264","width":1920,"height":1080,"fps":null,"loss":null,"audioCodec":null,"audioChannels":null,"audioSampleRate":null,"duration":null,"online":true,"originType":3,"originTypeStr":"rtp_push","originUrl":"rtp://__defaultVhost__/rtp/34020000001320000002_34020000001320000002","aliveSecond":0,"bytesSpeed":0,"callId":"e6e72138756dfd276b888202879d70b1@192.168.0.244","paramMap":{},"serverId":"000000"},"startTime":null,"endTime":null,"duration":null,"downLoadFilePath":null,"transcodeStream":null,"progress":0.0,"key":null}}'In [ ]: