Pyckplayer 1.0.6__tar.gz → 1.0.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyckplayer-1.0.6/src/Pyckplayer.egg-info → pyckplayer-1.0.8}/PKG-INFO +1 -1
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/setup.py +1 -1
- {pyckplayer-1.0.6 → pyckplayer-1.0.8/src/Pyckplayer.egg-info}/PKG-INFO +1 -1
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/core.py +109 -4
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/LICENSE +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/MANIFEST.in +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/README.md +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/pyproject.toml +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/setup.cfg +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/Pyckplayer.egg-info/SOURCES.txt +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/Pyckplayer.egg-info/dependency_links.txt +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/Pyckplayer.egg-info/entry_points.txt +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/Pyckplayer.egg-info/requires.txt +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/Pyckplayer.egg-info/top_level.txt +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/__init__.py +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/LICENSE +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/ckplayer.css +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/ckplayer.ixigua.css +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/ckplayer.red.css +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/adclose.png +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/buffer.png +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/ckplayer.48.png +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/ckplayer.png +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/ckplayer_ixigua.48.png +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/ckplayer_ixigua.png +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/ckplayer_red.48.png +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/ckplayer_red.png +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/favicon.ico +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/loading.png +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/logo.png +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/play.png +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/flv.js/LICENSE +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/flv.js/README.md +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/flv.js/flv.js +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/flv.js/flv.js.map +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/flv.js/flv.min.js +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/flv.js/flv.min.js.map +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/LICENSE +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/README.md +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls-demo.js +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls-demo.js.map +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.js +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.js.d.ts +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.js.map +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.light.js +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.light.js.map +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.light.min.js +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.light.min.js.map +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.min.js +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.min.js.map +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/js/ckplayer.js +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/js/ckplayer.min.js +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/language/en.js +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/language/zh.cn.js +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/language/zh.hk.js +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/mpegts.js/LICENSE +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/mpegts.js/mpegts.js +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/mpegts.js/mpegts.js.map +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/mpegts.js/mpegts.min.js +0 -0
- {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/cli.py +0 -0
|
@@ -6,7 +6,12 @@ import json
|
|
|
6
6
|
import atexit
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from urllib.parse import quote
|
|
9
|
-
from typing import Optional, Tuple, Union
|
|
9
|
+
from typing import Optional, Tuple, Union, Dict, Any
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
import cv2
|
|
13
|
+
except ImportError:
|
|
14
|
+
cv2 = None
|
|
10
15
|
|
|
11
16
|
|
|
12
17
|
DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
|
|
@@ -91,6 +96,78 @@ def download_cover(poster_url: Optional[str], silent: bool = True) -> Optional[s
|
|
|
91
96
|
return None
|
|
92
97
|
|
|
93
98
|
|
|
99
|
+
def is_streaming_protocol(url: str) -> bool:
|
|
100
|
+
streaming_protocols = [
|
|
101
|
+
'rtsp://', 'rtmp://', 'rtmps://', 'rtmpt://', 'rtmpte://',
|
|
102
|
+
'http://', 'https://'
|
|
103
|
+
]
|
|
104
|
+
url_lower = url.lower()
|
|
105
|
+
return any(url_lower.startswith(protocol) for protocol in streaming_protocols)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def get_content_type(url: str) -> Optional[str]:
|
|
109
|
+
try:
|
|
110
|
+
response = requests.head(url, timeout=5, allow_redirects=True)
|
|
111
|
+
if 'Content-Type' in response.headers:
|
|
112
|
+
return response.headers['Content-Type']
|
|
113
|
+
except Exception:
|
|
114
|
+
pass
|
|
115
|
+
return None
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def is_streaming_content(content_type: str) -> bool:
|
|
119
|
+
streaming_content_types = [
|
|
120
|
+
'application/vnd.apple.mpegurl',
|
|
121
|
+
'application/dash+xml',
|
|
122
|
+
'audio/mpegurl',
|
|
123
|
+
'video/mp4',
|
|
124
|
+
'video/flv',
|
|
125
|
+
'video/quicktime',
|
|
126
|
+
'application/x-mpegURL',
|
|
127
|
+
'application/octet-stream'
|
|
128
|
+
]
|
|
129
|
+
if content_type:
|
|
130
|
+
content_type_lower = content_type.lower()
|
|
131
|
+
return any(ct in content_type_lower for ct in streaming_content_types)
|
|
132
|
+
return False
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def get_video_info(video_url: str) -> Optional[Dict[str, Any]]:
|
|
136
|
+
if cv2 is None:
|
|
137
|
+
return None
|
|
138
|
+
|
|
139
|
+
cap = cv2.VideoCapture(video_url)
|
|
140
|
+
if not cap.isOpened():
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
|
144
|
+
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
|
145
|
+
fps = cap.get(cv2.CAP_PROP_FPS)
|
|
146
|
+
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
|
147
|
+
duration = frame_count / fps if fps > 0 else 0
|
|
148
|
+
fourcc_code = int(cap.get(cv2.CAP_PROP_FOURCC))
|
|
149
|
+
fourcc = (
|
|
150
|
+
chr((fourcc_code >> 0) & 0xFF)
|
|
151
|
+
+ chr((fourcc_code >> 8) & 0xFF)
|
|
152
|
+
+ chr((fourcc_code >> 16) & 0xFF)
|
|
153
|
+
+ chr((fourcc_code >> 24) & 0xFF)
|
|
154
|
+
)
|
|
155
|
+
bitrate = int(cap.get(cv2.CAP_PROP_BITRATE))
|
|
156
|
+
|
|
157
|
+
cap.release()
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
"width": width,
|
|
161
|
+
"height": height,
|
|
162
|
+
"resolution": f"{width}x{height}",
|
|
163
|
+
"fps": round(fps, 2),
|
|
164
|
+
"frame_count": frame_count,
|
|
165
|
+
"duration": round(duration, 2),
|
|
166
|
+
"fourcc": fourcc,
|
|
167
|
+
"bitrate": bitrate,
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
|
|
94
171
|
def is_live_url(url: str) -> bool:
|
|
95
172
|
url_lower = url.lower()
|
|
96
173
|
live_keywords = [
|
|
@@ -100,11 +177,25 @@ def is_live_url(url: str) -> bool:
|
|
|
100
177
|
'douyincdn.com', 'live.kuaishou.com', 'live.bilibili.com',
|
|
101
178
|
'live.douyin.com', 'live.qq.com', 'live.weibo.com'
|
|
102
179
|
]
|
|
103
|
-
|
|
180
|
+
if any(keyword in url_lower for keyword in live_keywords):
|
|
181
|
+
return True
|
|
182
|
+
|
|
183
|
+
video_info = get_video_info(url)
|
|
184
|
+
if video_info is not None:
|
|
185
|
+
duration = video_info.get("duration", 0)
|
|
186
|
+
if duration < 0:
|
|
187
|
+
return True
|
|
188
|
+
|
|
189
|
+
content_type = get_content_type(url)
|
|
190
|
+
if content_type:
|
|
191
|
+
return is_streaming_content(content_type)
|
|
192
|
+
|
|
193
|
+
return False
|
|
104
194
|
|
|
105
195
|
|
|
106
196
|
def detect_stream_type(url: str) -> str:
|
|
107
197
|
url_lower = url.lower()
|
|
198
|
+
|
|
108
199
|
if '.m3u8' in url_lower or '/hls/' in url_lower:
|
|
109
200
|
return 'hls'
|
|
110
201
|
elif '.flv' in url_lower:
|
|
@@ -113,8 +204,22 @@ def detect_stream_type(url: str) -> str:
|
|
|
113
204
|
return 'ts'
|
|
114
205
|
elif '.mp4' in url_lower:
|
|
115
206
|
return 'mp4'
|
|
116
|
-
|
|
117
|
-
return '
|
|
207
|
+
elif url_lower.startswith('rtsp://'):
|
|
208
|
+
return 'rtsp'
|
|
209
|
+
elif url_lower.startswith('rtmp://') or url_lower.startswith('rtmps://'):
|
|
210
|
+
return 'rtmp'
|
|
211
|
+
|
|
212
|
+
content_type = get_content_type(url)
|
|
213
|
+
if content_type:
|
|
214
|
+
content_type_lower = content_type.lower()
|
|
215
|
+
if 'mpegurl' in content_type_lower or 'hls' in content_type_lower:
|
|
216
|
+
return 'hls'
|
|
217
|
+
elif 'flv' in content_type_lower:
|
|
218
|
+
return 'flv'
|
|
219
|
+
elif 'dash' in content_type_lower:
|
|
220
|
+
return 'dash'
|
|
221
|
+
|
|
222
|
+
return 'auto'
|
|
118
223
|
|
|
119
224
|
|
|
120
225
|
def generate_html(video_url: str,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/ckplayer_ixigua.48.png
RENAMED
|
File without changes
|
{pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/ckplayer_ixigua.png
RENAMED
|
File without changes
|
{pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/ckplayer_red.48.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|