first commit
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "f5f7dfec",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Exception in thread Thread-8 (player_thread):\n",
|
||||
"Traceback (most recent call last):\n",
|
||||
" File \"d:\\Anaconda3\\Lib\\threading.py\", line 1073, in _bootstrap_inner\n",
|
||||
" self.run()\n",
|
||||
" File \"d:\\Anaconda3\\Lib\\threading.py\", line 1010, in run\n",
|
||||
" self._target(*self._args, **self._kwargs)\n",
|
||||
" File \"C:\\Users\\Administrator\\AppData\\Local\\Temp\\ipykernel_16072\\2038425495.py\", line 69, in player_thread\n",
|
||||
" File \"C:\\Users\\Administrator\\AppData\\Local\\Temp\\ipykernel_16072\\2038425495.py\", line 42, in decode_frames\n",
|
||||
"cv2.error: OpenCV(4.11.0) :-1: error: (-5:Bad argument) in function 'open'\n",
|
||||
"> Overload resolution failed:\n",
|
||||
"> - Expected 'filename' to be a str or path-like object\n",
|
||||
"> - VideoCapture.open() missing required argument 'apiPreference' (pos 2)\n",
|
||||
"> - Argument 'index' is required to be an integer\n",
|
||||
"> - VideoCapture.open() missing required argument 'apiPreference' (pos 2)\n",
|
||||
"> - VideoCapture.open() missing required argument 'apiPreference' (pos 2)\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ename": "KeyboardInterrupt",
|
||||
"evalue": "",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
|
||||
"\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
|
||||
"Cell \u001b[1;32mIn[3], line 97\u001b[0m\n\u001b[0;32m 95\u001b[0m m3u8_url \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhttp://113.45.217.230:18800/rtp/34020000001320000155_34020000001320000155/hls.m3u8\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 96\u001b[0m player \u001b[38;5;241m=\u001b[39m HLSPlayer(m3u8_url)\n\u001b[1;32m---> 97\u001b[0m player\u001b[38;5;241m.\u001b[39mstart()\n",
|
||||
"Cell \u001b[1;32mIn[3], line 88\u001b[0m, in \u001b[0;36mHLSPlayer.start\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 85\u001b[0m cv2\u001b[38;5;241m.\u001b[39mimshow(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mHLS Player\u001b[39m\u001b[38;5;124m'\u001b[39m, frame)\n\u001b[0;32m 87\u001b[0m \u001b[38;5;66;03m# 按q退出\u001b[39;00m\n\u001b[1;32m---> 88\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m cv2\u001b[38;5;241m.\u001b[39mwaitKey(\u001b[38;5;241m1\u001b[39m) \u001b[38;5;241m&\u001b[39m \u001b[38;5;241m0xFF\u001b[39m \u001b[38;5;241m==\u001b[39m \u001b[38;5;28mord\u001b[39m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mq\u001b[39m\u001b[38;5;124m'\u001b[39m):\n\u001b[0;32m 89\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrunning \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[0;32m 90\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n",
|
||||
"\u001b[1;31mKeyboardInterrupt\u001b[0m: "
|
||||
]
|
||||
},
|
||||
{
|
||||
"ename": "",
|
||||
"evalue": "",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[1;31m在当前单元格或上一个单元格中执行代码时 Kernel 崩溃。\n",
|
||||
"\u001b[1;31m请查看单元格中的代码,以确定故障的可能原因。\n",
|
||||
"\u001b[1;31m单击<a href='https://aka.ms/vscodeJupyterKernelCrash'>此处</a>了解详细信息。\n",
|
||||
"\u001b[1;31m有关更多详细信息,请查看 Jupyter <a href='command:jupyter.viewOutput'>log</a>。"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import cv2\n",
|
||||
"import m3u8\n",
|
||||
"import requests\n",
|
||||
"import numpy as np\n",
|
||||
"from urllib.parse import urljoin\n",
|
||||
"from threading import Thread\n",
|
||||
"from queue import Queue\n",
|
||||
"\n",
|
||||
"class HLSPlayer:\n",
|
||||
" def __init__(self, m3u8_url):\n",
|
||||
" self.m3u8_url = m3u8_url\n",
|
||||
" self.playlist = None\n",
|
||||
" self.current_segment = 0\n",
|
||||
" self.frame_queue = Queue(maxsize=30)\n",
|
||||
" self.running = False\n",
|
||||
" self.load_playlist()\n",
|
||||
" \n",
|
||||
" def load_playlist(self):\n",
|
||||
" response = requests.get(self.m3u8_url,verify=False)\n",
|
||||
" if response.status_code != 200:\n",
|
||||
" raise Exception(f\"无法下载m3u8文件: {response.status_code}\")\n",
|
||||
" \n",
|
||||
" self.playlist = m3u8.loads(response.text)\n",
|
||||
" \n",
|
||||
" # 如果是多码率播放列表,选择最高码率\n",
|
||||
" if self.playlist.is_variant:\n",
|
||||
" best_stream = max(self.playlist.playlists, key=lambda p: p.stream_info.bandwidth)\n",
|
||||
" self.m3u8_url = urljoin(self.m3u8_url, best_stream.uri)\n",
|
||||
" self.load_playlist()\n",
|
||||
" \n",
|
||||
" def fetch_segment(self, segment_url):\n",
|
||||
" response = requests.get(segment_url,verify=False)\n",
|
||||
" if response.status_code == 200:\n",
|
||||
" # 将TS数据转换为OpenCV可读格式\n",
|
||||
" video_data = np.frombuffer(response.content, dtype=np.uint8)\n",
|
||||
" return video_data\n",
|
||||
" return None\n",
|
||||
" \n",
|
||||
" def decode_frames(self, video_data):\n",
|
||||
" # 使用OpenCV解码视频帧\n",
|
||||
" cap = cv2.VideoCapture()\n",
|
||||
" cap.open(video_data)\n",
|
||||
" \n",
|
||||
" frames = []\n",
|
||||
" while cap.isOpened():\n",
|
||||
" ret, frame = cap.read()\n",
|
||||
" if not ret:\n",
|
||||
" break\n",
|
||||
" frames.append(frame)\n",
|
||||
" \n",
|
||||
" cap.release()\n",
|
||||
" return frames\n",
|
||||
" \n",
|
||||
" def player_thread(self):\n",
|
||||
" self.running = True\n",
|
||||
" while self.running:\n",
|
||||
" # 获取当前片段URL\n",
|
||||
" if self.current_segment >= len(self.playlist.segments):\n",
|
||||
" # 如果是直播流,重新加载播放列表\n",
|
||||
" self.load_playlist()\n",
|
||||
" self.current_segment = 0\n",
|
||||
" \n",
|
||||
" segment = self.playlist.segments[self.current_segment]\n",
|
||||
" segment_url = urljoin(self.m3u8_url, segment.uri)\n",
|
||||
" \n",
|
||||
" # 下载并解码片段\n",
|
||||
" video_data = self.fetch_segment(segment_url)\n",
|
||||
" if video_data is not None:\n",
|
||||
" frames = self.decode_frames(video_data)\n",
|
||||
" \n",
|
||||
" # 将帧放入队列\n",
|
||||
" for frame in frames:\n",
|
||||
" self.frame_queue.put(frame)\n",
|
||||
" \n",
|
||||
" self.current_segment += 1\n",
|
||||
" \n",
|
||||
" def start(self):\n",
|
||||
" # 启动播放器线程\n",
|
||||
" Thread(target=self.player_thread, daemon=True).start()\n",
|
||||
" \n",
|
||||
" # 显示视频\n",
|
||||
" while True:\n",
|
||||
" if not self.frame_queue.empty():\n",
|
||||
" frame = self.frame_queue.get()\n",
|
||||
" cv2.imshow('HLS Player', frame)\n",
|
||||
" \n",
|
||||
" # 按q退出\n",
|
||||
" if cv2.waitKey(1) & 0xFF == ord('q'):\n",
|
||||
" self.running = False\n",
|
||||
" break\n",
|
||||
" \n",
|
||||
" cv2.destroyAllWindows()\n",
|
||||
"\n",
|
||||
"if __name__ == \"__main__\":\n",
|
||||
" m3u8_url = \"http://113.45.217.230:18800/rtp/34020000001320000155_34020000001320000155/hls.m3u8\"\n",
|
||||
" player = HLSPlayer(m3u8_url)\n",
|
||||
" player.start()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "base",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.12.4"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
Reference in New Issue
Block a user