framesource 0.3.0__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 (282) hide show
  1. framesource-0.3.0/.github/workflows/ci.yml +80 -0
  2. framesource-0.3.0/.github/workflows/publish.yaml +45 -0
  3. framesource-0.3.0/.github/workflows/release.yml +41 -0
  4. framesource-0.3.0/.gitignore +104 -0
  5. framesource-0.3.0/CHANGELOG.md +129 -0
  6. framesource-0.3.0/LICENSE +21 -0
  7. framesource-0.3.0/MANIFEST.in +5 -0
  8. framesource-0.3.0/PKG-INFO +787 -0
  9. framesource-0.3.0/README.md +712 -0
  10. framesource-0.3.0/example.py +498 -0
  11. framesource-0.3.0/examples/README.md +156 -0
  12. framesource-0.3.0/examples/audio_spectrogram_example.py +187 -0
  13. framesource-0.3.0/examples/camera_360_example.py +286 -0
  14. framesource-0.3.0/examples/fisheye_ptz_example.py +264 -0
  15. framesource-0.3.0/examples/image_folder_example.py +88 -0
  16. framesource-0.3.0/examples/industrial_cameras_example.py +133 -0
  17. framesource-0.3.0/examples/inference_pipeline_example.py +171 -0
  18. framesource-0.3.0/examples/ipcamera_example.py +92 -0
  19. framesource-0.3.0/examples/multiple_cameras_example.py +151 -0
  20. framesource-0.3.0/examples/multiple_cameras_external_threading.py +235 -0
  21. framesource-0.3.0/examples/realsense_example.py +81 -0
  22. framesource-0.3.0/examples/record_replay_example.py +193 -0
  23. framesource-0.3.0/examples/run_examples.py +71 -0
  24. framesource-0.3.0/examples/screen_capture_example.py +66 -0
  25. framesource-0.3.0/examples/source_swap_example.py +161 -0
  26. framesource-0.3.0/examples/test_window_discovery.py +107 -0
  27. framesource-0.3.0/examples/threading_utils_examples.py +159 -0
  28. framesource-0.3.0/examples/video_file_example.py +75 -0
  29. framesource-0.3.0/examples/webcam_example.py +127 -0
  30. framesource-0.3.0/media/demo.gif +0 -0
  31. framesource-0.3.0/media/geti_demo.mp4 +0 -0
  32. framesource-0.3.0/media/image_seq/1000_71024.jpg +0 -0
  33. framesource-0.3.0/media/image_seq/1000_71024__1.jpg +0 -0
  34. framesource-0.3.0/media/image_seq/100_71024.jpg +0 -0
  35. framesource-0.3.0/media/image_seq/100_71024__1.jpg +0 -0
  36. framesource-0.3.0/media/image_seq/1010_71024.jpg +0 -0
  37. framesource-0.3.0/media/image_seq/1020_71024.jpg +0 -0
  38. framesource-0.3.0/media/image_seq/1030_71024.jpg +0 -0
  39. framesource-0.3.0/media/image_seq/1040_71024.jpg +0 -0
  40. framesource-0.3.0/media/image_seq/1050_71024.jpg +0 -0
  41. framesource-0.3.0/media/image_seq/1060_71024.jpg +0 -0
  42. framesource-0.3.0/media/image_seq/1070_71024.jpg +0 -0
  43. framesource-0.3.0/media/image_seq/1080_71024.jpg +0 -0
  44. framesource-0.3.0/media/image_seq/1090_71024.jpg +0 -0
  45. framesource-0.3.0/media/image_seq/1100_71024.jpg +0 -0
  46. framesource-0.3.0/media/image_seq/1100_71024__1.jpg +0 -0
  47. framesource-0.3.0/media/image_seq/110_71024.jpg +0 -0
  48. framesource-0.3.0/media/image_seq/1110_71024.jpg +0 -0
  49. framesource-0.3.0/media/image_seq/1120_71024.jpg +0 -0
  50. framesource-0.3.0/media/image_seq/1130_71024.jpg +0 -0
  51. framesource-0.3.0/media/image_seq/1140_71024.jpg +0 -0
  52. framesource-0.3.0/media/image_seq/1150_71024.jpg +0 -0
  53. framesource-0.3.0/media/image_seq/1160_71024.jpg +0 -0
  54. framesource-0.3.0/media/image_seq/1170_71024.jpg +0 -0
  55. framesource-0.3.0/media/image_seq/1180_71024.jpg +0 -0
  56. framesource-0.3.0/media/image_seq/1190_71024.jpg +0 -0
  57. framesource-0.3.0/media/image_seq/1200_71024.jpg +0 -0
  58. framesource-0.3.0/media/image_seq/1200_71024__1.jpg +0 -0
  59. framesource-0.3.0/media/image_seq/120_71024.jpg +0 -0
  60. framesource-0.3.0/media/image_seq/1210_71024.jpg +0 -0
  61. framesource-0.3.0/media/image_seq/1220_71024.jpg +0 -0
  62. framesource-0.3.0/media/image_seq/1230_71024.jpg +0 -0
  63. framesource-0.3.0/media/image_seq/1240_71024.jpg +0 -0
  64. framesource-0.3.0/media/image_seq/1250_71024.jpg +0 -0
  65. framesource-0.3.0/media/image_seq/1260_71024.jpg +0 -0
  66. framesource-0.3.0/media/image_seq/1270_71024.jpg +0 -0
  67. framesource-0.3.0/media/image_seq/1280_71024.jpg +0 -0
  68. framesource-0.3.0/media/image_seq/1290_71024.jpg +0 -0
  69. framesource-0.3.0/media/image_seq/1300_71024.jpg +0 -0
  70. framesource-0.3.0/media/image_seq/1300_71024__1.jpg +0 -0
  71. framesource-0.3.0/media/image_seq/130_71024.jpg +0 -0
  72. framesource-0.3.0/media/image_seq/1310_71024.jpg +0 -0
  73. framesource-0.3.0/media/image_seq/1320_71024.jpg +0 -0
  74. framesource-0.3.0/media/image_seq/1330_71024.jpg +0 -0
  75. framesource-0.3.0/media/image_seq/1340_71024.jpg +0 -0
  76. framesource-0.3.0/media/image_seq/1350_71024.jpg +0 -0
  77. framesource-0.3.0/media/image_seq/1360_71024.jpg +0 -0
  78. framesource-0.3.0/media/image_seq/1370_71024.jpg +0 -0
  79. framesource-0.3.0/media/image_seq/1380_71024.jpg +0 -0
  80. framesource-0.3.0/media/image_seq/1390_71024.jpg +0 -0
  81. framesource-0.3.0/media/image_seq/1400_71024.jpg +0 -0
  82. framesource-0.3.0/media/image_seq/1400_71024__1.jpg +0 -0
  83. framesource-0.3.0/media/image_seq/140_71024.jpg +0 -0
  84. framesource-0.3.0/media/image_seq/1410_71024.jpg +0 -0
  85. framesource-0.3.0/media/image_seq/1420_71024.jpg +0 -0
  86. framesource-0.3.0/media/image_seq/1430_71024.jpg +0 -0
  87. framesource-0.3.0/media/image_seq/1440_71024.jpg +0 -0
  88. framesource-0.3.0/media/image_seq/1450_71024.jpg +0 -0
  89. framesource-0.3.0/media/image_seq/1460_71024.jpg +0 -0
  90. framesource-0.3.0/media/image_seq/1470_71024.jpg +0 -0
  91. framesource-0.3.0/media/image_seq/1480_71024.jpg +0 -0
  92. framesource-0.3.0/media/image_seq/1490_71024.jpg +0 -0
  93. framesource-0.3.0/media/image_seq/1500_71024.jpg +0 -0
  94. framesource-0.3.0/media/image_seq/1500_71024__1.jpg +0 -0
  95. framesource-0.3.0/media/image_seq/150_71024.jpg +0 -0
  96. framesource-0.3.0/media/image_seq/1510_71024.jpg +0 -0
  97. framesource-0.3.0/media/image_seq/1520_71024.jpg +0 -0
  98. framesource-0.3.0/media/image_seq/1530_71024.jpg +0 -0
  99. framesource-0.3.0/media/image_seq/1540_71024.jpg +0 -0
  100. framesource-0.3.0/media/image_seq/1600_71024.jpg +0 -0
  101. framesource-0.3.0/media/image_seq/1600_71024__1.jpg +0 -0
  102. framesource-0.3.0/media/image_seq/160_71024.jpg +0 -0
  103. framesource-0.3.0/media/image_seq/1700_71024.jpg +0 -0
  104. framesource-0.3.0/media/image_seq/1700_71024__1.jpg +0 -0
  105. framesource-0.3.0/media/image_seq/170_71024.jpg +0 -0
  106. framesource-0.3.0/media/image_seq/1800_71024.jpg +0 -0
  107. framesource-0.3.0/media/image_seq/1800_71024__1.jpg +0 -0
  108. framesource-0.3.0/media/image_seq/180_71024.jpg +0 -0
  109. framesource-0.3.0/media/image_seq/1900_71024.jpg +0 -0
  110. framesource-0.3.0/media/image_seq/1900_71024__1.jpg +0 -0
  111. framesource-0.3.0/media/image_seq/190_71024.jpg +0 -0
  112. framesource-0.3.0/media/image_seq/2000_71024.jpg +0 -0
  113. framesource-0.3.0/media/image_seq/2000_71024__1.jpg +0 -0
  114. framesource-0.3.0/media/image_seq/200_71024.jpg +0 -0
  115. framesource-0.3.0/media/image_seq/200_71024__1.jpg +0 -0
  116. framesource-0.3.0/media/image_seq/2100_71024.jpg +0 -0
  117. framesource-0.3.0/media/image_seq/2100_71024__1.jpg +0 -0
  118. framesource-0.3.0/media/image_seq/210_71024.jpg +0 -0
  119. framesource-0.3.0/media/image_seq/2200_71024.jpg +0 -0
  120. framesource-0.3.0/media/image_seq/2200_71024__1.jpg +0 -0
  121. framesource-0.3.0/media/image_seq/220_71024.jpg +0 -0
  122. framesource-0.3.0/media/image_seq/2300_71024.jpg +0 -0
  123. framesource-0.3.0/media/image_seq/2300_71024__1.jpg +0 -0
  124. framesource-0.3.0/media/image_seq/230_71024.jpg +0 -0
  125. framesource-0.3.0/media/image_seq/2400_71024.jpg +0 -0
  126. framesource-0.3.0/media/image_seq/2400_71024__1.jpg +0 -0
  127. framesource-0.3.0/media/image_seq/240_71024.jpg +0 -0
  128. framesource-0.3.0/media/image_seq/2500_71024.jpg +0 -0
  129. framesource-0.3.0/media/image_seq/2500_71024__1.jpg +0 -0
  130. framesource-0.3.0/media/image_seq/250_71024.jpg +0 -0
  131. framesource-0.3.0/media/image_seq/2600_71024.jpg +0 -0
  132. framesource-0.3.0/media/image_seq/2600_71024__1.jpg +0 -0
  133. framesource-0.3.0/media/image_seq/260_71024.jpg +0 -0
  134. framesource-0.3.0/media/image_seq/2700_71024.jpg +0 -0
  135. framesource-0.3.0/media/image_seq/2700_71024__1.jpg +0 -0
  136. framesource-0.3.0/media/image_seq/270_71024.jpg +0 -0
  137. framesource-0.3.0/media/image_seq/2800_71024.jpg +0 -0
  138. framesource-0.3.0/media/image_seq/2800_71024__1.jpg +0 -0
  139. framesource-0.3.0/media/image_seq/280_71024.jpg +0 -0
  140. framesource-0.3.0/media/image_seq/2900_71024.jpg +0 -0
  141. framesource-0.3.0/media/image_seq/2900_71024__1.jpg +0 -0
  142. framesource-0.3.0/media/image_seq/290_71024.jpg +0 -0
  143. framesource-0.3.0/media/image_seq/3000_71024.jpg +0 -0
  144. framesource-0.3.0/media/image_seq/3000_71024__1.jpg +0 -0
  145. framesource-0.3.0/media/image_seq/300_71024.jpg +0 -0
  146. framesource-0.3.0/media/image_seq/300_71024__1.jpg +0 -0
  147. framesource-0.3.0/media/image_seq/3100_71024.jpg +0 -0
  148. framesource-0.3.0/media/image_seq/310_71024.jpg +0 -0
  149. framesource-0.3.0/media/image_seq/320_71024.jpg +0 -0
  150. framesource-0.3.0/media/image_seq/330_71024.jpg +0 -0
  151. framesource-0.3.0/media/image_seq/340_71024.jpg +0 -0
  152. framesource-0.3.0/media/image_seq/350_71024.jpg +0 -0
  153. framesource-0.3.0/media/image_seq/360_71024.jpg +0 -0
  154. framesource-0.3.0/media/image_seq/370_71024.jpg +0 -0
  155. framesource-0.3.0/media/image_seq/380_71024.jpg +0 -0
  156. framesource-0.3.0/media/image_seq/390_71024.jpg +0 -0
  157. framesource-0.3.0/media/image_seq/400_71024.jpg +0 -0
  158. framesource-0.3.0/media/image_seq/400_71024__1.jpg +0 -0
  159. framesource-0.3.0/media/image_seq/410_71024.jpg +0 -0
  160. framesource-0.3.0/media/image_seq/420_71024.jpg +0 -0
  161. framesource-0.3.0/media/image_seq/430_71024.jpg +0 -0
  162. framesource-0.3.0/media/image_seq/440_71024.jpg +0 -0
  163. framesource-0.3.0/media/image_seq/450_71024.jpg +0 -0
  164. framesource-0.3.0/media/image_seq/460_71024.jpg +0 -0
  165. framesource-0.3.0/media/image_seq/470_71024.jpg +0 -0
  166. framesource-0.3.0/media/image_seq/480_71024.jpg +0 -0
  167. framesource-0.3.0/media/image_seq/490_71024.jpg +0 -0
  168. framesource-0.3.0/media/image_seq/500_71024.jpg +0 -0
  169. framesource-0.3.0/media/image_seq/500_71024__1.jpg +0 -0
  170. framesource-0.3.0/media/image_seq/510_71024.jpg +0 -0
  171. framesource-0.3.0/media/image_seq/520_71024.jpg +0 -0
  172. framesource-0.3.0/media/image_seq/530_71024.jpg +0 -0
  173. framesource-0.3.0/media/image_seq/540_71024.jpg +0 -0
  174. framesource-0.3.0/media/image_seq/550_71024.jpg +0 -0
  175. framesource-0.3.0/media/image_seq/560_71024.jpg +0 -0
  176. framesource-0.3.0/media/image_seq/570_71024.jpg +0 -0
  177. framesource-0.3.0/media/image_seq/580_71024.jpg +0 -0
  178. framesource-0.3.0/media/image_seq/590_71024.jpg +0 -0
  179. framesource-0.3.0/media/image_seq/600_71024.jpg +0 -0
  180. framesource-0.3.0/media/image_seq/600_71024__1.jpg +0 -0
  181. framesource-0.3.0/media/image_seq/610_71024.jpg +0 -0
  182. framesource-0.3.0/media/image_seq/620_71024.jpg +0 -0
  183. framesource-0.3.0/media/image_seq/630_71024.jpg +0 -0
  184. framesource-0.3.0/media/image_seq/640_71024.jpg +0 -0
  185. framesource-0.3.0/media/image_seq/650_71024.jpg +0 -0
  186. framesource-0.3.0/media/image_seq/660_71024.jpg +0 -0
  187. framesource-0.3.0/media/image_seq/670_71024.jpg +0 -0
  188. framesource-0.3.0/media/image_seq/680_71024.jpg +0 -0
  189. framesource-0.3.0/media/image_seq/690_71024.jpg +0 -0
  190. framesource-0.3.0/media/image_seq/700_71024.jpg +0 -0
  191. framesource-0.3.0/media/image_seq/700_71024__1.jpg +0 -0
  192. framesource-0.3.0/media/image_seq/710_71024.jpg +0 -0
  193. framesource-0.3.0/media/image_seq/720_71024.jpg +0 -0
  194. framesource-0.3.0/media/image_seq/730_71024.jpg +0 -0
  195. framesource-0.3.0/media/image_seq/740_71024.jpg +0 -0
  196. framesource-0.3.0/media/image_seq/750_71024.jpg +0 -0
  197. framesource-0.3.0/media/image_seq/760_71024.jpg +0 -0
  198. framesource-0.3.0/media/image_seq/770_71024.jpg +0 -0
  199. framesource-0.3.0/media/image_seq/780_71024.jpg +0 -0
  200. framesource-0.3.0/media/image_seq/790_71024.jpg +0 -0
  201. framesource-0.3.0/media/image_seq/800_71024.jpg +0 -0
  202. framesource-0.3.0/media/image_seq/800_71024__1.jpg +0 -0
  203. framesource-0.3.0/media/image_seq/810_71024.jpg +0 -0
  204. framesource-0.3.0/media/image_seq/820_71024.jpg +0 -0
  205. framesource-0.3.0/media/image_seq/830_71024.jpg +0 -0
  206. framesource-0.3.0/media/image_seq/840_71024.jpg +0 -0
  207. framesource-0.3.0/media/image_seq/850_71024.jpg +0 -0
  208. framesource-0.3.0/media/image_seq/860_71024.jpg +0 -0
  209. framesource-0.3.0/media/image_seq/870_71024.jpg +0 -0
  210. framesource-0.3.0/media/image_seq/880_71024.jpg +0 -0
  211. framesource-0.3.0/media/image_seq/890_71024.jpg +0 -0
  212. framesource-0.3.0/media/image_seq/900_71024.jpg +0 -0
  213. framesource-0.3.0/media/image_seq/900_71024__1.jpg +0 -0
  214. framesource-0.3.0/media/image_seq/90_71024.jpg +0 -0
  215. framesource-0.3.0/media/image_seq/910_71024.jpg +0 -0
  216. framesource-0.3.0/media/image_seq/920_71024.jpg +0 -0
  217. framesource-0.3.0/media/image_seq/930_71024.jpg +0 -0
  218. framesource-0.3.0/media/image_seq/940_71024.jpg +0 -0
  219. framesource-0.3.0/media/image_seq/950_71024.jpg +0 -0
  220. framesource-0.3.0/media/image_seq/960_71024.jpg +0 -0
  221. framesource-0.3.0/media/image_seq/970_71024.jpg +0 -0
  222. framesource-0.3.0/media/image_seq/980_71024.jpg +0 -0
  223. framesource-0.3.0/media/image_seq/990_71024.jpg +0 -0
  224. framesource-0.3.0/media/interactive_360_demo.gif +0 -0
  225. framesource-0.3.0/pyproject.toml +140 -0
  226. framesource-0.3.0/setup.cfg +4 -0
  227. framesource-0.3.0/src/frame_processors/__init__.py +37 -0
  228. framesource-0.3.0/src/frame_source/__init__.py +50 -0
  229. framesource-0.3.0/src/framesource/__init__.py +93 -0
  230. framesource-0.3.0/src/framesource/_msmf_config.py +26 -0
  231. framesource-0.3.0/src/framesource/_version.py +24 -0
  232. framesource-0.3.0/src/framesource/discovery.py +109 -0
  233. framesource-0.3.0/src/framesource/errors.py +82 -0
  234. framesource-0.3.0/src/framesource/factory.py +290 -0
  235. framesource-0.3.0/src/framesource/processors/__init__.py +34 -0
  236. framesource-0.3.0/src/framesource/processors/equirectangular360_processor.py +577 -0
  237. framesource-0.3.0/src/framesource/processors/fisheye2equirectangular_processor.py +328 -0
  238. framesource-0.3.0/src/framesource/processors/frame_processor.py +30 -0
  239. framesource-0.3.0/src/framesource/processors/hyperspectral_processor.py +23 -0
  240. framesource-0.3.0/src/framesource/processors/realsense_depth_processor.py +90 -0
  241. framesource-0.3.0/src/framesource/py.typed +0 -0
  242. framesource-0.3.0/src/framesource/sources/__init__.py +40 -0
  243. framesource-0.3.0/src/framesource/sources/audiospectrogram_capture.py +1068 -0
  244. framesource-0.3.0/src/framesource/sources/basler_capture.py +477 -0
  245. framesource-0.3.0/src/framesource/sources/folder_capture.py +920 -0
  246. framesource-0.3.0/src/framesource/sources/genicam_capture.py +681 -0
  247. framesource-0.3.0/src/framesource/sources/huateng_capture.py +245 -0
  248. framesource-0.3.0/src/framesource/sources/ipcamera_capture.py +254 -0
  249. framesource-0.3.0/src/framesource/sources/mvsdk.py +2454 -0
  250. framesource-0.3.0/src/framesource/sources/realsense_capture.py +565 -0
  251. framesource-0.3.0/src/framesource/sources/screen_capture.py +800 -0
  252. framesource-0.3.0/src/framesource/sources/video_capture_base.py +560 -0
  253. framesource-0.3.0/src/framesource/sources/video_file_capture.py +259 -0
  254. framesource-0.3.0/src/framesource/sources/webcam_capture.py +511 -0
  255. framesource-0.3.0/src/framesource/sources/ximea_capture.py +299 -0
  256. framesource-0.3.0/src/framesource/threading_utils.py +790 -0
  257. framesource-0.3.0/src/framesource.egg-info/PKG-INFO +787 -0
  258. framesource-0.3.0/src/framesource.egg-info/SOURCES.txt +280 -0
  259. framesource-0.3.0/src/framesource.egg-info/dependency_links.txt +1 -0
  260. framesource-0.3.0/src/framesource.egg-info/requires.txt +34 -0
  261. framesource-0.3.0/src/framesource.egg-info/scm_file_list.json +276 -0
  262. framesource-0.3.0/src/framesource.egg-info/scm_version.json +8 -0
  263. framesource-0.3.0/src/framesource.egg-info/top_level.txt +3 -0
  264. framesource-0.3.0/tests/conftest.py +82 -0
  265. framesource-0.3.0/tests/test_base_capabilities.py +166 -0
  266. framesource-0.3.0/tests/test_contract.py +87 -0
  267. framesource-0.3.0/tests/test_discovery.py +46 -0
  268. framesource-0.3.0/tests/test_discovery_info.py +97 -0
  269. framesource-0.3.0/tests/test_errors.py +186 -0
  270. framesource-0.3.0/tests/test_factory.py +62 -0
  271. framesource-0.3.0/tests/test_frame.py +83 -0
  272. framesource-0.3.0/tests/test_frame_source_shim.py +67 -0
  273. framesource-0.3.0/tests/test_from_config.py +124 -0
  274. framesource-0.3.0/tests/test_grayscale.py +38 -0
  275. framesource-0.3.0/tests/test_high_frequency.py +59 -0
  276. framesource-0.3.0/tests/test_msmf_config.py +48 -0
  277. framesource-0.3.0/tests/test_opencv_api_compatibility.py +102 -0
  278. framesource-0.3.0/tests/test_opencv_compat.py +47 -0
  279. framesource-0.3.0/tests/test_simple_external_threading.py +98 -0
  280. framesource-0.3.0/tests/test_threading_utils.py +229 -0
  281. framesource-0.3.0/tests/test_typed_constructors.py +498 -0
  282. framesource-0.3.0/tests/test_webcam_backend.py +56 -0
@@ -0,0 +1,80 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, tidy]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ name: test (${{ matrix.os }}, py${{ matrix.python-version }})
12
+ runs-on: ${{ matrix.os }}
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ os: [ubuntu-latest, windows-latest]
17
+ python-version: ["3.9", "3.11", "3.13"]
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ with:
21
+ fetch-depth: 0 # setuptools_scm needs history/tags for the version
22
+
23
+ - uses: actions/setup-python@v5
24
+ with:
25
+ python-version: ${{ matrix.python-version }}
26
+
27
+ - name: Install system libraries for headless OpenCV
28
+ if: runner.os == 'Linux'
29
+ run: sudo apt-get update && sudo apt-get install -y libgl1 libglib2.0-0
30
+
31
+ # The audio extra is deliberately not installed: pyaudio needs portaudio
32
+ # system packages, and the audio tests importorskip their dependencies.
33
+ - name: Install package
34
+ run: |
35
+ python -m pip install --upgrade pip
36
+ pip install -e .
37
+ pip install pytest
38
+
39
+ - name: Run hardware-free test suite
40
+ run: pytest -m "not hardware"
41
+
42
+ lint:
43
+ name: lint (ruff)
44
+ runs-on: ubuntu-latest
45
+ steps:
46
+ - uses: actions/checkout@v4
47
+ - uses: actions/setup-python@v5
48
+ with:
49
+ python-version: "3.12"
50
+ - run: pip install ruff
51
+ - run: ruff check .
52
+ - run: ruff format --check .
53
+
54
+ typecheck:
55
+ name: mypy (non-blocking)
56
+ runs-on: ubuntu-latest
57
+ continue-on-error: true
58
+ steps:
59
+ - uses: actions/checkout@v4
60
+ - uses: actions/setup-python@v5
61
+ with:
62
+ python-version: "3.12"
63
+ - run: |
64
+ pip install mypy
65
+ pip install -e .
66
+ - run: mypy src/framesource
67
+
68
+ build:
69
+ name: build & twine check
70
+ runs-on: ubuntu-latest
71
+ steps:
72
+ - uses: actions/checkout@v4
73
+ with:
74
+ fetch-depth: 0
75
+ - uses: actions/setup-python@v5
76
+ with:
77
+ python-version: "3.12"
78
+ - run: pip install build twine
79
+ - run: python -m build
80
+ - run: twine check dist/*
@@ -0,0 +1,45 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ # Manual runs must be dispatched from a tag ref (e.g. v0.3.0), otherwise
8
+ # setuptools_scm produces a dev version that PyPI rejects.
9
+ workflow_dispatch:
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ with:
17
+ fetch-depth: 0 # setuptools_scm derives the version from the tag
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.12"
21
+ - run: pip install build twine
22
+ - run: python -m build
23
+ - run: twine check dist/*
24
+ - uses: actions/upload-artifact@v4
25
+ with:
26
+ name: dist
27
+ path: dist/
28
+
29
+ publish:
30
+ needs: build
31
+ runs-on: ubuntu-latest
32
+ environment:
33
+ name: pypi
34
+ url: https://pypi.org/p/framesource
35
+ # Trusted publishing: on pypi.org, add this repo as a trusted publisher
36
+ # for the "framesource" project with workflow name "publish.yaml" and
37
+ # environment "pypi" (one-time, manual). No API token is stored in the repo.
38
+ permissions:
39
+ id-token: write
40
+ steps:
41
+ - uses: actions/download-artifact@v4
42
+ with:
43
+ name: dist
44
+ path: dist/
45
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,41 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ with:
14
+ fetch-depth: 0 # setuptools_scm derives the version from the tag
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.12"
18
+ - run: pip install build twine
19
+ - run: python -m build
20
+ - run: twine check dist/*
21
+ - uses: actions/upload-artifact@v4
22
+ with:
23
+ name: dist
24
+ path: dist/
25
+
26
+ # PyPI publishing lives in publish.yaml (same v* tag trigger).
27
+
28
+ github-release:
29
+ needs: build
30
+ runs-on: ubuntu-latest
31
+ permissions:
32
+ contents: write
33
+ steps:
34
+ - uses: actions/download-artifact@v4
35
+ with:
36
+ name: dist
37
+ path: dist/
38
+ - uses: softprops/action-gh-release@v2
39
+ with:
40
+ files: dist/*
41
+ generate_release_notes: true
@@ -0,0 +1,104 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # setuptools_scm generated version file
7
+ src/framesource/_version.py
8
+
9
+ # C extensions
10
+ *.so
11
+
12
+ # Distribution / packaging
13
+ .Python
14
+ env/
15
+ build/
16
+ develop-eggs/
17
+ dist/
18
+ downloads/
19
+ eggs/
20
+ .eggs/
21
+ lib/
22
+ lib64/
23
+ parts/
24
+ sdist/
25
+ var/
26
+ *.egg-info/
27
+ .installed.cfg
28
+ *.egg
29
+ MANIFEST
30
+
31
+ # Virtual environments
32
+ venv/
33
+ ENV/
34
+ env.bak/
35
+ venv.bak/
36
+ .venv/
37
+ .github/prompts/
38
+
39
+
40
+ # PyInstaller
41
+ # Usually these files are written by a python script from a template
42
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
43
+ build/
44
+ dist/
45
+ *.spec
46
+
47
+ # Installer logs
48
+ debug.log
49
+
50
+ # Unit test / coverage reports
51
+ htmlcov/
52
+ .tox/
53
+ .nox/
54
+ .coverage
55
+ .coverage.*
56
+ .cache
57
+ nosetests.xml
58
+ coverage.xml
59
+ *.cover
60
+ .hypothesis/
61
+ .pytest_cache/
62
+
63
+ # Jupyter Notebook
64
+ .ipynb_checkpoints
65
+
66
+ # pyenv
67
+ .python-version
68
+
69
+ # pipenv
70
+ Pipfile.lock
71
+
72
+ # mypy
73
+ .mypy_cache/
74
+ .dmypy.json
75
+
76
+ # Pyre type checker
77
+ .pyre/
78
+
79
+ # VS Code
80
+ .vscode/
81
+
82
+ # Windows
83
+ Thumbs.db
84
+ Desktop.ini
85
+ $RECYCLE.BIN/
86
+
87
+ # macOS
88
+ .DS_Store
89
+ .AppleDouble
90
+ .LSOverride
91
+
92
+ # Linux
93
+ *~
94
+
95
+ # Logs
96
+ *.log
97
+
98
+ # Other
99
+ *.swp
100
+ *.swo
101
+
102
+ # Project-specific
103
+ src/*/__pycache__/
104
+ src/__pycache__/folder_capture.cpython-311.pyc
@@ -0,0 +1,129 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+
12
+ - `WebcamCapture` gains `backend` and `fourcc` constructor keyword arguments.
13
+ `backend` selects the OpenCV capture backend by name (`'msmf'`, `'dshow'`,
14
+ `'v4l2'`, `'avfoundation'`, `'gstreamer'`, `'ffmpeg'`, `'any'`) or a raw
15
+ `cv2.CAP_*` int; `fourcc` (e.g. `'MJPG'`) requests a pixel format, applied
16
+ before the resolution so drivers don't reset it. Fixes uncompressed formats
17
+ (e.g. YUY2) saturating the USB link and throttling high-resolution capture
18
+ to single-digit frame rates. `connect()` now logs a warning when it detects
19
+ an uncompressed format negotiated at 720p or above, and `get_fourcc()`
20
+ reports the negotiated format.
21
+
22
+ ### Fixed
23
+
24
+ - Importing `framesource` now disables OpenCV MSMF hardware transforms on
25
+ Windows (`OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS=0`, via `setdefault` so
26
+ an explicit user value wins). This cuts webcam open time on affected devices
27
+ from 20+ seconds to a fraction of a second with no throughput cost. Only
28
+ effective when `framesource` is imported before `cv2` opens an MSMF device.
29
+
30
+ ## [0.3.0] - 2026-07-12
31
+
32
+ The "synchronous core" release. The package was renamed, the internal
33
+ threading model was removed in favour of explicit, opt-in concurrency
34
+ helpers, and frames now carry metadata. Existing code keeps working: the
35
+ old import name, factory parameter names, and the OpenCV-compatible
36
+ `isOpened()` / `read()` / `release()` surface are all preserved.
37
+
38
+ ### Added
39
+
40
+ - `Frame` — an `np.ndarray` subclass returned by `read()`, carrying
41
+ `timestamp` (wall clock), `monotonic` (for latency/FPS math), `count`,
42
+ `uuid`, `source`, and a free-form `metadata` dict. Works in any
43
+ OpenCV/numpy call and survives pickling.
44
+ - `FrameSourceProtocol` — runtime-checkable protocol defining the minimal
45
+ source contract (`connect`/`disconnect`/`read`/`is_open`), so custom
46
+ sources can be duck-typed without inheriting `VideoCaptureBase`.
47
+ - `framesource.errors` — `FrameSourceError` base plus
48
+ `MissingDependencyError` (an `ImportError` carrying the pip-extra install
49
+ hint), `UnknownSourceTypeError` (a `ValueError`, raised by the factory),
50
+ and `NotConnectedError`. Existing `except ImportError/ValueError` clauses
51
+ keep working.
52
+ - `DeviceInfo` — typed, dict-compatible device descriptor returned by
53
+ `discover()` implementations.
54
+ - Typed constructors with explicit keyword parameters for the consumer
55
+ sources (`WebcamCapture`, `VideoFileCapture`, `FolderCapture`,
56
+ `IPCameraCapture`, `ScreenCapture`, `AudioSpectrogramCapture`) and the
57
+ vendor sources (`BaslerCapture`, `GenicamCapture`, `RealsenseCapture`,
58
+ `XimeaCapture`, `HuatengCapture`).
59
+ - Capability flags on every source (`supports_exposure`, `supports_gain`,
60
+ `supports_depth`) replacing `hasattr()` probing.
61
+ - Iterator protocol — `for frame in cap:` yields frames until the source is
62
+ exhausted.
63
+ - `wait_until_ready(timeout)` — poll until a source actually produces
64
+ frames (RTSP "connected but not yet streaming").
65
+ - `fps_actual()` — rolling-window measured FPS on the monotonic clock.
66
+ - `framesource.threading_utils` additions: `AsyncFrameSource` (asyncio
67
+ adapter), `SharedProducer` (one producer, N subscriber queues),
68
+ `ProducerConsumer` (joinable producer/consumer pair handle), and
69
+ `FrameProducer.get_stats()` now reports `avg_latency` and warns on high
70
+ drop rates.
71
+ - `FrameSourceFactory.from_config()` — create a source from a dict or a
72
+ `.json`/`.yaml` config file (YAML requires PyYAML to be installed).
73
+ - Optional-dependency extras: `audio`, `basler`, `realsense`, `genicam`,
74
+ `full`. `py.typed` marker shipped.
75
+ - Real-world examples: inference pipeline with back-pressure, record →
76
+ replay, and source swapping; CI (GitHub Actions) across
77
+ Ubuntu/Windows × Python 3.9/3.11/3.13; release automation via PyPI
78
+ trusted publishing.
79
+
80
+ ### Changed
81
+
82
+ - **Package renamed** to `framesource` (import and PyPI name now match),
83
+ with a `src/` layout and `sources`/`processors` subpackages.
84
+ - **Synchronous core**: capture classes no longer spawn internal threads.
85
+ Concurrency is explicit via `framesource.threading_utils`
86
+ (`simple_frame_producer`, `FrameProducer`, multiprocessing helper).
87
+ The sole exception is `AudioSpectrogramCapture`'s audio ring-buffer
88
+ thread, which is inherent to its I/O model.
89
+ - Factory parameters renamed for clarity: `capture_type` → `source_type`,
90
+ `source` → `source_id` (old names still work, see Deprecated).
91
+ - Library no longer calls `logging.basicConfig()` or prints to stdout; all
92
+ diagnostics go through per-module loggers.
93
+ - Python floor raised to 3.9 (3.8 is end-of-life).
94
+ - Versioning is tag-driven via `setuptools_scm`.
95
+ - Lint/format tooling consolidated on ruff (replacing black + isort).
96
+
97
+ ### Deprecated
98
+
99
+ - `import frame_source` — use `import framesource`. The shim (including
100
+ deep imports like `frame_source.webcam_capture`) warns and will be
101
+ removed in a future major release.
102
+ - Factory params `capture_type=` / `source=` — use `source_type` /
103
+ `source_id`. Warn via `DeprecationWarning`; no removal scheduled within
104
+ 0.x.
105
+ - `get_config_schema()` on all sources — UI form schemas belong in the
106
+ consuming application; typed constructors expose the same information.
107
+ Scheduled for removal in 0.4.0.
108
+
109
+ ### Removed
110
+
111
+ - Web-UI residue: `get_available_sources()` and the `display_fields` class
112
+ attributes.
113
+ - Internal threading API: `start_async()`, `stop()`, `get_latest_frame()`,
114
+ `_background_capture` (deprecated behaviourally by the synchronous core;
115
+ the old methods no longer exist).
116
+
117
+ ### Fixed
118
+
119
+ - `AudioSpectrogramCapture` accepts `freq_range` as a tuple/list as
120
+ documented, not only as a `"min,max"` string.
121
+ - `FrameSourceFactory.create(connect=False)` no longer leaks the `connect`
122
+ kwarg into the capture's config.
123
+ - `multiprocess_frame_producer` no longer raises `UnboundLocalError` when
124
+ source creation fails; queue-full handling is explicit.
125
+ - `readme.md` renamed to `README.md`, fixing sdist builds on
126
+ case-sensitive filesystems.
127
+
128
+ [Unreleased]: https://github.com/olkham/FrameSource/compare/v0.3.0...HEAD
129
+ [0.3.0]: https://github.com/olkham/FrameSource/releases/tag/v0.3.0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Oliver Hamilton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,5 @@
1
+ include README.md
2
+ include LICENSE
3
+ recursive-include src/framesource *.py
4
+ recursive-include src/frame_source *.py
5
+ include src/framesource/py.typed