# aitoolkit-cam
[](https://pypi.org/project/aitoolkit-cam/)
[](https://pypi.org/project/aitoolkit-cam/)
[](https://github.com/dianx12/aitoolkit-cam/blob/main/LICENSE)
极简Python摄像头库 - 专为ARM设备和Jupyter环境设计的高性能摄像头工具包。
## 🚀 特性
- **🎯 简单易用**: 三行代码即可启动摄像头流
- **🔧 MJPEG流修复**: v3.0版本完全解决视频流断流问题
- **🏢 多客户端支持**: 支持多用户同时访问摄像头流
- **📱 Jupyter优化**: 专为Jupyter notebook环境优化
- **🔄 ARM64优化**: 针对树莓派等ARM设备优化性能
- **⚡ FastAPI集成**: 内置Web服务器,一键启动视频流
- **🎨 实时图像处理**: 内置多种滤镜和图像处理功能
## 🛠️ 安装
```bash
pip install aitoolkit-cam
```
## 📖 快速开始
### 基本使用
```python
from aitoolkit_cam import Camera
# 启动摄像头
with Camera(source=0, max_frames=100) as cam:
url = cam.start()
print(f"视频流地址: {url}")
# 处理每一帧
for frame in cam:
# 在这里添加你的图像处理代码
processed_frame = your_processing_function(frame)
cam.show(processed_frame)
```
### FastAPI Web服务
```python
from fastapi import FastAPI
from aitoolkit_cam import add_camera_routes
app = FastAPI()
add_camera_routes(app, prefix="/camera")
# 访问 http://localhost:8000/camera/stream 查看视频流
```
### Jupyter Notebook中使用
```python
import aitoolkit_cam
# 快速启动摄像头管理器
manager = aitoolkit_cam.camera_manager
print(f"摄像头状态: {manager.is_running}")
# 获取单帧图像
frame = manager.read_frame()
if frame is not None:
print(f"成功获取帧: {frame.shape}")
```
## 🔧 高级功能
### 图像滤镜
```python
from aitoolkit_cam import Camera, ImageFilters
with Camera() as cam:
filters = ImageFilters()
url = cam.start()
for frame in cam:
# 应用复古滤镜
vintage_frame = filters.vintage(frame)
cam.show(vintage_frame)
```
### 设备管理
```python
from aitoolkit_cam import list_available_cameras, get_optimal_camera
# 列出所有可用摄像头
cameras = list_available_cameras()
print(f"发现 {len(cameras)} 个摄像头设备")
# 自动选择最佳摄像头
best_camera = get_optimal_camera()
print(f"推荐使用摄像头: {best_camera}")
```
## 📋 版本历史
### v3.0.0 (2025-10-06)
- ✅ **重大修复**: 完全解决MJPEG视频流断流问题
- ✅ **多客户端支持**: 添加JPEG缓存机制,支持多用户同时访问
- ✅ **连接稳定性**: 改进错误处理和恢复机制
- ✅ **浏览器兼容性**: 添加Content-Length头,提高兼容性
- ✅ **性能优化**: 优化ARM设备上的性能表现
### v2.0.0
- 修复MJPEG流显示问题
- 改进多客户端支持
### v1.1.0
- 基础摄像头功能
- Jupyter环境集成
## 🔧 API文档
### Camera类
```python
Camera(source=0, width=640, height=480, fps=20, max_frames=None)
```
**参数:**
- `source`: 摄像头设备索引或路径
- `width`: 视频宽度 (默认: 640)
- `height`: 视频高度 (默认: 480)
- `fps`: 帧率 (默认: 20)
- `max_frames`: 最大帧数限制 (默认: None)
### FastAPI集成
```python
add_camera_routes(app, prefix="/camera")
```
**端点:**
- `GET /camera/stream` - MJPEG视频流
- `GET /camera/frame` - 单帧JPEG图像
- `GET /camera/info` - 摄像头信息
## 🎯 使用场景
1. **教育项目**: 简单易懂的API,适合编程教学
2. **IoT应用**: ARM设备上的视频监控
3. **Jupyter研究**: 数据科学和机器学习中的图像处理
4. **Web应用**: 快速集成视频流功能
5. **原型开发**: 快速搭建包含摄像头的应用原型
## 📞 技术支持
- **问题反馈**: [GitHub Issues](https://github.com/dianx12/aitoolkit-cam/issues)
- **源代码**: [GitHub Repository](https://github.com/dianx12/aitoolkit-cam)
- **作者**: Haitao Wang
- **邮箱**: dianx12@163.com
## 📄 许可证
MIT License - 详见 [LICENSE](LICENSE) 文件。
## 🏷️ 标签
`camera` `opencv` `video` `streaming` `web` `cv2` `jupyter` `notebook` `education` `arm64` `raspberry-pi` `real-time` `smart-stop` `mjpeg` `fastapi`
Raw data
{
"_id": null,
"home_page": "https://github.com/dianx12/aitoolkit-cam",
"name": "aitoolkit-cam",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "camera opencv arm jupyter fastapi mjpeg streaming",
"author": "Haitao Wang",
"author_email": "dianx12@163.com",
"download_url": "https://files.pythonhosted.org/packages/d5/50/1e94cee1d08ee0ac315a299eba839406d3a2abd476611159c480f6250c82/aitoolkit_cam-3.0.0.tar.gz",
"platform": null,
"description": "# aitoolkit-cam\n\n[](https://pypi.org/project/aitoolkit-cam/)\n[](https://pypi.org/project/aitoolkit-cam/)\n[](https://github.com/dianx12/aitoolkit-cam/blob/main/LICENSE)\n\n\u6781\u7b80Python\u6444\u50cf\u5934\u5e93 - \u4e13\u4e3aARM\u8bbe\u5907\u548cJupyter\u73af\u5883\u8bbe\u8ba1\u7684\u9ad8\u6027\u80fd\u6444\u50cf\u5934\u5de5\u5177\u5305\u3002\n\n## \ud83d\ude80 \u7279\u6027\n\n- **\ud83c\udfaf \u7b80\u5355\u6613\u7528**: \u4e09\u884c\u4ee3\u7801\u5373\u53ef\u542f\u52a8\u6444\u50cf\u5934\u6d41\n- **\ud83d\udd27 MJPEG\u6d41\u4fee\u590d**: v3.0\u7248\u672c\u5b8c\u5168\u89e3\u51b3\u89c6\u9891\u6d41\u65ad\u6d41\u95ee\u9898\n- **\ud83c\udfe2 \u591a\u5ba2\u6237\u7aef\u652f\u6301**: \u652f\u6301\u591a\u7528\u6237\u540c\u65f6\u8bbf\u95ee\u6444\u50cf\u5934\u6d41\n- **\ud83d\udcf1 Jupyter\u4f18\u5316**: \u4e13\u4e3aJupyter notebook\u73af\u5883\u4f18\u5316\n- **\ud83d\udd04 ARM64\u4f18\u5316**: \u9488\u5bf9\u6811\u8393\u6d3e\u7b49ARM\u8bbe\u5907\u4f18\u5316\u6027\u80fd\n- **\u26a1 FastAPI\u96c6\u6210**: \u5185\u7f6eWeb\u670d\u52a1\u5668\uff0c\u4e00\u952e\u542f\u52a8\u89c6\u9891\u6d41\n- **\ud83c\udfa8 \u5b9e\u65f6\u56fe\u50cf\u5904\u7406**: \u5185\u7f6e\u591a\u79cd\u6ee4\u955c\u548c\u56fe\u50cf\u5904\u7406\u529f\u80fd\n\n## \ud83d\udee0\ufe0f \u5b89\u88c5\n\n```bash\npip install aitoolkit-cam\n```\n\n## \ud83d\udcd6 \u5feb\u901f\u5f00\u59cb\n\n### \u57fa\u672c\u4f7f\u7528\n\n```python\nfrom aitoolkit_cam import Camera\n\n# \u542f\u52a8\u6444\u50cf\u5934\nwith Camera(source=0, max_frames=100) as cam:\n url = cam.start()\n print(f\"\u89c6\u9891\u6d41\u5730\u5740: {url}\")\n\n # \u5904\u7406\u6bcf\u4e00\u5e27\n for frame in cam:\n # \u5728\u8fd9\u91cc\u6dfb\u52a0\u4f60\u7684\u56fe\u50cf\u5904\u7406\u4ee3\u7801\n processed_frame = your_processing_function(frame)\n cam.show(processed_frame)\n```\n\n### FastAPI Web\u670d\u52a1\n\n```python\nfrom fastapi import FastAPI\nfrom aitoolkit_cam import add_camera_routes\n\napp = FastAPI()\nadd_camera_routes(app, prefix=\"/camera\")\n\n# \u8bbf\u95ee http://localhost:8000/camera/stream \u67e5\u770b\u89c6\u9891\u6d41\n```\n\n### Jupyter Notebook\u4e2d\u4f7f\u7528\n\n```python\nimport aitoolkit_cam\n\n# \u5feb\u901f\u542f\u52a8\u6444\u50cf\u5934\u7ba1\u7406\u5668\nmanager = aitoolkit_cam.camera_manager\nprint(f\"\u6444\u50cf\u5934\u72b6\u6001: {manager.is_running}\")\n\n# \u83b7\u53d6\u5355\u5e27\u56fe\u50cf\nframe = manager.read_frame()\nif frame is not None:\n print(f\"\u6210\u529f\u83b7\u53d6\u5e27: {frame.shape}\")\n```\n\n## \ud83d\udd27 \u9ad8\u7ea7\u529f\u80fd\n\n### \u56fe\u50cf\u6ee4\u955c\n\n```python\nfrom aitoolkit_cam import Camera, ImageFilters\n\nwith Camera() as cam:\n filters = ImageFilters()\n url = cam.start()\n\n for frame in cam:\n # \u5e94\u7528\u590d\u53e4\u6ee4\u955c\n vintage_frame = filters.vintage(frame)\n cam.show(vintage_frame)\n```\n\n### \u8bbe\u5907\u7ba1\u7406\n\n```python\nfrom aitoolkit_cam import list_available_cameras, get_optimal_camera\n\n# \u5217\u51fa\u6240\u6709\u53ef\u7528\u6444\u50cf\u5934\ncameras = list_available_cameras()\nprint(f\"\u53d1\u73b0 {len(cameras)} \u4e2a\u6444\u50cf\u5934\u8bbe\u5907\")\n\n# \u81ea\u52a8\u9009\u62e9\u6700\u4f73\u6444\u50cf\u5934\nbest_camera = get_optimal_camera()\nprint(f\"\u63a8\u8350\u4f7f\u7528\u6444\u50cf\u5934: {best_camera}\")\n```\n\n## \ud83d\udccb \u7248\u672c\u5386\u53f2\n\n### v3.0.0 (2025-10-06)\n- \u2705 **\u91cd\u5927\u4fee\u590d**: \u5b8c\u5168\u89e3\u51b3MJPEG\u89c6\u9891\u6d41\u65ad\u6d41\u95ee\u9898\n- \u2705 **\u591a\u5ba2\u6237\u7aef\u652f\u6301**: \u6dfb\u52a0JPEG\u7f13\u5b58\u673a\u5236\uff0c\u652f\u6301\u591a\u7528\u6237\u540c\u65f6\u8bbf\u95ee\n- \u2705 **\u8fde\u63a5\u7a33\u5b9a\u6027**: \u6539\u8fdb\u9519\u8bef\u5904\u7406\u548c\u6062\u590d\u673a\u5236\n- \u2705 **\u6d4f\u89c8\u5668\u517c\u5bb9\u6027**: \u6dfb\u52a0Content-Length\u5934\uff0c\u63d0\u9ad8\u517c\u5bb9\u6027\n- \u2705 **\u6027\u80fd\u4f18\u5316**: \u4f18\u5316ARM\u8bbe\u5907\u4e0a\u7684\u6027\u80fd\u8868\u73b0\n\n### v2.0.0\n- \u4fee\u590dMJPEG\u6d41\u663e\u793a\u95ee\u9898\n- \u6539\u8fdb\u591a\u5ba2\u6237\u7aef\u652f\u6301\n\n### v1.1.0\n- \u57fa\u7840\u6444\u50cf\u5934\u529f\u80fd\n- Jupyter\u73af\u5883\u96c6\u6210\n\n## \ud83d\udd27 API\u6587\u6863\n\n### Camera\u7c7b\n\n```python\nCamera(source=0, width=640, height=480, fps=20, max_frames=None)\n```\n\n**\u53c2\u6570:**\n- `source`: \u6444\u50cf\u5934\u8bbe\u5907\u7d22\u5f15\u6216\u8def\u5f84\n- `width`: \u89c6\u9891\u5bbd\u5ea6 (\u9ed8\u8ba4: 640)\n- `height`: \u89c6\u9891\u9ad8\u5ea6 (\u9ed8\u8ba4: 480)\n- `fps`: \u5e27\u7387 (\u9ed8\u8ba4: 20)\n- `max_frames`: \u6700\u5927\u5e27\u6570\u9650\u5236 (\u9ed8\u8ba4: None)\n\n### FastAPI\u96c6\u6210\n\n```python\nadd_camera_routes(app, prefix=\"/camera\")\n```\n\n**\u7aef\u70b9:**\n- `GET /camera/stream` - MJPEG\u89c6\u9891\u6d41\n- `GET /camera/frame` - \u5355\u5e27JPEG\u56fe\u50cf\n- `GET /camera/info` - \u6444\u50cf\u5934\u4fe1\u606f\n\n## \ud83c\udfaf \u4f7f\u7528\u573a\u666f\n\n1. **\u6559\u80b2\u9879\u76ee**: \u7b80\u5355\u6613\u61c2\u7684API\uff0c\u9002\u5408\u7f16\u7a0b\u6559\u5b66\n2. **IoT\u5e94\u7528**: ARM\u8bbe\u5907\u4e0a\u7684\u89c6\u9891\u76d1\u63a7\n3. **Jupyter\u7814\u7a76**: \u6570\u636e\u79d1\u5b66\u548c\u673a\u5668\u5b66\u4e60\u4e2d\u7684\u56fe\u50cf\u5904\u7406\n4. **Web\u5e94\u7528**: \u5feb\u901f\u96c6\u6210\u89c6\u9891\u6d41\u529f\u80fd\n5. **\u539f\u578b\u5f00\u53d1**: \u5feb\u901f\u642d\u5efa\u5305\u542b\u6444\u50cf\u5934\u7684\u5e94\u7528\u539f\u578b\n\n## \ud83d\udcde \u6280\u672f\u652f\u6301\n\n- **\u95ee\u9898\u53cd\u9988**: [GitHub Issues](https://github.com/dianx12/aitoolkit-cam/issues)\n- **\u6e90\u4ee3\u7801**: [GitHub Repository](https://github.com/dianx12/aitoolkit-cam)\n- **\u4f5c\u8005**: Haitao Wang\n- **\u90ae\u7bb1**: dianx12@163.com\n\n## \ud83d\udcc4 \u8bb8\u53ef\u8bc1\n\nMIT License - \u8be6\u89c1 [LICENSE](LICENSE) \u6587\u4ef6\u3002\n\n## \ud83c\udff7\ufe0f \u6807\u7b7e\n\n`camera` `opencv` `video` `streaming` `web` `cv2` `jupyter` `notebook` `education` `arm64` `raspberry-pi` `real-time` `smart-stop` `mjpeg` `fastapi`\n",
"bugtrack_url": null,
"license": null,
"summary": "ARM\u6444\u50cf\u5934\u5de5\u5177\u5305 v3.0 - \u4e13\u4e3aJupyter\u73af\u5883\u548cARM\u8bbe\u5907\u4f18\u5316\uff0c\u4fee\u590dMJPEG\u6d41\u95ee\u9898",
"version": "3.0.0",
"project_urls": {
"Bug Reports": "https://github.com/dianx12/aitoolkit-cam/issues",
"Documentation": "https://github.com/dianx12/aitoolkit-cam/blob/main/README.md",
"Homepage": "https://github.com/dianx12/aitoolkit-cam",
"Source": "https://github.com/dianx12/aitoolkit-cam"
},
"split_keywords": [
"camera",
"opencv",
"arm",
"jupyter",
"fastapi",
"mjpeg",
"streaming"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "8ad4487aa48df47d1c53a27fa218a5846f25dfd9ae94d9e3ef02f579b0e22f56",
"md5": "72268a5fe7ab862c50ee1dd289660888",
"sha256": "afef4047335bf386e7e25b97d04311353e33ec81f1c6486fca924b7f6778247f"
},
"downloads": -1,
"filename": "aitoolkit_cam-3.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "72268a5fe7ab862c50ee1dd289660888",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 29935,
"upload_time": "2025-10-06T11:20:42",
"upload_time_iso_8601": "2025-10-06T11:20:42.093874Z",
"url": "https://files.pythonhosted.org/packages/8a/d4/487aa48df47d1c53a27fa218a5846f25dfd9ae94d9e3ef02f579b0e22f56/aitoolkit_cam-3.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "d5501e94cee1d08ee0ac315a299eba839406d3a2abd476611159c480f6250c82",
"md5": "66973736ca4c17f921ff03c79e4e860e",
"sha256": "8c29cd7b0edeae243fd4c0d1924a1aa5a8bf04e8fa5b37047c2b241a97d22819"
},
"downloads": -1,
"filename": "aitoolkit_cam-3.0.0.tar.gz",
"has_sig": false,
"md5_digest": "66973736ca4c17f921ff03c79e4e860e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 27396,
"upload_time": "2025-10-06T11:20:43",
"upload_time_iso_8601": "2025-10-06T11:20:43.664624Z",
"url": "https://files.pythonhosted.org/packages/d5/50/1e94cee1d08ee0ac315a299eba839406d3a2abd476611159c480f6250c82/aitoolkit_cam-3.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-06 11:20:43",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "dianx12",
"github_project": "aitoolkit-cam",
"github_not_found": true,
"lcname": "aitoolkit-cam"
}