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.
Files changed (60) hide show
  1. {pyckplayer-1.0.6/src/Pyckplayer.egg-info → pyckplayer-1.0.8}/PKG-INFO +1 -1
  2. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/setup.py +1 -1
  3. {pyckplayer-1.0.6 → pyckplayer-1.0.8/src/Pyckplayer.egg-info}/PKG-INFO +1 -1
  4. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/core.py +109 -4
  5. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/LICENSE +0 -0
  6. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/MANIFEST.in +0 -0
  7. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/README.md +0 -0
  8. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/pyproject.toml +0 -0
  9. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/setup.cfg +0 -0
  10. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/Pyckplayer.egg-info/SOURCES.txt +0 -0
  11. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/Pyckplayer.egg-info/dependency_links.txt +0 -0
  12. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/Pyckplayer.egg-info/entry_points.txt +0 -0
  13. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/Pyckplayer.egg-info/requires.txt +0 -0
  14. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/Pyckplayer.egg-info/top_level.txt +0 -0
  15. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/__init__.py +0 -0
  16. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/LICENSE +0 -0
  17. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/ckplayer.css +0 -0
  18. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/ckplayer.ixigua.css +0 -0
  19. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/ckplayer.red.css +0 -0
  20. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/adclose.png +0 -0
  21. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/buffer.png +0 -0
  22. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/ckplayer.48.png +0 -0
  23. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/ckplayer.png +0 -0
  24. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/ckplayer_ixigua.48.png +0 -0
  25. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/ckplayer_ixigua.png +0 -0
  26. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/ckplayer_red.48.png +0 -0
  27. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/ckplayer_red.png +0 -0
  28. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/favicon.ico +0 -0
  29. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/loading.png +0 -0
  30. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/logo.png +0 -0
  31. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/css/images/play.png +0 -0
  32. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/flv.js/LICENSE +0 -0
  33. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/flv.js/README.md +0 -0
  34. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/flv.js/flv.js +0 -0
  35. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/flv.js/flv.js.map +0 -0
  36. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/flv.js/flv.min.js +0 -0
  37. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/flv.js/flv.min.js.map +0 -0
  38. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/LICENSE +0 -0
  39. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/README.md +0 -0
  40. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls-demo.js +0 -0
  41. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls-demo.js.map +0 -0
  42. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.js +0 -0
  43. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.js.d.ts +0 -0
  44. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.js.map +0 -0
  45. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.light.js +0 -0
  46. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.light.js.map +0 -0
  47. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.light.min.js +0 -0
  48. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.light.min.js.map +0 -0
  49. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.min.js +0 -0
  50. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/hls.js/hls.min.js.map +0 -0
  51. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/js/ckplayer.js +0 -0
  52. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/js/ckplayer.min.js +0 -0
  53. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/language/en.js +0 -0
  54. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/language/zh.cn.js +0 -0
  55. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/language/zh.hk.js +0 -0
  56. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/mpegts.js/LICENSE +0 -0
  57. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/mpegts.js/mpegts.js +0 -0
  58. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/mpegts.js/mpegts.js.map +0 -0
  59. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/ckplayer/mpegts.js/mpegts.min.js +0 -0
  60. {pyckplayer-1.0.6 → pyckplayer-1.0.8}/src/pyckplayer/cli.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Pyckplayer
3
- Version: 1.0.6
3
+ Version: 1.0.8
4
4
  Summary: 一个基于CKPlayer的Python视频播放器包装器
5
5
  Home-page: https://github.com/yourusername/pyckplayer
6
6
  Author: lenvy1
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="Pyckplayer",
8
- version="1.0.6",
8
+ version="1.0.8",
9
9
  author="lenvy1",
10
10
  author_email="lenvy1@163.com",
11
11
  description="一个基于CKPlayer的Python视频播放器包装器",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Pyckplayer
3
- Version: 1.0.6
3
+ Version: 1.0.8
4
4
  Summary: 一个基于CKPlayer的Python视频播放器包装器
5
5
  Home-page: https://github.com/yourusername/pyckplayer
6
6
  Author: lenvy1
@@ -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
- return any(keyword in url_lower for keyword in live_keywords)
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
- else:
117
- return 'auto'
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