Commit a65bde03 by xiaoqi

Update .gitignore and untrack ignored files

parents
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# Virtual environment files
.venv/
venv/
env/
.eggs/
pip-wheel-metadata
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyCharm files and directories
.idea/
*.iml
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# dotenv file
.env
# Logs and databases
logs/
*.log
*.sql
*.sqlite3
# Local configuration files
local_settings.py
# Testing and coverage
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
# Translations
*.mo
*.pot
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
\ No newline at end of file
import os.path
import convert_webp_2_mp4
def rename_webp_file(webp_file_dir):
# 检查输入路径是否为目录
if os.path.isdir(webp_file_dir):
# 遍历目录及其子目录中的所有文件
for dirpath, _, filenames in os.walk(webp_file_dir):
for filename in filenames:
# 获取文件完整路径
full_path = os.path.join(dirpath, filename)
# 检查文件是否是 WebP 动画文件
if convert_webp_2_mp4.is_webp_animator(full_path):
# 获取文件的 FPS 值
fps = int(convert_webp_2_mp4.get_fps(full_path))
# 如果成功获取到 FPS 值
if fps is not None:
# 分离文件名和扩展名
base_name, ext = os.path.splitext(filename)
# 构造新的文件名
new_filename = f"{base_name}_fps_{fps}{ext}"
# 构造新的完整路径
new_full_path = os.path.join(dirpath, new_filename)
# 重命名文件
os.rename(full_path, new_full_path)
print(f"Renamed: {full_path} -> {new_full_path}")
else:
print(f"Failed to get FPS for file: {full_path}")
else:
print(f"The provided path is not a directory: {webp_file_dir}")
if __name__ == '__main__':
inputDirOrFile = input("请输入文件或目录的路径:")
inputDirOrFile = inputDirOrFile.replace("\"", "")
rename_webp_file(inputDirOrFile)
from dataclasses import dataclass, field
from typing import List, Optional
# 假设你已经有了json_data这个变量,它包含了你的JSON字符串
import json
@dataclass
class Gift:
darkMd5: str
darkRes: str
gid: int
md5: str
mp4Res: str
resource: str
weight: int
zipMd5: Optional[str] = ""
zipRes: Optional[str] = ""
@dataclass
class Response:
msg: str
code: int
data: List[Gift]
md5: str
def json_to_entity(json_str: str) -> Response:
# 将JSON字符串解析成字典
parsed_dict = json.loads(json_str)
# 提取"data"部分并转换为Gift实例列表
gifts = [Gift(**gift_data) for gift_data in parsed_dict['data']]
# 创建Response实例
response = Response(
msg=parsed_dict['msg'],
code=parsed_dict['code'],
data=gifts,
md5=parsed_dict['md5']
)
return response
import requests
import json
import os
from urllib.parse import unquote
from pathlib import Path
from urllib.parse import urlparse
import concurrent.futures
from gift_parser import json_to_entity
is_release_api = True
test_host = "https://ceshi.yabolive.tv/apishare"
release_host = "https://ceshi.yabolive.tv/apishare"
cdn_host = "https://zhibocdn.yabolive.net/comm"
def firefly_login(phone, password):
url = f"{get_host()}/user/login.html?cancel=0&prchannel=&localecode=zh-Hans-CN&countrycode=86&advertisingId=ea55a34e-9152-4ec8-b2b5-74cff51b4100&cert=RQsxRXO3pnOHpQswfQpHP9-Kfne5RuRWp7-xfhOTRuel&imsi=&pkg=android.happylive&appname=com.happy.live&driverid=4d5872cb5a783a22760dd6c7f9b90cad6&bootloader=S906U1UEU7EXK6&storeApp=1&model=SM-S906U1&net=wifi&lang=0&brand=samsung&localecountry=CN&os=android&larea=2&appversion=7700&manufactruer=samsung&phone={phone
}&imei=&osversion=14&pwd={password}&device=g0q&cid=fireflygw&debug=sendbox"
response = requests.get(url, )
print(f"Response Code:{response.status_code}")
print(f"Response Text:{response.text}")
if response.status_code == 200:
code = response.json()["code"]
msg = unquote(response.json()["msg"])
print(f"msg:{msg}")
if code == 1: # 登录成功,
save_token(phone, response.text)
uid = response.json()["uid"]
token = response.json()["token"]
return uid, token
return None, None
def read_token_uid(phone, password):
path = f"{phone}"
db = Path(path)
if db.exists():
# 文件存在,尝试读取token和uid
with open(path, 'r', encoding='utf-8') as file:
try:
data = json.load(file)
uid = data.get('uid')
token = data.get('token')
if uid and token:
print("Token and UID loaded from local file.")
return uid, token
except json.JSONDecodeError:
print("Failed to decode JSON from local file.")
# 如果没有找到有效的本地文件,或者文件中的数据无效,则登录并获取新token和uid
print("No valid local token/UID found, logging in...")
uid, token = firefly_login(phone, password)
return uid, token
def save_token(phone, json):
path = f"{phone}"
db = Path(path)
if db.exists():
db.unlink(missing_ok=True)
with open(path, 'w', encoding='utf-8') as file:
file.write(json)
def get_host():
if is_release_api:
return release_host
else:
return test_host
def request_url(api, phone, password):
url = get_host() + api + base_param(phone, password)
response = requests.get(url, )
print(f"Response Code:{response.status_code}")
# print(f"Response Text:{response.text}")
return response.text
def base_param(phone, password):
uid, token = read_token_uid(phone, password)
return f"?cancel=0&prchannel=&localecode=zh-Hans-CN&countrycode=86&advertisingId=ea55a34e-9152-4ec8-b2b5-74cff51b4100&cert=RQsxRXO3pnOHpQswfQpHP9-Kfne5RuRWp7-xfhOTRuel&imsi=&pkg=android.happylive&appname=com.happy.live&driverid=4d5872cb5a783a22760dd6c7f9b90cad6&bootloader=S906U1UEU7EXK6&storeApp=1&model=SM-S906U1&net=wifi&lang=0&brand=samsung&localecountry=CN&os=android&larea=2&appversion=7700&manufactruer=samsung&uid={uid
}&imei=&osversion=14&token={token}&device=g0q&cid=fireflygw&debug=sendbox"
def load_live_gift_list(phone, password):
live_gift = request_url(api="/setting/updatelivegift.html", phone=phone, password=password)
jsonobject = json.loads(live_gift)
live_gift_list = jsonobject["data"]
shechigifts = [shechigift for shechigift in live_gift_list if shechigift.get("category") == 1001]
# print(shechigifts)
json_text = request_url(api="/setting/updatespecialresource", phone=phone, password=password)
result = json_to_entity(json_text)
matching_elements = [shiechigift for shiechigift in shechigifts for resource in result.data if shiechigift.get("darkMd5") == resource.darkMd5]
# matching_elements = [resource for resource in result.data for shechigift in shechigifts if resource.darkMd5 == shechigift.get("darkMd5")]
print(matching_elements)
# 创建一个线程池,大小为5
# with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
# # 对于result.data中的每一个gift,提交一个download_file任务到线程池
# futures = [executor.submit(download_file, cdn_host + gift.darkRes, "shechi_webp_dir", f"{gift.gid}-{gift.darkMd5}.webp") for
# gift in matching_elements]
#
# # 等待所有任务完成
# concurrent.futures.wait(futures)
#
# print("所有文件下载完成")
def load_gift_resource(phone, password):
json_text = request_url(api="/setting/updatespecialresource", phone=phone, password=password)
result = json_to_entity(json_text)
# 创建一个线程池,大小为5
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
# 对于result.data中的每一个gift,提交一个download_file任务到线程池
futures = [executor.submit(download_file, cdn_host + gift.darkRes, "webp_dir", f"{gift.gid}-{gift.darkMd5}") for
gift in result.data]
# 等待所有任务完成
concurrent.futures.wait(futures)
print("所有文件下载完成")
def download_file(url, directory, custom_filename=None):
print("开始下载" + url)
# 如果没有提供自定义文件名,则从URL中解析
if custom_filename is None:
a = urlparse(url)
filename = os.path.basename(a.path)
else:
# 使用提供的自定义文件名
filename = custom_filename
# 确保目录存在
Path(directory).mkdir(parents=True, exist_ok=True)
local_filename = os.path.join(directory, filename)
# 发送GET请求
response = requests.get(url, stream=True)
# 确保请求成功
response.raise_for_status()
# 写入文件到本地路径
with open(local_filename, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
if chunk: # 过滤掉保持活动连接的空字节
f.write(chunk)
print("下载完成")
return local_filename
if __name__ == '__main__':
# uid, token = read_token_uid("13560573423", "123456a")
# print("token=" + token)
# load_gift_resource("13560573423", "123456a")
load_live_gift_list("15889845884", "123456a")
File added
class ObfuseTableBase64:
MAX_LENGTH = 5
MAX_CODE_TIME = 3
placeHolder = ord('l') # 'l'的ASCII码
# 初始化编码表和解码表
@classmethod
def __init__(cls):
# 初始化临时数组
tmp0 = [ord(c) for c in '09_-18634275#']
tmp1 = [0x41 + i for i in range(len(tmp0))]
tmp2 = [tmp1[-1] + i + 1 for i in range(len(tmp1))]
tmp3 = [0x61 + i for i in range(len(tmp1))]
tmp4 = [tmp3[-1] + i + 1 for i in range(len(tmp3))]
data2Arr = [
tmp3, # 0
tmp0, # 1
tmp1, # 2
tmp4, # 3
tmp2 # 4
]
# 生成65字符的中间表
data65 = []
for i in range(5 * len(tmp0)):
quotient, remainder = divmod(i, 5)
data65.append(data2Arr[remainder][quotient])
# 生成64字符的编码表
idx = data65.index(cls.placeHolder) if cls.placeHolder in data65 else 0
cls.encodingTable = data65[:idx] + data65[idx + 1:] if idx < len(data65) else data65[:64]
# 生成解码表
cls.decodingTable = [-1] * 256
for i, char in enumerate(cls.encodingTable):
cls.decodingTable[char] = i
@classmethod
def encode(cls, data):
if isinstance(data, str):
data = data.encode('utf-8')
modulus = len(data) % 3
output_length = (len(data) // 3) * 4 + (4 if modulus else 0)
encoded = bytearray(output_length)
for i in range(0, len(data) - modulus, 3):
byte1, byte2, byte3 = data[i], data[i + 1], data[i + 2]
encoded[i // 3 * 4] = cls.encodingTable[(byte1 >> 2) & 0x3F]
encoded[i // 3 * 4 + 1] = cls.encodingTable[((byte1 << 4) | (byte2 >> 4)) & 0x3F]
encoded[i // 3 * 4 + 2] = cls.encodingTable[((byte2 << 2) | (byte3 >> 6)) & 0x3F]
encoded[i // 3 * 4 + 3] = cls.encodingTable[byte3 & 0x3F]
# 处理余数情况
if modulus == 1:
byte = data[-1]
encoded[-4] = cls.encodingTable[(byte >> 2) & 0x3F]
encoded[-3] = cls.encodingTable[((byte << 4) & 0x3F)]
encoded[-2:] = [cls.placeHolder] * 2
elif modulus == 2:
byte1, byte2 = data[-2], data[-1]
encoded[-4] = cls.encodingTable[(byte1 >> 2) & 0x3F]
encoded[-3] = cls.encodingTable[((byte1 << 4) | (byte2 >> 4)) & 0x3F]
encoded[-2] = cls.encodingTable[((byte2 << 2) & 0x3F)]
encoded[-1] = cls.placeHolder
return encoded.decode('utf-8')
@classmethod
def decode(cls, data):
if isinstance(data, str):
data = data.encode('utf-8')
data = cls.discard_non_base64_bytes(data)
modulus = 0
if data[-2] == cls.placeHolder:
modulus = 1
elif data[-1] == cls.placeHolder:
modulus = 2
output_length = ((len(data) // 4) - 1) * 3 + (4 - modulus)
decoded = bytearray(output_length)
for i in range(0, len(data) - 4, 4):
b1 = cls.decodingTable[data[i]]
b2 = cls.decodingTable[data[i + 1]]
b3 = cls.decodingTable[data[i + 2]]
b4 = cls.decodingTable[data[i + 3]]
decoded[i // 4 * 3] = (b1 << 2) | (b2 >> 4)
decoded[i // 4 * 3 + 1] = (b2 << 4) | (b3 >> 2)
decoded[i // 4 * 3 + 2] = (b3 << 6) | b4
# 处理末尾
if modulus == 1:
b1 = cls.decodingTable[data[-4]]
b2 = cls.decodingTable[data[-3]]
decoded[-1] = (b1 << 2) | (b2 >> 4)
elif modulus == 2:
b1 = cls.decodingTable[data[-4]]
b2 = cls.decodingTable[data[-3]]
b3 = cls.decodingTable[data[-2]]
decoded[-2] = (b1 << 2) | (b2 >> 4)
decoded[-1] = (b2 << 4) | (b3 >> 2)
return decoded.decode('utf-8')
@classmethod
def discard_non_base64_bytes(cls, data):
return bytearray([b for b in data if cls.is_valid_base64_byte(b)])
@classmethod
def is_valid_base64_byte(cls, byte):
if byte == cls.placeHolder:
return True
if byte < 0 or byte >= 128:
return False
return cls.decodingTable[byte] != -1
@classmethod
def obfuse_base64(cls, decode_str):
if not (decode_str.startswith('{{') and decode_str.endswith('}}')):
if decode_str.startswith('"') and decode_str.endswith('"'):
decode_str = decode_str[1:-1]
try:
decode_str = cls.decode(decode_str)
except Exception as e:
print(f"解码错误: {e}")
return decode_str
\ No newline at end of file
import av
import numpy as np
from PIL import Image
import os
def png_to_webm_with_alpha(input_folder, output_file, fps=12):
# 获取所有PNG文件并按名称排序
png_files = sorted([f for f in os.listdir(input_folder) if f.endswith('.png')])
if not png_files:
raise ValueError("No PNG files found in the input folder")
first_image = Image.open(os.path.join(input_folder, png_files[0]))
width, height = first_image.size
# 创建输出容器和视频流
container = av.open(output_file, mode='w')
stream = container.add_stream('libvpx-vp9', rate=fps)
stream.pix_fmt = 'yuva420p'
stream.width = width
stream.height = height
# 设置编码器参数
stream.options = {
'quality': 'good',
'crf': '35',
'auto-alt-ref': '0',
}
for png_file in png_files:
image_path = os.path.join(input_folder, png_file)
image = Image.open(image_path).convert('RGBA')
frame_data = np.array(image)
# 创建AVFrame并填充数据
frame = av.VideoFrame.from_ndarray(frame_data, format='rgba')
# 编码并写入
for packet in stream.encode(frame):
container.mux(packet)
# 刷新编码器(修复此处:传入 None 表示结束)
for packet in stream.encode(None): # <-- 更安全的刷新方式
container.mux(packet)
container.close()
if __name__ == "__main__":
input_folder = "pngs"
output_file = "output.webm"
png_to_webm_with_alpha(input_folder, output_file, fps=12)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment