mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-09-29 21:02:55 +08:00
Compare commits
1693 Commits
v0.8.0-rc4
...
release_wo
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1d58e419f4 | ||
![]() |
16dc9f4bf7 | ||
![]() |
52b47a3414 | ||
![]() |
139664e598 | ||
![]() |
441c605312 | ||
![]() |
def889e3a8 | ||
![]() |
613f1f6bd6 | ||
![]() |
e173377859 | ||
![]() |
86c59c1722 | ||
![]() |
a399cb09fa | ||
![]() |
5a46c36380 | ||
![]() |
36c1e00a6b | ||
![]() |
859ab0e7fa | ||
![]() |
cf2b56613f | ||
![]() |
1a9e00ee49 | ||
![]() |
b9649de327 | ||
![]() |
823550eed3 | ||
![]() |
c141362614 | ||
![]() |
e0e8a6fcc9 | ||
![]() |
0b858419d1 | ||
![]() |
2fb7200fb7 | ||
![]() |
e9376ca285 | ||
![]() |
cff4b9651f | ||
![]() |
9df5927ac5 | ||
![]() |
29f82add72 | ||
![]() |
d102ebf855 | ||
![]() |
cb3990a0ac | ||
![]() |
9fc93c72a0 | ||
![]() |
e13a176820 | ||
![]() |
1e71e36056 | ||
![]() |
18545718c1 | ||
![]() |
c8b38bdd47 | ||
![]() |
e80b6d9e5b | ||
![]() |
ee1e1b748c | ||
![]() |
0c2f3a9702 | ||
![]() |
a3c0e30502 | ||
![]() |
b4d5a3ef14 | ||
![]() |
facd557f8c | ||
![]() |
12487b3b60 | ||
![]() |
8f349a6365 | ||
![]() |
91f7d67c5e | ||
![]() |
98200b7dda | ||
![]() |
282cbf8f40 | ||
![]() |
cd35481e92 | ||
![]() |
126aed2798 | ||
![]() |
efbc094bbc | ||
![]() |
c7b2c6b95d | ||
![]() |
1bdfc380c3 | ||
![]() |
cac37e484d | ||
![]() |
4469507e5b | ||
![]() |
8626160df2 | ||
![]() |
d4d2bb2521 | ||
![]() |
e545dfc47b | ||
![]() |
9ea10f8541 | ||
![]() |
fa6c6c50d0 | ||
![]() |
4c7ea01137 | ||
![]() |
34b315cc8c | ||
![]() |
9b687d77ce | ||
![]() |
e32bd4ab15 | ||
![]() |
e19c0668e7 | ||
![]() |
869bb2b177 | ||
![]() |
3869b274e2 | ||
![]() |
2379e6fd1b | ||
![]() |
dcafcc1320 | ||
![]() |
d508088bd0 | ||
![]() |
97e5a98b95 | ||
![]() |
68ebd55425 | ||
![]() |
a82334ca1c | ||
![]() |
d7ddcea951 | ||
![]() |
cc6e049966 | ||
![]() |
dbd21eb6fa | ||
![]() |
e1a6398219 | ||
![]() |
7f5fba08b7 | ||
![]() |
c35e8371be | ||
![]() |
49e7723405 | ||
![]() |
52cc707eb8 | ||
![]() |
c47b02d2fe | ||
![]() |
3a460133d4 | ||
![]() |
67a5a7d21a | ||
![]() |
5d2b87e077 | ||
![]() |
8298806028 | ||
![]() |
8cc7acd591 | ||
![]() |
8bde914939 | ||
![]() |
fe9fcf3eaa | ||
![]() |
20c2ab39bc | ||
![]() |
08ef69bac4 | ||
![]() |
79fabbb6b0 | ||
![]() |
8941aa5311 | ||
![]() |
14d2b79c72 | ||
![]() |
9a4f970337 | ||
![]() |
22b9507797 | ||
![]() |
37379e6fba | ||
![]() |
232588636f | ||
![]() |
e77fedc445 | ||
![]() |
ead03c381b | ||
![]() |
0048cd5edc | ||
![]() |
56dfcd7a32 | ||
![]() |
9f3ac19e05 | ||
![]() |
50f13b7196 | ||
![]() |
50b17031c4 | ||
![]() |
d11c1a2066 | ||
![]() |
27144eb0b9 | ||
![]() |
64705c065f | ||
![]() |
08eefd8385 | ||
![]() |
705ee54315 | ||
![]() |
e26bb94007 | ||
![]() |
1aba8c1ef5 | ||
![]() |
f92237c9c1 | ||
![]() |
0858859939 | ||
![]() |
1c27ee2d2b | ||
![]() |
08586f8f65 | ||
![]() |
cfd04d164e | ||
![]() |
fa2e4993d9 | ||
![]() |
080d7a2d88 | ||
![]() |
7d0216b8fb | ||
![]() |
c743dfd657 | ||
![]() |
4a6579527b | ||
![]() |
fd9196ae3e | ||
![]() |
a3eccce8f3 | ||
![]() |
111933d3b4 | ||
![]() |
76d4f16db3 | ||
![]() |
0d6bb6714a | ||
![]() |
5d30944d6e | ||
![]() |
3797340efa | ||
![]() |
8728139ae3 | ||
![]() |
730851cda9 | ||
![]() |
46412e99d9 | ||
![]() |
e5664826b1 | ||
![]() |
9a1c8b2cc4 | ||
![]() |
6aedc39a9a | ||
![]() |
b9e6afa659 | ||
![]() |
9185753322 | ||
![]() |
a1b50d2cf4 | ||
![]() |
a2206bb177 | ||
![]() |
5658e5a4cc | ||
![]() |
2a0b8a78fe | ||
![]() |
b80ff1aa3a | ||
![]() |
f682203f9d | ||
![]() |
a63af1a891 | ||
![]() |
64fd5f8be3 | ||
![]() |
6e35c97376 | ||
![]() |
db6ee41f3c | ||
![]() |
36434bb26d | ||
![]() |
3c25c578f0 | ||
![]() |
2e4f5bc0e0 | ||
![]() |
bd0d16a75b | ||
![]() |
7069ef93bb | ||
![]() |
737681aa4f | ||
![]() |
77cb469430 | ||
![]() |
3e18d58921 | ||
![]() |
de6a916939 | ||
![]() |
45f7db5cf1 | ||
![]() |
bbdf5e1bee | ||
![]() |
b538572afb | ||
![]() |
14048cb83e | ||
![]() |
602041beb1 | ||
![]() |
ef6b464d0e | ||
![]() |
731743c7e5 | ||
![]() |
f25bee7672 | ||
![]() |
7c629c1874 | ||
![]() |
6146afe8f7 | ||
![]() |
c815f3c331 | ||
![]() |
767abed7f0 | ||
![]() |
28ea2afa51 | ||
![]() |
3921a7faa2 | ||
![]() |
4c63ad767a | ||
![]() |
afe3b5dd3d | ||
![]() |
fbed3fbb8b | ||
![]() |
318ae28004 | ||
![]() |
24365fb865 | ||
![]() |
36ccaa4cff | ||
![]() |
98576418a8 | ||
![]() |
c2e2656407 | ||
![]() |
e941012d48 | ||
![]() |
7d3e5c9c4c | ||
![]() |
b7ff6735f6 | ||
![]() |
f57d21039e | ||
![]() |
d0b38f0a47 | ||
![]() |
b79b1d9443 | ||
![]() |
947ccbc654 | ||
![]() |
eaf7078d98 | ||
![]() |
b42e995f0f | ||
![]() |
f8c0f74ab8 | ||
![]() |
f9d422b5b5 | ||
![]() |
f0dda499f8 | ||
![]() |
a96602f3f5 | ||
![]() |
961ce03835 | ||
![]() |
761daf46ea | ||
![]() |
9016a48dc7 | ||
![]() |
a96a951e23 | ||
![]() |
680198148b | ||
![]() |
dc44a6c3b4 | ||
![]() |
157b160b9d | ||
![]() |
d0413e3ea8 | ||
![]() |
6a4f317403 | ||
![]() |
8481ab3745 | ||
![]() |
a8cef179e7 | ||
![]() |
0fd1eaff43 | ||
![]() |
d30a738960 | ||
![]() |
bfa7a5cc60 | ||
![]() |
b655eca152 | ||
![]() |
f2ff55dba2 | ||
![]() |
91aadb6044 | ||
![]() |
c5b8d13beb | ||
![]() |
dacf45cd88 | ||
![]() |
c6d0e93157 | ||
![]() |
662025a961 | ||
![]() |
07155b1fa9 | ||
![]() |
8e584cf844 | ||
![]() |
d0873631cc | ||
![]() |
dfd3fcdff6 | ||
![]() |
00016b7499 | ||
![]() |
5bb5e2dc5a | ||
![]() |
dc2e786a6f | ||
![]() |
598ae98bfe | ||
![]() |
ce3a544ecd | ||
![]() |
6ac36e8436 | ||
![]() |
5c12762cb5 | ||
![]() |
3a0c36e8db | ||
![]() |
6adc810145 | ||
![]() |
6d34f2229b | ||
![]() |
b909ff4ecb | ||
![]() |
2d52fbd8e8 | ||
![]() |
c9254b256a | ||
![]() |
7a2d09dc35 | ||
![]() |
a94346e17e | ||
![]() |
20415bb5e0 | ||
![]() |
7c0d25f9da | ||
![]() |
5e772c3625 | ||
![]() |
691e9d26d2 | ||
![]() |
f37f034b6a | ||
![]() |
88fc0fac8f | ||
![]() |
1fd23f86aa | ||
![]() |
d6f82f9edc | ||
![]() |
00b9a490bb | ||
![]() |
5259d51c04 | ||
![]() |
04aada8720 | ||
![]() |
69630e7385 | ||
![]() |
dd02958f7c | ||
![]() |
30dfdf47d4 | ||
![]() |
f48dd8c1ab | ||
![]() |
22cc2712a6 | ||
![]() |
cbb77e5794 | ||
![]() |
baf671b764 | ||
![]() |
606f00867e | ||
![]() |
2fae9dcb93 | ||
![]() |
3f509b6ff9 | ||
![]() |
c38c981cd0 | ||
![]() |
d0891e5183 | ||
![]() |
325205740b | ||
![]() |
f30ba25444 | ||
![]() |
339b6944f1 | ||
![]() |
0f68fbc8db | ||
![]() |
998bffe706 | ||
![]() |
12d4a47e3d | ||
![]() |
1171f01683 | ||
![]() |
f905704479 | ||
![]() |
58c6ef1e12 | ||
![]() |
83edf9574e | ||
![]() |
c25367221e | ||
![]() |
7ee17c7af8 | ||
![]() |
c3b313a70d | ||
![]() |
f1dc3a639c | ||
![]() |
2f401bd8da | ||
![]() |
8cb8a030be | ||
![]() |
f3f9b36e07 | ||
![]() |
0a8249d6fb | ||
![]() |
b6fce8f0bb | ||
![]() |
d51197eaa2 | ||
![]() |
d2a2643cd6 | ||
![]() |
bd17e7d824 | ||
![]() |
ed0d2be321 | ||
![]() |
9137f1594b | ||
![]() |
ef14a43930 | ||
![]() |
ee4a133655 | ||
![]() |
ece070fee1 | ||
![]() |
3d40ed5d47 | ||
![]() |
e640981cc4 | ||
![]() |
9e531b0b5b | ||
![]() |
7c1568fcb9 | ||
![]() |
09cc4251f0 | ||
![]() |
793fe251b9 | ||
![]() |
2be2050d57 | ||
![]() |
0996883a98 | ||
![]() |
b66810247e | ||
![]() |
0592cedcde | ||
![]() |
ca7853c087 | ||
![]() |
3efa77f302 | ||
![]() |
ff1b5c87aa | ||
![]() |
a8f282515f | ||
![]() |
730416418d | ||
![]() |
7e5abe7a65 | ||
![]() |
ec4d79eafc | ||
![]() |
ff90db30e6 | ||
![]() |
bd9942b426 | ||
![]() |
dfd574beeb | ||
![]() |
b359ff1b8e | ||
![]() |
0f1cf67b91 | ||
![]() |
d81dd60fef | ||
![]() |
32569842d3 | ||
![]() |
5c27cb7e9b | ||
![]() |
7459a1cdde | ||
![]() |
b160abac0d | ||
![]() |
fd6eb78f41 | ||
![]() |
8d941e5e26 | ||
![]() |
8bc76d19db | ||
![]() |
20b52a96bc | ||
![]() |
367d7244d3 | ||
![]() |
435d152423 | ||
![]() |
d3949eebfa | ||
![]() |
d1701e127e | ||
![]() |
f0c1b66b0f | ||
![]() |
699248d769 | ||
![]() |
deec5b8bfd | ||
![]() |
62f36b221e | ||
![]() |
ae0aba44dc | ||
![]() |
bd1d13d78c | ||
![]() |
ab50d0b006 | ||
![]() |
1e17dbaa91 | ||
![]() |
f66ccb04f6 | ||
![]() |
39bf6c44bc | ||
![]() |
846a180a7b | ||
![]() |
11738110dc | ||
![]() |
53d63e0f75 | ||
![]() |
deccc4fd46 | ||
![]() |
4940826011 | ||
![]() |
fec1dd3f46 | ||
![]() |
42f3ee3de5 | ||
![]() |
e357715a8c | ||
![]() |
6d0c2ec5c8 | ||
![]() |
17e8a46c7d | ||
![]() |
76dbab6a8b | ||
![]() |
b568a29fa8 | ||
![]() |
b4038821cc | ||
![]() |
6634be1f79 | ||
![]() |
5fb96c777a | ||
![]() |
181b53a55d | ||
![]() |
5951a740d2 | ||
![]() |
e3b9998879 | ||
![]() |
f52b1212cd | ||
![]() |
aded314f3c | ||
![]() |
ede1dedbbd | ||
![]() |
0751358e5b | ||
![]() |
17b92aa657 | ||
![]() |
0fcfcb85ab | ||
![]() |
ef50af03f2 | ||
![]() |
02f577347d | ||
![]() |
03b45c153b | ||
![]() |
2add675d42 | ||
![]() |
305323c9e9 | ||
![]() |
85015d9409 | ||
![]() |
b38c9e82e2 | ||
![]() |
82aa238eca | ||
![]() |
19890310fe | ||
![]() |
9bf98f908d | ||
![]() |
ad52e238ce | ||
![]() |
ca7790ff65 | ||
![]() |
cbd07696b5 | ||
![]() |
37360edbc1 | ||
![]() |
df016ddd0d | ||
![]() |
b48f6d750f | ||
![]() |
83006eeb65 | ||
![]() |
e451f44ced | ||
![]() |
6dc82b6cef | ||
![]() |
43ade86796 | ||
![]() |
6bcf44aee8 | ||
![]() |
0d16bd0144 | ||
![]() |
9dca1e1d9f | ||
![]() |
7f96d89ec4 | ||
![]() |
04a22f8283 | ||
![]() |
ece7dc29e7 | ||
![]() |
cdd8e6fd4e | ||
![]() |
fbaab71d78 | ||
![]() |
83aad5262a | ||
![]() |
3c72b96042 | ||
![]() |
35ddc896fa | ||
![]() |
ba6794fb99 | ||
![]() |
7960090409 | ||
![]() |
366c31259f | ||
![]() |
9b109a7d14 | ||
![]() |
03d37fe830 | ||
![]() |
433bf690e3 | ||
![]() |
c820badb40 | ||
![]() |
98384789d4 | ||
![]() |
75e0ed38eb | ||
![]() |
8535213ad9 | ||
![]() |
416ce66b51 | ||
![]() |
cb73d0cd39 | ||
![]() |
f8f76fcb94 | ||
![]() |
149d6694d6 | ||
![]() |
15415bab10 | ||
![]() |
3b62ff093a | ||
![]() |
a218d2f6ff | ||
![]() |
6e0faa930a | ||
![]() |
d6c9538859 | ||
![]() |
dee471e9e9 | ||
![]() |
e3eae53cb9 | ||
![]() |
6986949d84 | ||
![]() |
19a65eaaac | ||
![]() |
cefbed614f | ||
![]() |
37db4070ce | ||
![]() |
da3e197534 | ||
![]() |
0e61ea7723 | ||
![]() |
f855b1a2b3 | ||
![]() |
bc16ad1f13 | ||
![]() |
1b8cd10142 | ||
![]() |
83c80c570c | ||
![]() |
4c5cd02ab7 | ||
![]() |
7d589bd6e1 | ||
![]() |
1bf3b83ef3 | ||
![]() |
b61b6f46cd | ||
![]() |
ac339d411c | ||
![]() |
3f17f871fa | ||
![]() |
e454daf727 | ||
![]() |
732e527401 | ||
![]() |
b44e6cd5dc | ||
![]() |
2d9556f5f3 | ||
![]() |
e82f72a9d3 | ||
![]() |
ce2d589a28 | ||
![]() |
750bf0e79a | ||
![]() |
4dc6c93cdb | ||
![]() |
f7e9507bee | ||
![]() |
e8d8cc4f55 | ||
![]() |
c20c982ad0 | ||
![]() |
962bdc7fa5 | ||
![]() |
a5e561c81d | ||
![]() |
c4ebafe777 | ||
![]() |
7ed715b371 | ||
![]() |
161e7b3fd7 | ||
![]() |
42eaa13402 | ||
![]() |
17c26c9fa9 | ||
![]() |
318240c14c | ||
![]() |
34bdf2fc10 | ||
![]() |
d97fa99ec5 | ||
![]() |
a554b22968 | ||
![]() |
9621b4b9a1 | ||
![]() |
3611e874ca | ||
![]() |
fbf29667d4 | ||
![]() |
c13dd132ee | ||
![]() |
3524d1a055 | ||
![]() |
a8c567d877 | ||
![]() |
80135342c2 | ||
![]() |
c2b13fdbdf | ||
![]() |
2797a60d4f | ||
![]() |
0592c8b0e2 | ||
![]() |
2b685ac343 | ||
![]() |
13122fc2b1 | ||
![]() |
c901707670 | ||
![]() |
27d3676ba5 | ||
![]() |
52459bf348 | ||
![]() |
6cfa73a284 | ||
![]() |
7b26935462 | ||
![]() |
c9cd810c9f | ||
![]() |
1715e2e09d | ||
![]() |
b69c0daadb | ||
![]() |
56d2978bc8 | ||
![]() |
1ef109e171 | ||
![]() |
08ab9dedf7 | ||
![]() |
3d90366af2 | ||
![]() |
c74c9ff161 | ||
![]() |
27a31e731f | ||
![]() |
562e2627c2 | ||
![]() |
babd976533 | ||
![]() |
748815b6ce | ||
![]() |
88252e0ae6 | ||
![]() |
c0bf69b4bf | ||
![]() |
b6b10e753f | ||
![]() |
4a45089b95 | ||
![]() |
3b9bcb356b | ||
![]() |
e10ddb343c | ||
![]() |
e8cd25ddf2 | ||
![]() |
624c314335 | ||
![]() |
b33094207c | ||
![]() |
7083a5c9b6 | ||
![]() |
db131d4971 | ||
![]() |
74d6ab0555 | ||
![]() |
66881eb89f | ||
![]() |
ad60f4894b | ||
![]() |
8d21c950a3 | ||
![]() |
ea8ec23cbe | ||
![]() |
f06e8b47be | ||
![]() |
7edeaa3407 | ||
![]() |
7a7e30e1ff | ||
![]() |
78dc75a4f1 | ||
![]() |
a5078b8517 | ||
![]() |
77876bd663 | ||
![]() |
a0697b81a1 | ||
![]() |
88b903ba39 | ||
![]() |
116edce3dc | ||
![]() |
7130d93616 | ||
![]() |
11054daebe | ||
![]() |
7926ddd008 | ||
![]() |
93f2316711 | ||
![]() |
fd3688a9c7 | ||
![]() |
a63dd9bccd | ||
![]() |
f54b223adf | ||
![]() |
9ddcf7b1fe | ||
![]() |
07c635d822 | ||
![]() |
6ed8977548 | ||
![]() |
e50cccc78a | ||
![]() |
feeb7107d5 | ||
![]() |
f52de322d3 | ||
![]() |
2f3e046130 | ||
![]() |
edbdbb7f07 | ||
![]() |
4bb5785d89 | ||
![]() |
36c6ee73fe | ||
![]() |
924f946e46 | ||
![]() |
d22e25064b | ||
![]() |
12d51d3c73 | ||
![]() |
5fa1fbafed | ||
![]() |
d36ab05bf1 | ||
![]() |
fb85c8ca54 | ||
![]() |
b2a2a9d6c7 | ||
![]() |
e2239d36c9 | ||
![]() |
6620236bc3 | ||
![]() |
02df2a8bbd | ||
![]() |
89513e469a | ||
![]() |
f5466426df | ||
![]() |
2631a4c35b | ||
![]() |
ef9338f5af | ||
![]() |
19afb035ff | ||
![]() |
a7751f210b | ||
![]() |
3bec28ffef | ||
![]() |
81b3fdb423 | ||
![]() |
30f520f6f0 | ||
![]() |
0de1da5943 | ||
![]() |
e39fb51dec | ||
![]() |
621aa0cf61 | ||
![]() |
367ac28a94 | ||
![]() |
99577a57e6 | ||
![]() |
65bc644d03 | ||
![]() |
01b9d4d848 | ||
![]() |
daadd206dd | ||
![]() |
60b2315028 | ||
![]() |
19d17c8c81 | ||
![]() |
24410849b7 | ||
![]() |
e0b3b27b8a | ||
![]() |
170899bd71 | ||
![]() |
2031c3146f | ||
![]() |
dafc7edb59 | ||
![]() |
7fbfdb3cb8 | ||
![]() |
e0a0d129df | ||
![]() |
2d76363da5 | ||
![]() |
54bfa4679c | ||
![]() |
3c708d7672 | ||
![]() |
b4fb6086b3 | ||
![]() |
ab44a65fe3 | ||
![]() |
95596b39fd | ||
![]() |
cf2466c8c1 | ||
![]() |
6b123675c4 | ||
![]() |
ddcae2d4aa | ||
![]() |
731db8fb8f | ||
![]() |
cb0c5c2587 | ||
![]() |
1643b4d108 | ||
![]() |
acd1fb9e3e | ||
![]() |
ddde477770 | ||
![]() |
3edbb8dc41 | ||
![]() |
581c2591ae | ||
![]() |
d49359e26a | ||
![]() |
e79eab711a | ||
![]() |
5b7cd9ce64 | ||
![]() |
3cb96091ec | ||
![]() |
fdd2cc972e | ||
![]() |
61243ad34b | ||
![]() |
5f4c439f57 | ||
![]() |
1f963ec5aa | ||
![]() |
bcbf0061ff | ||
![]() |
57dce4ec38 | ||
![]() |
0dbf909ca6 | ||
![]() |
47ac5ed522 | ||
![]() |
ec7aaa18ab | ||
![]() |
bee965df06 | ||
![]() |
543cad5497 | ||
![]() |
d9c45a76fe | ||
![]() |
417a42b0b3 | ||
![]() |
8ac3114f9a | ||
![]() |
740d932848 | ||
![]() |
e645c8e007 | ||
![]() |
9ee367d9e9 | ||
![]() |
8410788e99 | ||
![]() |
12235acd75 | ||
![]() |
ba5cffac55 | ||
![]() |
64ab6580dc | ||
![]() |
0a3295aa5c | ||
![]() |
ffa98a138b | ||
![]() |
5e71d95cb1 | ||
![]() |
9fd13aad11 | ||
![]() |
ebef38e408 | ||
![]() |
b6592c67d1 | ||
![]() |
d547680116 | ||
![]() |
bc5aa1141a | ||
![]() |
ea7d1aabba | ||
![]() |
760d65b214 | ||
![]() |
ceab294840 | ||
![]() |
abc40f2581 | ||
![]() |
dc738e9be7 | ||
![]() |
53d39a1373 | ||
![]() |
cee52e9cfd | ||
![]() |
9c6193b9b5 | ||
![]() |
e4a79b12eb | ||
![]() |
5eac767758 | ||
![]() |
b6ad287ef2 | ||
![]() |
f4991b46f8 | ||
![]() |
ecc7b93dc0 | ||
![]() |
ff56262c6e | ||
![]() |
da1b7c2e28 | ||
![]() |
76bbd838f7 | ||
![]() |
a8e81a255d | ||
![]() |
fee48e555e | ||
![]() |
59b52f3879 | ||
![]() |
d6731b17a4 | ||
![]() |
3f05f74ecb | ||
![]() |
e3ec292528 | ||
![]() |
63260119fb | ||
![]() |
ffd637cc0c | ||
![]() |
be2408b366 | ||
![]() |
6e519e0071 | ||
![]() |
f3e0ced1cd | ||
![]() |
368c07cc34 | ||
![]() |
d999575832 | ||
![]() |
06bc9bb4dc | ||
![]() |
161991df1f | ||
![]() |
e3e03ec12f | ||
![]() |
c85df9c691 | ||
![]() |
7953d131ae | ||
![]() |
c6f0abf732 | ||
![]() |
49f70b9563 | ||
![]() |
369299315f | ||
![]() |
9b99ba81e5 | ||
![]() |
499866bf94 | ||
![]() |
420bcd7aa0 | ||
![]() |
43c2761308 | ||
![]() |
b1ec56de29 | ||
![]() |
45c43d7cf5 | ||
![]() |
037f3761e7 | ||
![]() |
739a267462 | ||
![]() |
ba3fbc99ba | ||
![]() |
cd9f6b074e | ||
![]() |
964bcc0733 | ||
![]() |
4f79ca1bf0 | ||
![]() |
bc52fc1e79 | ||
![]() |
fee3418e60 | ||
![]() |
2a5ab77637 | ||
![]() |
6abc0ce921 | ||
![]() |
7888059c9f | ||
![]() |
97161310a5 | ||
![]() |
2651bc18cd | ||
![]() |
87e2810725 | ||
![]() |
007fa75294 | ||
![]() |
94a2b6bb88 | ||
![]() |
e5fe323aca | ||
![]() |
4523c9b06d | ||
![]() |
5ad391977e | ||
![]() |
25a7c4ee81 | ||
![]() |
87144cd572 | ||
![]() |
69560c8bde | ||
![]() |
aaedd24f37 | ||
![]() |
3cb6d43fac | ||
![]() |
68248cc274 | ||
![]() |
047c2408d2 | ||
![]() |
91982c4f7e | ||
![]() |
4e5512e35d | ||
![]() |
1f4ce6ff1e | ||
![]() |
c497e83a54 | ||
![]() |
93f94a7afb | ||
![]() |
6c0978498d | ||
![]() |
370276a7b6 | ||
![]() |
f4187d6b83 | ||
![]() |
c4d442450b | ||
![]() |
82432a78b7 | ||
![]() |
ebdf36e0b9 | ||
![]() |
65825040a3 | ||
![]() |
253061ee5f | ||
![]() |
a46c37018f | ||
![]() |
2e81c94d8e | ||
![]() |
a04fa105ef | ||
![]() |
ad3f6fc551 | ||
![]() |
53045de1c2 | ||
![]() |
410cea71f1 | ||
![]() |
cc27c94e03 | ||
![]() |
a9d95b89e1 | ||
![]() |
4eb3e98076 | ||
![]() |
664e04836d | ||
![]() |
a1b21a87a1 | ||
![]() |
e718d09c79 | ||
![]() |
c97aac6c94 | ||
![]() |
9c9220979e | ||
![]() |
42bc372d6e | ||
![]() |
47c1985c26 | ||
![]() |
9e31873520 | ||
![]() |
8665a24560 | ||
![]() |
2b842468ad | ||
![]() |
8cddf87f9e | ||
![]() |
573fdae37f | ||
![]() |
9b5c6bea56 | ||
![]() |
40cb5102b0 | ||
![]() |
95343b6094 | ||
![]() |
e15b2627fc | ||
![]() |
02caeb9f87 | ||
![]() |
4383b883c0 | ||
![]() |
bcc26dd86a | ||
![]() |
1bc9efd529 | ||
![]() |
11624d4759 | ||
![]() |
94e2a500c7 | ||
![]() |
552638d000 | ||
![]() |
8163afce79 | ||
![]() |
2a36a1b980 | ||
![]() |
d8123d2497 | ||
![]() |
86268b99fb | ||
![]() |
b4d4adb75b | ||
![]() |
3c01dbed7d | ||
![]() |
2eada219cd | ||
![]() |
8dd367efa9 | ||
![]() |
66dc8c772b | ||
![]() |
68cdd9b94c | ||
![]() |
65c211bb6d | ||
![]() |
60ad38261b | ||
![]() |
c02100ee6f | ||
![]() |
8669c29e3d | ||
![]() |
10783fec49 | ||
![]() |
3bed4611f1 | ||
![]() |
f0e836e5b6 | ||
![]() |
a1ae5b67d8 | ||
![]() |
53f7190d42 | ||
![]() |
3846a13805 | ||
![]() |
7c60753ab0 | ||
![]() |
df40b96b44 | ||
![]() |
faf583451f | ||
![]() |
be7b858cbd | ||
![]() |
a6a0e4d1de | ||
![]() |
14faf0b2f6 | ||
![]() |
bdfe4a961a | ||
![]() |
1bc8d94312 | ||
![]() |
7e9f913ff6 | ||
![]() |
0882e4a454 | ||
![]() |
699bd3748a | ||
![]() |
2ca59f0abe | ||
![]() |
64b1b8e15c | ||
![]() |
b6f799e641 | ||
![]() |
c461c9e700 | ||
![]() |
9df415b3f2 | ||
![]() |
f7c5e02a35 | ||
![]() |
656e6a2a89 | ||
![]() |
afefa3ec02 | ||
![]() |
8c45dab9b8 | ||
![]() |
0d6dd1ed0f | ||
![]() |
911d6fdfa7 | ||
![]() |
0cf759acad | ||
![]() |
7c57c8c2da | ||
![]() |
89c04acdff | ||
![]() |
05d5f13f0e | ||
![]() |
4682af81fb | ||
![]() |
e649a1eb98 | ||
![]() |
01482d791b | ||
![]() |
6e2e297aeb | ||
![]() |
5577ef081f | ||
![]() |
2d5d3bdaf4 | ||
![]() |
3376e85be6 | ||
![]() |
7a1215d581 | ||
![]() |
a94297ac93 | ||
![]() |
37325c70ba | ||
![]() |
3c46a33992 | ||
![]() |
ed1897db71 | ||
![]() |
dfbebb63ff | ||
![]() |
e68f80b44a | ||
![]() |
a67a768e89 | ||
![]() |
43f05c18d6 | ||
![]() |
3b076c28c2 | ||
![]() |
cbf12e3f90 | ||
![]() |
17b745434c | ||
![]() |
37011c2fda | ||
![]() |
fa95a041dd | ||
![]() |
0879d7a2d1 | ||
![]() |
653c2274e1 | ||
![]() |
061fb15a80 | ||
![]() |
3246fcce22 | ||
![]() |
f2a3797b46 | ||
![]() |
b80080ac52 | ||
![]() |
b36b63599b | ||
![]() |
5d8c0e43c2 | ||
![]() |
7845995dfd | ||
![]() |
afe88d6e3a | ||
![]() |
560ee0104d | ||
![]() |
dc8b625d55 | ||
![]() |
162c0147d2 | ||
![]() |
ef54cd6fb3 | ||
![]() |
c2465a46a8 | ||
![]() |
24d3a9cdd5 | ||
![]() |
5e82eaed88 | ||
![]() |
1d45b0b351 | ||
![]() |
ba119e4f96 | ||
![]() |
75c2feb387 | ||
![]() |
da637d3c8f | ||
![]() |
bc078fcc88 | ||
![]() |
93cd973e59 | ||
![]() |
5f9d477863 | ||
![]() |
ca693240b1 | ||
![]() |
468febc434 | ||
![]() |
4b81c88794 | ||
![]() |
2ac28b93f3 | ||
![]() |
3e7ed982d4 | ||
![]() |
d8d410802f | ||
![]() |
ca7bad8909 | ||
![]() |
7b2b5bfa71 | ||
![]() |
d2c3cdcf04 | ||
![]() |
7c8142174e | ||
![]() |
efe3f96223 | ||
![]() |
de244d6873 | ||
![]() |
53bf3cd2e6 | ||
![]() |
f59871a189 | ||
![]() |
2dda7608bb | ||
![]() |
10db9faff9 | ||
![]() |
90bff605fa | ||
![]() |
f512df44c1 | ||
![]() |
4e8ce28948 | ||
![]() |
16057cdef7 | ||
![]() |
da36f25fd0 | ||
![]() |
0e9c8a4ddd | ||
![]() |
ccc9b90625 | ||
![]() |
d992a959f2 | ||
![]() |
358d0521a1 | ||
![]() |
691ed6a4c7 | ||
![]() |
78e1782084 | ||
![]() |
0d5ae9a399 | ||
![]() |
d343a658ec | ||
![]() |
0bd3cff13b | ||
![]() |
5b71271b3c | ||
![]() |
0a4d658c7f | ||
![]() |
b75929a846 | ||
![]() |
e33cd442cd | ||
![]() |
91539de3ff | ||
![]() |
bc0206de9d | ||
![]() |
f536494a38 | ||
![]() |
f2030d301f | ||
![]() |
d890217447 | ||
![]() |
cafe0917c7 | ||
![]() |
ebf4e43ced | ||
![]() |
a1afade9ba | ||
![]() |
b86b2d6602 | ||
![]() |
12abbc59d6 | ||
![]() |
ec91466fe4 | ||
![]() |
0044f73d7a | ||
![]() |
65e0ec7826 | ||
![]() |
a5016afdd4 | ||
![]() |
6808ba1b3b | ||
![]() |
41f58c7692 | ||
![]() |
c6234bf548 | ||
![]() |
d995761419 | ||
![]() |
d749cf2e6b | ||
![]() |
164e9b7eb8 | ||
![]() |
d43f9189a6 | ||
![]() |
a292f272e9 | ||
![]() |
58c32857d3 | ||
![]() |
35bd1de5ba | ||
![]() |
51fd18f56d | ||
![]() |
162e275ef3 | ||
![]() |
44a2b54773 | ||
![]() |
d17828931b | ||
![]() |
cef77fba01 | ||
![]() |
e724fe3da6 | ||
![]() |
045aac8933 | ||
![]() |
2e5d082ef3 | ||
![]() |
923d07b1a4 | ||
![]() |
c424c4b7ef | ||
![]() |
b1cc64d4fa | ||
![]() |
0abd0627df | ||
![]() |
dccfc3b84f | ||
![]() |
deb3536cb2 | ||
![]() |
1d8f1b24a9 | ||
![]() |
7cabf8e5f5 | ||
![]() |
ffee9c8065 | ||
![]() |
00112eb7bc | ||
![]() |
9bbe75d64e | ||
![]() |
95fe62e141 | ||
![]() |
1c9ba11e07 | ||
![]() |
4bae3993da | ||
![]() |
d03865d1a5 | ||
![]() |
83481afee1 | ||
![]() |
b1a2b0cda2 | ||
![]() |
0dfba6e8d9 | ||
![]() |
e4afe50509 | ||
![]() |
006569391f | ||
![]() |
f4c3bb0617 | ||
![]() |
3e07d4eddb | ||
![]() |
4004048add | ||
![]() |
cbf26e09a4 | ||
![]() |
20b4b503f0 | ||
![]() |
08f573aaa5 | ||
![]() |
3dd3786055 | ||
![]() |
bfecee9650 | ||
![]() |
395c16300d | ||
![]() |
ff19cdb773 | ||
![]() |
5627b66a6e | ||
![]() |
ebdfbfe96c | ||
![]() |
1a009c7fd1 | ||
![]() |
c14f986fae | ||
![]() |
ee5b9986ad | ||
![]() |
190f217b13 | ||
![]() |
e78662b924 | ||
![]() |
5a2e395352 | ||
![]() |
8de15af7b4 | ||
![]() |
21178613de | ||
![]() |
340be7f86d | ||
![]() |
0ff4acd59c | ||
![]() |
28dd43f8ae | ||
![]() |
56d24cbf6d | ||
![]() |
e433bec17f | ||
![]() |
3189467a36 | ||
![]() |
63536d249f | ||
![]() |
3e90f3032c | ||
![]() |
5cff849e59 | ||
![]() |
06cc7527a9 | ||
![]() |
d78dc2388c | ||
![]() |
583912db9c | ||
![]() |
5792cf042e | ||
![]() |
4524dca3ed | ||
![]() |
304a569c7e | ||
![]() |
10c200dc24 | ||
![]() |
0b8617d09f | ||
![]() |
e7026dfd6e | ||
![]() |
b82d75b79e | ||
![]() |
ac30091258 | ||
![]() |
de58bdcc9f | ||
![]() |
329e5f8f91 | ||
![]() |
4a16171f96 | ||
![]() |
f0212c2aa4 | ||
![]() |
7401cf2399 | ||
![]() |
493d16519a | ||
![]() |
a87675d3cc | ||
![]() |
0bef16bb17 | ||
![]() |
e0078f388e | ||
![]() |
cf6e66c453 | ||
![]() |
34fa53afcc | ||
![]() |
663bf05fd7 | ||
![]() |
f512af2563 | ||
![]() |
7e7d70aa5b | ||
![]() |
dd1cf4d2ce | ||
![]() |
e627f4e935 | ||
![]() |
c6445898ce | ||
![]() |
f1ddd0e6f7 | ||
![]() |
db369a5b7f | ||
![]() |
87cd618998 | ||
![]() |
338e4004d4 | ||
![]() |
675f21e23a | ||
![]() |
4d2d11193f | ||
![]() |
69aaf1f8e6 | ||
![]() |
a10970d7c9 | ||
![]() |
6eecb6780e | ||
![]() |
80627e4989 | ||
![]() |
9e987fdebc | ||
![]() |
e6292c719d | ||
![]() |
7c74bf2566 | ||
![]() |
2c91e7853c | ||
![]() |
1e7f196e5c | ||
![]() |
f91f4f0053 | ||
![]() |
8b2622a234 | ||
![]() |
a2ddb12eb3 | ||
![]() |
985bd6d9bd | ||
![]() |
ec3c15e4a7 | ||
![]() |
188b202836 | ||
![]() |
01e607a14e | ||
![]() |
5b164b72dc | ||
![]() |
dcf65febba | ||
![]() |
56a2d4e64d | ||
![]() |
ef214fb80a | ||
![]() |
93f418ac0b | ||
![]() |
689af4ff87 | ||
![]() |
4ab0927de8 | ||
![]() |
014e6fc909 | ||
![]() |
6832575643 | ||
![]() |
07ad2d97b1 | ||
![]() |
039f1a522e | ||
![]() |
24e2f84231 | ||
![]() |
e0c0033852 | ||
![]() |
c50e9d48bf | ||
![]() |
173eaabddf | ||
![]() |
a748b70da1 | ||
![]() |
8eabe5dd41 | ||
![]() |
114415b5e1 | ||
![]() |
ba55b5a6db | ||
![]() |
7533f2a8ab | ||
![]() |
543a8a1712 | ||
![]() |
9b23ff597c | ||
![]() |
b2ce1edd5a | ||
![]() |
a0235b7da4 | ||
![]() |
87e2300855 | ||
![]() |
34bc6a6457 | ||
![]() |
273076e7f4 | ||
![]() |
b29b311e92 | ||
![]() |
5a9e82c4b0 | ||
![]() |
6218791708 | ||
![]() |
0e43f452d2 | ||
![]() |
0695bb097d | ||
![]() |
294c79a271 | ||
![]() |
e351e132f5 | ||
![]() |
258215a3ae | ||
![]() |
08ddfc100f | ||
![]() |
8ab6cba521 | ||
![]() |
eb16de7395 | ||
![]() |
dde0498ed3 | ||
![]() |
75c8570913 | ||
![]() |
e36099a342 | ||
![]() |
2f2329ba44 | ||
![]() |
6c8b184d2c | ||
![]() |
32878bd016 | ||
![]() |
12d13988c4 | ||
![]() |
9e4d921488 | ||
![]() |
edc1884c4e | ||
![]() |
a2d1bd2c67 | ||
![]() |
bb68a2405b | ||
![]() |
42ac4172ff | ||
![]() |
998921ae63 | ||
![]() |
26ae6084ea | ||
![]() |
76142e9699 | ||
![]() |
5e692acfbb | ||
![]() |
a67b8ab84d | ||
![]() |
4cf55ad8e2 | ||
![]() |
c1132e6897 | ||
![]() |
d6104f2eb2 | ||
![]() |
b0e0abe385 | ||
![]() |
4916e1cd1d | ||
![]() |
cd87f3e6f4 | ||
![]() |
18f4ab2644 | ||
![]() |
0bd3be94ec | ||
![]() |
25bb515afc | ||
![]() |
7ab6961ee1 | ||
![]() |
ae24cf3bb2 | ||
![]() |
2e494477a6 | ||
![]() |
80b72c75d9 | ||
![]() |
9494bb7f5f | ||
![]() |
86a741b6e6 | ||
![]() |
f738275d21 | ||
![]() |
e297e02800 | ||
![]() |
b2e05afff2 | ||
![]() |
05fc35fc3d | ||
![]() |
c809494c98 | ||
![]() |
ef82c5c691 | ||
![]() |
c0e2a75715 | ||
![]() |
01ddd00bc5 | ||
![]() |
d150f01a2c | ||
![]() |
f9e159deaf | ||
![]() |
381b00157e | ||
![]() |
800f33e7be | ||
![]() |
b8218876be | ||
![]() |
5669f4c161 | ||
![]() |
c492b30adb | ||
![]() |
eb48722126 | ||
![]() |
8e881b60f0 | ||
![]() |
0260d824a6 | ||
![]() |
0877a7dec7 | ||
![]() |
4c7919ad69 | ||
![]() |
4e997124b3 | ||
![]() |
8b040f5c95 | ||
![]() |
96156805ed | ||
![]() |
b8d48d7e62 | ||
![]() |
8ca12806ca | ||
![]() |
de811b7018 | ||
![]() |
7bf7365f6c | ||
![]() |
1daffd92fd | ||
![]() |
74986982a0 | ||
![]() |
aa807d25ed | ||
![]() |
cd28869649 | ||
![]() |
ae97692883 | ||
![]() |
e8e778c6d4 | ||
![]() |
5c552a0d71 | ||
![]() |
0f5dfea9de | ||
![]() |
e6cdb6a7a2 | ||
![]() |
1d25936f31 | ||
![]() |
1049673413 | ||
![]() |
c3109f808c | ||
![]() |
a943ac1308 | ||
![]() |
96319e795c | ||
![]() |
5a8016de87 | ||
![]() |
bc350644bd | ||
![]() |
c793500ad2 | ||
![]() |
1b2134c49e | ||
![]() |
86a5b46c68 | ||
![]() |
f83d4a58dd | ||
![]() |
a5f241d5bd | ||
![]() |
661f7baa21 | ||
![]() |
7b063a19dc | ||
![]() |
0320d94ea6 | ||
![]() |
a7b7a45b23 | ||
![]() |
89e317a6bb | ||
![]() |
5a209caed3 | ||
![]() |
288b1a0562 | ||
![]() |
d35b09b18f | ||
![]() |
e8eb3125a5 | ||
![]() |
8109445fdd | ||
![]() |
f63a7cb6c0 | ||
![]() |
7fc5297f60 | ||
![]() |
00ff76a0b9 | ||
![]() |
b8df419bad | ||
![]() |
faf103152a | ||
![]() |
65855e23d9 | ||
![]() |
6c28613def | ||
![]() |
56480dc1ef | ||
![]() |
8e1c15291d | ||
![]() |
a1e52c51b1 | ||
![]() |
8cc834633e | ||
![]() |
7d65c05994 | ||
![]() |
d74021af47 | ||
![]() |
46fe06e779 | ||
![]() |
fbea51372f | ||
![]() |
fa5ec8d019 | ||
![]() |
11c425a7eb | ||
![]() |
0d352f3d8a | ||
![]() |
6ccff71408 | ||
![]() |
41fea2a531 | ||
![]() |
3d6dad7e7e | ||
![]() |
4efc584816 | ||
![]() |
10ab70080a | ||
![]() |
bddde74c06 | ||
![]() |
29de723267 | ||
![]() |
354a9240f0 | ||
![]() |
5ae4f47e96 | ||
![]() |
26424488a5 | ||
![]() |
334095252c | ||
![]() |
1c85f774eb | ||
![]() |
bbf0fc8324 | ||
![]() |
b143e11e0e | ||
![]() |
927f56ab9f | ||
![]() |
2181379475 | ||
![]() |
45798d6d14 | ||
![]() |
f6d5e96dbf | ||
![]() |
e18aa56427 | ||
![]() |
f3a1c1de0a | ||
![]() |
0ccf543ec1 | ||
![]() |
1f1a708388 | ||
![]() |
58c0d97b5f | ||
![]() |
abef002af8 | ||
![]() |
adf2bc078c | ||
![]() |
b33f4e2dc6 | ||
![]() |
9cab5da74c | ||
![]() |
189b9c6648 | ||
![]() |
1823bd0305 | ||
![]() |
8fd12f001b | ||
![]() |
fc40567794 | ||
![]() |
de121008c1 | ||
![]() |
2fbfbf614b | ||
![]() |
1181620f33 | ||
![]() |
c527b1ca5d | ||
![]() |
181a504a14 | ||
![]() |
5d940bcb86 | ||
![]() |
dcfe26c9c0 | ||
![]() |
5d94c68d66 | ||
![]() |
a476bc9885 | ||
![]() |
dc759a3e56 | ||
![]() |
4818c08fe2 | ||
![]() |
3bc75ae931 | ||
![]() |
a94b61ef91 | ||
![]() |
e51021c573 | ||
![]() |
19115fb828 | ||
![]() |
16ef432228 | ||
![]() |
4449bc5292 | ||
![]() |
50f0c05e69 | ||
![]() |
6b26fc753e | ||
![]() |
ebee204ca0 | ||
![]() |
1a3567c5d0 | ||
![]() |
4fa6fa2001 | ||
![]() |
92aa16c556 | ||
![]() |
a3853af47a | ||
![]() |
f26f7b8d3f | ||
![]() |
f4aa02cc19 | ||
![]() |
da2492413f | ||
![]() |
3876b00088 | ||
![]() |
b1dfee2cf5 | ||
![]() |
13c2c582ad | ||
![]() |
f892a821f5 | ||
![]() |
bb3ba2d572 | ||
![]() |
9ee2e776fa | ||
![]() |
fd61ca20b0 | ||
![]() |
f9add57ed4 | ||
![]() |
e1b341788d | ||
![]() |
04c8b089a5 | ||
![]() |
9971482506 | ||
![]() |
955d9e6ec2 | ||
![]() |
fe2e32c84f | ||
![]() |
c6e53d0ea8 | ||
![]() |
436b10a87b | ||
![]() |
a2d5754e4b | ||
![]() |
3d28d8cee2 | ||
![]() |
11d8095cdd | ||
![]() |
a4052a9fe5 | ||
![]() |
6e6ee93282 | ||
![]() |
85de881181 | ||
![]() |
3712a8ab80 | ||
![]() |
4ee7240ef3 | ||
![]() |
df8126de73 | ||
![]() |
2eddbe3d03 | ||
![]() |
46dad7b58d | ||
![]() |
eb5e6d19fa | ||
![]() |
5afeb6e081 | ||
![]() |
17944882f4 | ||
![]() |
b24bb3eb18 | ||
![]() |
98d8118fb2 | ||
![]() |
3e1b680e4c | ||
![]() |
b4e7e51e63 | ||
![]() |
2a41a9d3ff | ||
![]() |
09b0068d16 | ||
![]() |
f9457be109 | ||
![]() |
e9291fe9d1 | ||
![]() |
20912c12e7 | ||
![]() |
7ddba4fc59 | ||
![]() |
7ad8b8298d | ||
![]() |
3fb24b4bf5 | ||
![]() |
ab93cae4c0 | ||
![]() |
8d01cc4807 | ||
![]() |
1e21a62851 | ||
![]() |
c664bd63f6 | ||
![]() |
dada764d2c | ||
![]() |
762afb8f43 | ||
![]() |
f009897eca | ||
![]() |
fa61e9da29 | ||
![]() |
0ff037997f | ||
![]() |
e8c2cfa5b5 | ||
![]() |
fb214b64ca | ||
![]() |
222dc2f7c9 | ||
![]() |
f94a946418 | ||
![]() |
b3ee2de079 | ||
![]() |
515d8c04ad | ||
![]() |
49c65cf9c6 | ||
![]() |
211fcd64c7 | ||
![]() |
5075e4eee1 | ||
![]() |
7bfe8e4f5b | ||
![]() |
8e0c2b256e | ||
![]() |
d66f5f6bad | ||
![]() |
fd9c8c1f0d | ||
![]() |
3a3b788c65 | ||
![]() |
b134db48b3 | ||
![]() |
f110a261b9 | ||
![]() |
b72b66781a | ||
![]() |
9b3a649f17 | ||
![]() |
d83ffd8984 | ||
![]() |
175c85d69a | ||
![]() |
3aa7f753b3 | ||
![]() |
861ee0485d | ||
![]() |
03e756dd27 | ||
![]() |
5d0984998d | ||
![]() |
3b695040d1 | ||
![]() |
40bf7a0f41 | ||
![]() |
cbdf2c2c71 | ||
![]() |
bbe3f07ec6 | ||
![]() |
35281c037c | ||
![]() |
e0eb247028 | ||
![]() |
a7ecc2af4b | ||
![]() |
f2d1f7b00f | ||
![]() |
89c2ae2208 | ||
![]() |
0df35379ef | ||
![]() |
138fa45820 | ||
![]() |
58cfb8bba4 | ||
![]() |
ed761d1767 | ||
![]() |
babe1dd1eb | ||
![]() |
cbd418b8de | ||
![]() |
9c5b0d4138 | ||
![]() |
94c21a6363 | ||
![]() |
d1a5e2e8e0 | ||
![]() |
17179abf5a | ||
![]() |
61f717daa3 | ||
![]() |
c70419bd0b | ||
![]() |
4eed27e178 | ||
![]() |
8e2ba4a8ea | ||
![]() |
700f25abc3 | ||
![]() |
4596ada801 | ||
![]() |
a8df97dc1a | ||
![]() |
4e0203ca68 | ||
![]() |
8413e10091 | ||
![]() |
7aaf5bd29f | ||
![]() |
5afda72b84 | ||
![]() |
7a6ffb1032 | ||
![]() |
fd51c7a955 | ||
![]() |
b91b0d39dd | ||
![]() |
7fc9026ca6 | ||
![]() |
f4a0ec43a6 | ||
![]() |
46e5a042ae | ||
![]() |
7309c06be8 | ||
![]() |
c71b717a54 | ||
![]() |
da8e54ed51 | ||
![]() |
b70c11e7a7 | ||
![]() |
e8c342e162 | ||
![]() |
f7975cbbc4 | ||
![]() |
098e293c82 | ||
![]() |
eb3f50c9f0 | ||
![]() |
78a0b5e6c9 | ||
![]() |
055bd22138 | ||
![]() |
8dfff83447 | ||
![]() |
de3a19c4f0 | ||
![]() |
2a33c05378 | ||
![]() |
bbb4d10718 | ||
![]() |
68dfaaf767 | ||
![]() |
0bb998c465 | ||
![]() |
ec9b525a3c | ||
![]() |
88ed7501a7 | ||
![]() |
c73aebadcb | ||
![]() |
40c4ca305e | ||
![]() |
7b3abe330e | ||
![]() |
0d96c3529d | ||
![]() |
62452b1d21 | ||
![]() |
c5f005afef | ||
![]() |
4a45b6e76d | ||
![]() |
a3cfbb6722 | ||
![]() |
dc8ba5239d | ||
![]() |
b53a50cd54 | ||
![]() |
9822d614e2 | ||
![]() |
ca20c735f7 | ||
![]() |
d3dc018260 | ||
![]() |
28a2a3816a | ||
![]() |
5461308d30 | ||
![]() |
b2f469ad76 | ||
![]() |
8ea75e6748 | ||
![]() |
09a4d6d030 | ||
![]() |
abbc608ee4 | ||
![]() |
9634ec8e31 | ||
![]() |
84a0827aee | ||
![]() |
1fbcf4d9b9 | ||
![]() |
80f8256422 | ||
![]() |
57864f2be6 | ||
![]() |
f4bc68d396 | ||
![]() |
926eec3c65 | ||
![]() |
abc6bbe7e0 | ||
![]() |
acdfd1ccc4 | ||
![]() |
315a13e1ce | ||
![]() |
aab6a00e4c | ||
![]() |
a4e6d9ed9a | ||
![]() |
e16dbcb671 | ||
![]() |
e89697fab0 | ||
![]() |
c52782aa3f | ||
![]() |
7060f22024 | ||
![]() |
d1931f249c | ||
![]() |
bf1a542afb | ||
![]() |
ebb6d348a3 | ||
![]() |
f667bd9066 | ||
![]() |
ff2eba5b9f | ||
![]() |
3eb0021207 | ||
![]() |
6379f5cd5e | ||
![]() |
e3a8448a23 | ||
![]() |
00d6036788 | ||
![]() |
53bb69621c | ||
![]() |
ad85beea91 | ||
![]() |
d7a237677a | ||
![]() |
16effa3938 | ||
![]() |
33a04c425b | ||
![]() |
20a52bc4e6 | ||
![]() |
482399d82f | ||
![]() |
3a171d19e3 | ||
![]() |
480970c799 | ||
![]() |
ceb3329f9e | ||
![]() |
1c0162c181 | ||
![]() |
cf62dccef7 | ||
![]() |
42410a260c | ||
![]() |
00c6a8f577 | ||
![]() |
9d2469549f | ||
![]() |
d2bc2c20c1 | ||
![]() |
10c37a3036 | ||
![]() |
00d14fa49f | ||
![]() |
0f1bc40f00 | ||
![]() |
4252857e19 | ||
![]() |
6d12a34c40 | ||
![]() |
9e126a4b91 | ||
![]() |
040ffda687 | ||
![]() |
39ff49e054 | ||
![]() |
b8f72a5bcb | ||
![]() |
43db704b74 | ||
![]() |
5043040530 | ||
![]() |
3c60aeeef9 | ||
![]() |
0344d61b26 | ||
![]() |
0e8467782b | ||
![]() |
423ea26266 | ||
![]() |
2f3339ba85 | ||
![]() |
9433b50785 | ||
![]() |
1e7b53dc0e | ||
![]() |
bc94748f2a | ||
![]() |
2395f93ed1 | ||
![]() |
d771726c2a | ||
![]() |
b2a2fe898c | ||
![]() |
31d408a746 | ||
![]() |
4a74f295e7 | ||
![]() |
b6ba6459fb | ||
![]() |
e399790442 | ||
![]() |
20c65b9a31 | ||
![]() |
1a7853a47e | ||
![]() |
683c3a4c90 | ||
![]() |
4a8d998afe | ||
![]() |
fe59d90c51 | ||
![]() |
f87813805a | ||
![]() |
a7e5b9978f | ||
![]() |
0a3959af86 | ||
![]() |
9ba6054140 | ||
![]() |
3348f04889 | ||
![]() |
c12aec7c8f | ||
![]() |
05f66b8f24 | ||
![]() |
d8b80f0fe9 | ||
![]() |
7314572d97 | ||
![]() |
52a29ed00a | ||
![]() |
5eaf8a5448 | ||
![]() |
f70fb12c3d | ||
![]() |
ece6c1203c | ||
![]() |
9c7e3177a2 | ||
![]() |
058c0affaf | ||
![]() |
5ee7146884 | ||
![]() |
1aa9a7a093 | ||
![]() |
a202c44a0f | ||
![]() |
85776cc7d0 | ||
![]() |
6d133ef724 | ||
![]() |
53288d361c | ||
![]() |
e729bd52aa | ||
![]() |
ddb6127519 | ||
![]() |
50b42eb6fe | ||
![]() |
b6572b7272 | ||
![]() |
57ced2c284 | ||
![]() |
26a3491466 | ||
![]() |
eed8463832 | ||
![]() |
718b4f3fd7 | ||
![]() |
22461d1728 | ||
![]() |
69cab1e6bb | ||
![]() |
a661fddaf3 | ||
![]() |
1b85e561b9 | ||
![]() |
a803ab8577 | ||
![]() |
daa759cc55 | ||
![]() |
513a099c24 | ||
![]() |
e299e73a68 | ||
![]() |
9550ac7422 | ||
![]() |
07bd376649 | ||
![]() |
ec6a1ed9d1 | ||
![]() |
7aee28d080 | ||
![]() |
24ec13e36d | ||
![]() |
d2e7c360b9 | ||
![]() |
f00628f4e5 | ||
![]() |
19bd5ace7d | ||
![]() |
3e2506136c | ||
![]() |
4e03acc944 | ||
![]() |
188eb6b9ea | ||
![]() |
c89e1a5735 | ||
![]() |
e50cc59f0d | ||
![]() |
96f87caff0 | ||
![]() |
b422a83b57 | ||
![]() |
15ae3bee55 | ||
![]() |
0cac2fec2a | ||
![]() |
5965da88c3 | ||
![]() |
ba0338e9d5 | ||
![]() |
ff62338359 | ||
![]() |
9867f4eeee | ||
![]() |
ba278dfc3d | ||
![]() |
063030bcf3 | ||
![]() |
276ce8710c | ||
![]() |
5ed7a17f46 | ||
![]() |
01c3b4fa6e | ||
![]() |
165ca8fbc7 | ||
![]() |
ce90ae343c | ||
![]() |
a99f360a64 | ||
![]() |
d51e9446ff | ||
![]() |
d3524ee46f | ||
![]() |
121ea37825 | ||
![]() |
9592d95599 | ||
![]() |
d6faa18adb | ||
![]() |
1cbe6f77ee | ||
![]() |
4f5d4e36b7 | ||
![]() |
163025c1f2 | ||
![]() |
880178d62e | ||
![]() |
d285ff7e54 | ||
![]() |
54671fc522 | ||
![]() |
53e3e6545d | ||
![]() |
91cb49c4a3 | ||
![]() |
c065cb48f2 | ||
![]() |
d376f6b1d2 | ||
![]() |
45526a7652 | ||
![]() |
cc7929932b | ||
![]() |
e6516235fa | ||
![]() |
40d5a9f890 | ||
![]() |
ee3e744cc6 | ||
![]() |
b55bd1e027 | ||
![]() |
9a96df0319 | ||
![]() |
e9b1618364 | ||
![]() |
6dc6ed1e94 | ||
![]() |
1943a49274 | ||
![]() |
a8c00edc94 | ||
![]() |
faa8abb2b9 | ||
![]() |
f6cd2fc68e | ||
![]() |
6482000d6b | ||
![]() |
dcf7209706 | ||
![]() |
2ec921593e | ||
![]() |
75a01f657e | ||
![]() |
d4e512c1fc | ||
![]() |
26e7d34f18 | ||
![]() |
15b5ffddd4 | ||
![]() |
f0f3764992 | ||
![]() |
2beb44b591 | ||
![]() |
27b659dde1 | ||
![]() |
630c2ee6f6 | ||
![]() |
600477c487 | ||
![]() |
d31c295598 | ||
![]() |
a7bb0931c4 | ||
![]() |
ff99a01423 | ||
![]() |
ea6e311318 | ||
![]() |
6790467bbc | ||
![]() |
d315dbea22 | ||
![]() |
8db7ab6724 | ||
![]() |
9a2c034ae8 | ||
![]() |
2885b80a13 | ||
![]() |
4a85156e87 | ||
![]() |
1785c69e1b | ||
![]() |
a862ba8348 | ||
![]() |
633d45d02f | ||
![]() |
7f4e042dfa | ||
![]() |
507ec13848 | ||
![]() |
2132352639 | ||
![]() |
11016b8486 | ||
![]() |
8615f14407 | ||
![]() |
1e84f08018 | ||
![]() |
7f663328dc | ||
![]() |
ea53068432 | ||
![]() |
144aff9b4e | ||
![]() |
18db6daf0a | ||
![]() |
26ba29b538 | ||
![]() |
70167a34b6 | ||
![]() |
ccb668a1b6 | ||
![]() |
0989c64eab | ||
![]() |
c082fc5cb2 | ||
![]() |
d39111a294 | ||
![]() |
3c072f94b0 | ||
![]() |
7f8ae2ce5c | ||
![]() |
d84b75168c | ||
![]() |
eb0a5e1c55 | ||
![]() |
47ac77dbb0 | ||
![]() |
ec84847be7 | ||
![]() |
e7839bfd40 | ||
![]() |
8762da627b | ||
![]() |
3fab321045 | ||
![]() |
9451048574 | ||
![]() |
46c002038b | ||
![]() |
d1d833ea9a | ||
![]() |
c1f0750526 | ||
![]() |
89e02b6956 | ||
![]() |
97e8258288 | ||
![]() |
39040c1874 | ||
![]() |
c709851888 | ||
![]() |
b022bec1fa | ||
![]() |
bca0531963 | ||
![]() |
b2c7fc8f5b | ||
![]() |
96ac2c29d6 | ||
![]() |
14a5118b4d | ||
![]() |
232fa1ffe8 | ||
![]() |
d2e91754e9 | ||
![]() |
4d9066a58d | ||
![]() |
c618867941 | ||
![]() |
5ad4017510 | ||
![]() |
63e14a98f9 | ||
![]() |
25e3fe8eab | ||
![]() |
840f046572 | ||
![]() |
89e3c2e4b1 | ||
![]() |
c770470b58 | ||
![]() |
4619836122 | ||
![]() |
76403bba8e | ||
![]() |
a9afa303a2 | ||
![]() |
e5399ae07a | ||
![]() |
80a5a7b129 | ||
![]() |
9dc97d4b6b | ||
![]() |
d8c9169af2 | ||
![]() |
ec256f7130 | ||
![]() |
19bbfce4ed | ||
![]() |
b0b2d9d972 | ||
![]() |
6f5f5c9461 | ||
![]() |
fc04bc6046 | ||
![]() |
9f504253fb | ||
![]() |
961997e078 | ||
![]() |
363594a9a2 | ||
![]() |
247e2677f3 | ||
![]() |
5b5159f4dd | ||
![]() |
bc8b85860c | ||
![]() |
44d45c5880 | ||
![]() |
a6d8e4fc3f | ||
![]() |
2cc9a15f6a | ||
![]() |
151f9fb2ee | ||
![]() |
32fb76b3d1 | ||
![]() |
8d52e2635a | ||
![]() |
f20e1f20a6 | ||
![]() |
af8594c5c6 | ||
![]() |
899d41f361 | ||
![]() |
7dc6382c90 | ||
![]() |
e8009c2d26 | ||
![]() |
3bc7cdaab6 | ||
![]() |
724d8187c6 | ||
![]() |
8f68df60c7 | ||
![]() |
6af3cb6134 | ||
![]() |
2ff0c3907f | ||
![]() |
dd102ff01d | ||
![]() |
f20b1d75e6 | ||
![]() |
a4b88ac4a7 | ||
![]() |
93b9d586d2 | ||
![]() |
41dd4447cc | ||
![]() |
8b9c8a2e80 | ||
![]() |
a63ff1bb99 | ||
![]() |
d5e3b59245 | ||
![]() |
d0470fffcc | ||
![]() |
5053305e17 | ||
![]() |
9c79392060 | ||
![]() |
708c3278bf | ||
![]() |
c0249f6e59 | ||
![]() |
afd8aefac2 | ||
![]() |
3c07767138 | ||
![]() |
953c442f13 | ||
![]() |
e147852878 | ||
![]() |
db7ee6cfb3 | ||
![]() |
3b41b6cc33 | ||
![]() |
5e79888370 | ||
![]() |
a6aa9bdd59 | ||
![]() |
d78b7cc110 | ||
![]() |
e7cdace0ab | ||
![]() |
f60eb4e977 | ||
![]() |
7aecf6c6de | ||
![]() |
75d62096a6 | ||
![]() |
7c44994070 | ||
![]() |
f49f3fd9c3 | ||
![]() |
5ea86d636c | ||
![]() |
4c6e90717a | ||
![]() |
d60ca9d783 | ||
![]() |
d304718ea0 | ||
![]() |
c787c8948e | ||
![]() |
62728ef7fb | ||
![]() |
47e256f03d | ||
![]() |
527db52d5e | ||
![]() |
f78b2c48a7 | ||
![]() |
90c965a32a | ||
![]() |
d4afcde6c9 | ||
![]() |
257de89ce4 | ||
![]() |
735cc3962b | ||
![]() |
feb42181de | ||
![]() |
f5c4bfa7b4 | ||
![]() |
65ddd91855 | ||
![]() |
6d7d838613 | ||
![]() |
5edf7b7f00 | ||
![]() |
117569830d | ||
![]() |
d62aec7287 | ||
![]() |
4e0cf3681e | ||
![]() |
d98751102a | ||
![]() |
1acbeb813e | ||
![]() |
b87ec752cf | ||
![]() |
753df31fa6 | ||
![]() |
bd77b74689 | ||
![]() |
810c23d8ee | ||
![]() |
34d9b2983e | ||
![]() |
63c5c8412a | ||
![]() |
60207723d1 | ||
![]() |
f4117ad096 | ||
![]() |
8bed4e9970 | ||
![]() |
f72eaf781c | ||
![]() |
e9ecc20a36 | ||
![]() |
addfa2a32d | ||
![]() |
0dad9bc393 | ||
![]() |
5155875a72 | ||
![]() |
4ed1217366 | ||
![]() |
50e898a684 | ||
![]() |
251c7fa982 | ||
![]() |
00c75e9f98 | ||
![]() |
1b5b02d286 | ||
![]() |
946d655cee | ||
![]() |
d56710b0b5 | ||
![]() |
0cf78277b5 | ||
![]() |
ce2a583ff9 | ||
![]() |
84bddad30e | ||
![]() |
0ff682504a | ||
![]() |
5d5984166f | ||
![]() |
b825eb44fe | ||
![]() |
7015eb66f2 | ||
![]() |
494eeb16a5 | ||
![]() |
692fdc8d5d | ||
![]() |
ec1a8ebd4a | ||
![]() |
59daa6597b | ||
![]() |
3941ce4ad1 | ||
![]() |
aff87d4372 | ||
![]() |
373ca87887 | ||
![]() |
03c855ecbe | ||
![]() |
3a3cb24631 | ||
![]() |
4c3fea25a5 | ||
![]() |
af303cbf2a | ||
![]() |
b7c09a9b38 | ||
![]() |
eced06eea8 | ||
![]() |
15d989255c | ||
![]() |
095566b9c2 | ||
![]() |
b77a65d446 | ||
![]() |
9778a748fc | ||
![]() |
a89dddcafa | ||
![]() |
75973fd4c0 | ||
![]() |
514036f9d1 | ||
![]() |
36fbedab20 | ||
![]() |
180baeba50 | ||
![]() |
cce82fe2a5 | ||
![]() |
5512bb2e06 | ||
![]() |
be1fcbbdf8 | ||
![]() |
422cd52049 | ||
![]() |
d67a56d37e | ||
![]() |
070c9721b6 | ||
![]() |
0219834dd1 |
97
.devcontainer/devcontainer.json
Normal file
97
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"name": "Frigate Devcontainer",
|
||||
"dockerComposeFile": "../docker-compose.yml",
|
||||
"service": "devcontainer",
|
||||
"workspaceFolder": "/workspace/frigate",
|
||||
"initializeCommand": ".devcontainer/initialize.sh",
|
||||
"postCreateCommand": ".devcontainer/post_create.sh",
|
||||
"overrideCommand": false,
|
||||
"remoteUser": "vscode",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/common-utils:1": {}
|
||||
},
|
||||
"forwardPorts": [5000, 5001, 5173, 1935, 8554, 8555],
|
||||
"portsAttributes": {
|
||||
"5000": {
|
||||
"label": "NGINX",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"5001": {
|
||||
"label": "Frigate API",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"5173": {
|
||||
"label": "Vite Server",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"1935": {
|
||||
"label": "RTMP",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"8554": {
|
||||
"label": "gortc RTSP",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"8555": {
|
||||
"label": "go2rtc WebRTC",
|
||||
"onAutoForward": "silent"
|
||||
}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"ms-python.black-formatter",
|
||||
"visualstudioexptteam.vscodeintellicode",
|
||||
"mhutchie.git-graph",
|
||||
"ms-azuretools.vscode-docker",
|
||||
"streetsidesoftware.code-spell-checker",
|
||||
"esbenp.prettier-vscode",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"mikestead.dotenv",
|
||||
"csstools.postcss",
|
||||
"blanu.vscode-styled-jsx",
|
||||
"bradlc.vscode-tailwindcss",
|
||||
"ms-python.isort",
|
||||
"charliermarsh.ruff"
|
||||
],
|
||||
"settings": {
|
||||
"remote.autoForwardPorts": false,
|
||||
"python.linting.pylintEnabled": true,
|
||||
"python.linting.enabled": true,
|
||||
"python.formatting.provider": "none",
|
||||
"python.languageServer": "Pylance",
|
||||
"editor.formatOnPaste": false,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnType": true,
|
||||
"python.testing.pytestEnabled": false,
|
||||
"python.testing.unittestEnabled": true,
|
||||
"python.testing.unittestArgs": ["-v", "-s", "./frigate/test"],
|
||||
"files.trimTrailingWhitespace": true,
|
||||
"eslint.workingDirectories": ["./web"],
|
||||
"isort.args": ["--settings-path=./pyproject.toml"],
|
||||
"[python]": {
|
||||
"editor.defaultFormatter": "ms-python.black-formatter",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll": true,
|
||||
"source.organizeImports": true
|
||||
}
|
||||
},
|
||||
"[json][jsonc]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[jsx][js][tsx][ts]": {
|
||||
"editor.codeActionsOnSave": [
|
||||
"source.addMissingImports",
|
||||
"source.fixAll"
|
||||
],
|
||||
"editor.tabSize": 2
|
||||
},
|
||||
"cSpell.ignoreWords": ["rtmp"],
|
||||
"cSpell.words": ["preact", "astype", "hwaccel", "mqtt"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
13
.devcontainer/initialize.sh
Executable file
13
.devcontainer/initialize.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# These folders needs to be created and owned by the host user
|
||||
mkdir -p debug web/dist
|
||||
|
||||
if [[ -f "config/config.yml" ]]; then
|
||||
echo "config/config.yml already exists, skipping initialization" >&2
|
||||
else
|
||||
echo "initializing config/config.yml" >&2
|
||||
cp -fv config/config.yml.example config/config.yml
|
||||
fi
|
28
.devcontainer/post_create.sh
Executable file
28
.devcontainer/post_create.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
# Cleanup the old github host key
|
||||
sed -i -e '/AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31\/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi\/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==/d' ~/.ssh/known_hosts
|
||||
# Add new github host key
|
||||
curl -L https://api.github.com/meta | jq -r '.ssh_keys | .[]' | \
|
||||
sed -e 's/^/github.com /' >> ~/.ssh/known_hosts
|
||||
|
||||
# Frigate normal container runs as root, so it have permission to create
|
||||
# the folders. But the devcontainer runs as the host user, so we need to
|
||||
# create the folders and give the host user permission to write to them.
|
||||
sudo mkdir -p /media/frigate
|
||||
sudo chown -R "$(id -u):$(id -g)" /media/frigate
|
||||
|
||||
# When started as a service, LIBAVFORMAT_VERSION_MAJOR is defined in the
|
||||
# s6 service file. For dev, where frigate is started from an interactive
|
||||
# shell, we define it in .bashrc instead.
|
||||
echo 'export LIBAVFORMAT_VERSION_MAJOR=$(ffmpeg -version | grep -Po "libavformat\W+\K\d+")' >> $HOME/.bashrc
|
||||
|
||||
make version
|
||||
|
||||
cd web
|
||||
|
||||
npm install
|
||||
|
||||
npm run build
|
@@ -3,4 +3,14 @@ docs/
|
||||
.gitignore
|
||||
debug
|
||||
config/
|
||||
*.pyc
|
||||
*.pyc
|
||||
.git
|
||||
core
|
||||
*.mp4
|
||||
*.jpg
|
||||
*.db
|
||||
*.ts
|
||||
|
||||
web/dist/
|
||||
web/node_modules/
|
||||
web/.npm
|
||||
|
4
.github/FUNDING.yml
vendored
4
.github/FUNDING.yml
vendored
@@ -1 +1,3 @@
|
||||
github: blakeblackshear
|
||||
github:
|
||||
- blakeblackshear
|
||||
- NickM-27
|
||||
|
55
.github/ISSUE_TEMPLATE/bug_report.md
vendored
55
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,55 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Version of frigate**
|
||||
What version are you using?
|
||||
|
||||
**Config file**
|
||||
Include your full config file wrapped in triple back ticks.
|
||||
```yaml
|
||||
config here
|
||||
```
|
||||
|
||||
**Logs**
|
||||
```
|
||||
Include relevant log output here
|
||||
```
|
||||
|
||||
**Frigate debug stats**
|
||||
```
|
||||
Output from frigate's /debug/stats endpoint
|
||||
```
|
||||
|
||||
**FFprobe from your camera**
|
||||
|
||||
Run the following command and paste output below
|
||||
```
|
||||
ffprobe <stream_url>
|
||||
```
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Computer Hardware**
|
||||
- OS: [e.g. Ubuntu, Windows]
|
||||
- Virtualization: [e.g. Proxmox, Virtualbox]
|
||||
- Coral Version: [e.g. USB, PCIe, None]
|
||||
- Network Setup: [e.g. Wired, WiFi]
|
||||
|
||||
**Camera Info:**
|
||||
- Manufacturer: [e.g. Dahua]
|
||||
- Model: [e.g. IPC-HDW5231R-ZE]
|
||||
- Resolution: [e.g. 720p]
|
||||
- FPS: [e.g. 5]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
107
.github/ISSUE_TEMPLATE/camera_support_request.yml
vendored
Normal file
107
.github/ISSUE_TEMPLATE/camera_support_request.yml
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
name: Camera Support Request
|
||||
description: Support for setting up cameras in Frigate
|
||||
title: "[Camera Support]: "
|
||||
labels: ["support", "triage"]
|
||||
assignees: []
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the problem you are having
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: Visible on the Debug page in the Web UI
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: config
|
||||
attributes:
|
||||
label: Frigate config file
|
||||
description: This will be automatically formatted into code, so no need for backticks.
|
||||
render: yaml
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: ffprobe
|
||||
attributes:
|
||||
label: FFprobe output from your camera
|
||||
description: Run `ffprobe <camera_url>` and provide output below
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: stats
|
||||
attributes:
|
||||
label: Frigate stats
|
||||
description: Output from frigate's /api/stats endpoint
|
||||
render: json
|
||||
- type: dropdown
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating system
|
||||
options:
|
||||
- HassOS
|
||||
- Debian
|
||||
- Other Linux
|
||||
- Proxmox
|
||||
- UNRAID
|
||||
- Windows
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: install-method
|
||||
attributes:
|
||||
label: Install method
|
||||
options:
|
||||
- HassOS Addon
|
||||
- Docker Compose
|
||||
- Docker CLI
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: coral
|
||||
attributes:
|
||||
label: Coral version
|
||||
options:
|
||||
- USB
|
||||
- PCIe
|
||||
- M.2
|
||||
- Dev Board
|
||||
- Other
|
||||
- CPU (no coral)
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: network
|
||||
attributes:
|
||||
label: Network connection
|
||||
options:
|
||||
- Wired
|
||||
- Wireless
|
||||
- Mixed
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: camera
|
||||
attributes:
|
||||
label: Camera make and model
|
||||
description: Dahua, hikvision, amcrest, reolink, etc and model number
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: other
|
||||
attributes:
|
||||
label: Any other information that may be helpful
|
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
blank_issues_enabled: false
|
82
.github/ISSUE_TEMPLATE/config_support_request.yml
vendored
Normal file
82
.github/ISSUE_TEMPLATE/config_support_request.yml
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
name: Config Support Request
|
||||
description: Support for Frigate configuration
|
||||
title: "[Config Support]: "
|
||||
labels: ["support", "triage"]
|
||||
assignees: []
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the problem you are having
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: Visible on the Debug page in the Web UI
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: config
|
||||
attributes:
|
||||
label: Frigate config file
|
||||
description: This will be automatically formatted into code, so no need for backticks.
|
||||
render: yaml
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: stats
|
||||
attributes:
|
||||
label: Frigate stats
|
||||
description: Output from frigate's /api/stats endpoint
|
||||
render: json
|
||||
- type: dropdown
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating system
|
||||
options:
|
||||
- HassOS
|
||||
- Debian
|
||||
- Other Linux
|
||||
- Proxmox
|
||||
- UNRAID
|
||||
- Windows
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: install-method
|
||||
attributes:
|
||||
label: Install method
|
||||
options:
|
||||
- HassOS Addon
|
||||
- Docker Compose
|
||||
- Docker CLI
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: coral
|
||||
attributes:
|
||||
label: Coral version
|
||||
options:
|
||||
- USB
|
||||
- PCIe
|
||||
- M.2
|
||||
- Dev Board
|
||||
- Other
|
||||
- CPU (no coral)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: other
|
||||
attributes:
|
||||
label: Any other information that may be helpful
|
84
.github/ISSUE_TEMPLATE/detector_support_request.yml
vendored
Normal file
84
.github/ISSUE_TEMPLATE/detector_support_request.yml
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
name: Detector Support Request
|
||||
description: Support for setting up object detector in Frigate (Coral, OpenVINO, TensorRT, etc.)
|
||||
title: "[Detector Support]: "
|
||||
labels: ["support", "triage"]
|
||||
assignees: []
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the problem you are having
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: Visible on the Debug page in the Web UI
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: config
|
||||
attributes:
|
||||
label: Frigate config file
|
||||
description: This will be automatically formatted into code, so no need for backticks.
|
||||
render: yaml
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: docker
|
||||
attributes:
|
||||
label: docker-compose file or Docker CLI command
|
||||
description: This will be automatically formatted into code, so no need for backticks.
|
||||
render: yaml
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating system
|
||||
options:
|
||||
- HassOS
|
||||
- Debian
|
||||
- Other Linux
|
||||
- Proxmox
|
||||
- UNRAID
|
||||
- Windows
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: install-method
|
||||
attributes:
|
||||
label: Install method
|
||||
options:
|
||||
- HassOS Addon
|
||||
- Docker Compose
|
||||
- Docker CLI
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: coral
|
||||
attributes:
|
||||
label: Coral version
|
||||
options:
|
||||
- USB
|
||||
- PCIe
|
||||
- M.2
|
||||
- Dev Board
|
||||
- Other
|
||||
- CPU (no coral)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: other
|
||||
attributes:
|
||||
label: Any other information that may be helpful
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe what you are trying to accomplish and why in non technical terms**
|
||||
I want to be able to ... so that I can ...
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
107
.github/ISSUE_TEMPLATE/general_support_request.yml
vendored
Normal file
107
.github/ISSUE_TEMPLATE/general_support_request.yml
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
name: General Support Request
|
||||
description: General support request for Frigate
|
||||
title: "[Support]: "
|
||||
labels: ["support", "triage"]
|
||||
assignees: []
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the problem you are having
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: Visible on the Debug page in the Web UI
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: config
|
||||
attributes:
|
||||
label: Frigate config file
|
||||
description: This will be automatically formatted into code, so no need for backticks.
|
||||
render: yaml
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: ffprobe
|
||||
attributes:
|
||||
label: FFprobe output from your camera
|
||||
description: Run `ffprobe <camera_url>` and provide output below
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: stats
|
||||
attributes:
|
||||
label: Frigate stats
|
||||
description: Output from frigate's /api/stats endpoint
|
||||
render: json
|
||||
- type: dropdown
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating system
|
||||
options:
|
||||
- HassOS
|
||||
- Debian
|
||||
- Other Linux
|
||||
- Proxmox
|
||||
- UNRAID
|
||||
- Windows
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: install-method
|
||||
attributes:
|
||||
label: Install method
|
||||
options:
|
||||
- HassOS Addon
|
||||
- Docker Compose
|
||||
- Docker CLI
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: coral
|
||||
attributes:
|
||||
label: Coral version
|
||||
options:
|
||||
- USB
|
||||
- PCIe
|
||||
- M.2
|
||||
- Dev Board
|
||||
- Other
|
||||
- CPU (no coral)
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: network
|
||||
attributes:
|
||||
label: Network connection
|
||||
options:
|
||||
- Wired
|
||||
- Wireless
|
||||
- Mixed
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: camera
|
||||
attributes:
|
||||
label: Camera make and model
|
||||
description: Dahua, hikvision, amcrest, reolink, etc and model number
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: other
|
||||
attributes:
|
||||
label: Any other information that may be helpful
|
96
.github/ISSUE_TEMPLATE/hwaccel_support_request.yml
vendored
Normal file
96
.github/ISSUE_TEMPLATE/hwaccel_support_request.yml
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
name: Hardware Acceleration Support Request
|
||||
description: Support for setting up GPU hardware acceleration in Frigate
|
||||
title: "[HW Accel Support]: "
|
||||
labels: ["support", "triage"]
|
||||
assignees: []
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the problem you are having
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: Visible on the Debug page in the Web UI
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: config
|
||||
attributes:
|
||||
label: Frigate config file
|
||||
description: This will be automatically formatted into code, so no need for backticks.
|
||||
render: yaml
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: docker
|
||||
attributes:
|
||||
label: docker-compose file or Docker CLI command
|
||||
description: This will be automatically formatted into code, so no need for backticks.
|
||||
render: yaml
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: ffprobe
|
||||
attributes:
|
||||
label: FFprobe output from your camera
|
||||
description: Run `ffprobe <camera_url>` and provide output below
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating system
|
||||
options:
|
||||
- HassOS
|
||||
- Debian
|
||||
- Other Linux
|
||||
- Proxmox
|
||||
- UNRAID
|
||||
- Windows
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: install-method
|
||||
attributes:
|
||||
label: Install method
|
||||
options:
|
||||
- HassOS Addon
|
||||
- Docker Compose
|
||||
- Docker CLI
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: network
|
||||
attributes:
|
||||
label: Network connection
|
||||
options:
|
||||
- Wired
|
||||
- Wireless
|
||||
- Mixed
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: camera
|
||||
attributes:
|
||||
label: Camera make and model
|
||||
description: Dahua, hikvision, amcrest, reolink, etc and model number
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: other
|
||||
attributes:
|
||||
label: Any other information that may be helpful
|
39
.github/actions/setup/action.yml
vendored
Normal file
39
.github/actions/setup/action.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
name: 'Setup'
|
||||
description: 'Set up QEMU and Buildx'
|
||||
inputs:
|
||||
GITHUB_TOKEN:
|
||||
required: true
|
||||
outputs:
|
||||
image-name:
|
||||
value: ghcr.io/${{ steps.lowercaseRepo.outputs.lowercase }}:${{ github.ref_name }}-${{ steps.create-short-sha.outputs.SHORT_SHA }}
|
||||
cache-name:
|
||||
value: ghcr.io/${{ steps.lowercaseRepo.outputs.lowercase }}:cache
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Remove unnecessary files
|
||||
run: |
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /usr/local/lib/android
|
||||
sudo rm -rf /opt/ghc
|
||||
shell: bash
|
||||
- id: lowercaseRepo
|
||||
uses: ASzc/change-string-case-action@v5
|
||||
with:
|
||||
string: ${{ github.repository }}
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ inputs.GITHUB_TOKEN }}
|
||||
- name: Create version file
|
||||
run: make version
|
||||
shell: bash
|
||||
- id: create-short-sha
|
||||
run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
32
.github/dependabot.yml
vendored
Normal file
32
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
target-branch: dev
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/docker"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
target-branch: dev
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/docker/main"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
target-branch: dev
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/web"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
target-branch: dev
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/docs"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
target-branch: dev
|
160
.github/workflows/ci.yml
vendored
Normal file
160
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
- master
|
||||
|
||||
# only run the latest commit to avoid cache overwrites
|
||||
concurrency:
|
||||
group: ${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
PYTHON_VERSION: 3.9
|
||||
|
||||
jobs:
|
||||
amd64_build:
|
||||
runs-on: ubuntu-latest
|
||||
name: AMD64 Build
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up QEMU and Buildx
|
||||
id: setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Build and push amd64 standard build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: docker/main/Dockerfile
|
||||
push: true
|
||||
platforms: linux/amd64
|
||||
target: frigate
|
||||
tags: ${{ steps.setup.outputs.image-name }}-amd64
|
||||
cache-from: type=registry,ref=${{ steps.setup.outputs.cache-name }}-amd64
|
||||
- name: Build and push TensorRT (x86 GPU)
|
||||
uses: docker/bake-action@v4
|
||||
with:
|
||||
push: true
|
||||
targets: tensorrt
|
||||
files: docker/tensorrt/trt.hcl
|
||||
set: |
|
||||
tensorrt.tags=${{ steps.setup.outputs.image-name }}-tensorrt
|
||||
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-amd64
|
||||
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-amd64,mode=max
|
||||
arm64_build:
|
||||
runs-on: ubuntu-latest
|
||||
name: ARM Build
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up QEMU and Buildx
|
||||
id: setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Build and push arm64 standard build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: docker/main/Dockerfile
|
||||
push: true
|
||||
platforms: linux/arm64
|
||||
target: frigate
|
||||
tags: |
|
||||
${{ steps.setup.outputs.image-name }}-standard-arm64
|
||||
cache-from: type=registry,ref=${{ steps.setup.outputs.cache-name }}-arm64
|
||||
- name: Build and push RPi build
|
||||
uses: docker/bake-action@v4
|
||||
with:
|
||||
push: true
|
||||
targets: rpi
|
||||
files: docker/rpi/rpi.hcl
|
||||
set: |
|
||||
rpi.tags=${{ steps.setup.outputs.image-name }}-rpi
|
||||
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-arm64
|
||||
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-arm64,mode=max
|
||||
jetson_jp4_build:
|
||||
runs-on: ubuntu-latest
|
||||
name: Jetson Jetpack 4
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up QEMU and Buildx
|
||||
id: setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Build and push TensorRT (Jetson, Jetpack 4)
|
||||
env:
|
||||
ARCH: arm64
|
||||
BASE_IMAGE: timongentzsch/l4t-ubuntu20-opencv:latest
|
||||
SLIM_BASE: timongentzsch/l4t-ubuntu20-opencv:latest
|
||||
TRT_BASE: timongentzsch/l4t-ubuntu20-opencv:latest
|
||||
uses: docker/bake-action@v4
|
||||
with:
|
||||
push: true
|
||||
targets: tensorrt
|
||||
files: docker/tensorrt/trt.hcl
|
||||
set: |
|
||||
tensorrt.tags=${{ steps.setup.outputs.image-name }}-tensorrt-jp4
|
||||
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-jp4
|
||||
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-jp4,mode=max
|
||||
jetson_jp5_build:
|
||||
runs-on: ubuntu-latest
|
||||
name: Jetson Jetpack 5
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up QEMU and Buildx
|
||||
id: setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Build and push TensorRT (Jetson, Jetpack 5)
|
||||
env:
|
||||
ARCH: arm64
|
||||
BASE_IMAGE: nvcr.io/nvidia/l4t-tensorrt:r8.5.2-runtime
|
||||
SLIM_BASE: nvcr.io/nvidia/l4t-tensorrt:r8.5.2-runtime
|
||||
TRT_BASE: nvcr.io/nvidia/l4t-tensorrt:r8.5.2-runtime
|
||||
uses: docker/bake-action@v4
|
||||
with:
|
||||
push: true
|
||||
targets: tensorrt
|
||||
files: docker/tensorrt/trt.hcl
|
||||
set: |
|
||||
tensorrt.tags=${{ steps.setup.outputs.image-name }}-tensorrt-jp5
|
||||
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-jp5
|
||||
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-jp5,mode=max
|
||||
# The majority of users running arm64 are rpi users, so the rpi
|
||||
# build should be the primary arm64 image
|
||||
assemble_default_build:
|
||||
runs-on: ubuntu-latest
|
||||
name: Assemble and push default build
|
||||
needs:
|
||||
- amd64_build
|
||||
- arm64_build
|
||||
steps:
|
||||
- id: lowercaseRepo
|
||||
uses: ASzc/change-string-case-action@v5
|
||||
with:
|
||||
string: ${{ github.repository }}
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Create short sha
|
||||
run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV
|
||||
- uses: int128/docker-manifest-create-action@v1
|
||||
with:
|
||||
tags: ghcr.io/${{ steps.lowercaseRepo.outputs.lowercase }}:${{ github.ref_name }}-${{ env.SHORT_SHA }}
|
||||
suffixes: |
|
||||
-amd64
|
||||
-rpi
|
24
.github/workflows/dependabot-auto-merge.yaml
vendored
Normal file
24
.github/workflows/dependabot-auto-merge.yaml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: dependabot-auto-merge
|
||||
on: pull_request
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
dependabot-auto-merge:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.actor == 'dependabot[bot]'
|
||||
steps:
|
||||
- name: Get Dependabot metadata
|
||||
id: metadata
|
||||
uses: dependabot/fetch-metadata@v1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Enable auto-merge for Dependabot PRs
|
||||
if: steps.metadata.outputs.dependency-type == 'direct:development' && (steps.metadata.outputs.update-type == 'version-update:semver-minor' || steps.metadata.outputs.update-type == 'version-update:semver-patch')
|
||||
run: |
|
||||
gh pr review --approve "$PR_URL"
|
||||
gh pr merge --auto --squash "$PR_URL"
|
||||
env:
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
108
.github/workflows/pull_request.yml
vendored
Normal file
108
.github/workflows/pull_request.yml
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
name: On pull request
|
||||
|
||||
on: pull_request
|
||||
|
||||
env:
|
||||
DEFAULT_PYTHON: 3.9
|
||||
|
||||
jobs:
|
||||
build_devcontainer:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build Devcontainer
|
||||
# The Dockerfile contains features that requires buildkit, and since the
|
||||
# devcontainer cli uses docker-compose to build the image, the only way to
|
||||
# ensure docker-compose uses buildkit is to explicitly enable it.
|
||||
env:
|
||||
DOCKER_BUILDKIT: "1"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@master
|
||||
with:
|
||||
node-version: 16.x
|
||||
- name: Install devcontainer cli
|
||||
run: npm install --global @devcontainers/cli
|
||||
- name: Build devcontainer
|
||||
run: devcontainer build --workspace-folder .
|
||||
# It would be nice to also test the following commands, but for some
|
||||
# reason they don't work even though in VS Code devcontainer works.
|
||||
# - name: Start devcontainer
|
||||
# run: devcontainer up --workspace-folder .
|
||||
# - name: Run devcontainer scripts
|
||||
# run: devcontainer run-user-commands --workspace-folder .
|
||||
|
||||
web_lint:
|
||||
name: Web - Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@master
|
||||
with:
|
||||
node-version: 16.x
|
||||
- run: npm install
|
||||
working-directory: ./web
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
working-directory: ./web
|
||||
|
||||
web_test:
|
||||
name: Web - Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@master
|
||||
with:
|
||||
node-version: 16.x
|
||||
- run: npm install
|
||||
working-directory: ./web
|
||||
- name: Test
|
||||
run: npm run test
|
||||
working-directory: ./web
|
||||
|
||||
python_checks:
|
||||
runs-on: ubuntu-latest
|
||||
name: Python Checks
|
||||
steps:
|
||||
- name: Check out the repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v4.7.1
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Install requirements
|
||||
run: |
|
||||
python3 -m pip install -U pip
|
||||
python3 -m pip install -r docker/main/requirements-dev.txt
|
||||
- name: Check black
|
||||
run: |
|
||||
black --check --diff frigate migrations docker *.py
|
||||
- name: Check isort
|
||||
run: |
|
||||
isort --check --diff frigate migrations docker *.py
|
||||
- name: Check ruff
|
||||
run: |
|
||||
ruff check frigate migrations docker *.py
|
||||
|
||||
python_tests:
|
||||
runs-on: ubuntu-latest
|
||||
name: Python Tests
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@master
|
||||
with:
|
||||
node-version: 16.x
|
||||
- run: npm install
|
||||
working-directory: ./web
|
||||
- name: Build web
|
||||
run: npm run build
|
||||
working-directory: ./web
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build
|
||||
run: make
|
||||
- name: Run mypy
|
||||
run: docker run --rm --entrypoint=python3 frigate:latest -u -m mypy --config-file frigate/mypy.ini frigate
|
||||
- name: Run tests
|
||||
run: docker run --rm --entrypoint=python3 frigate:latest -u -m unittest
|
62
.github/workflows/release.yml
vendored
Normal file
62
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
name: On release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- id: lowercaseRepo
|
||||
uses: ASzc/change-string-case-action@v5
|
||||
with:
|
||||
string: ${{ github.repository }}
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Create tag variables
|
||||
run: |
|
||||
echo "BASE=ghcr.io/${{ steps.lowercaseRepo.outputs.lowercase }}" >> $GITHUB_ENV
|
||||
echo "BUILD_TAG=${{ github.ref_name }}-${GITHUB_SHA::7}" >> $GITHUB_ENV
|
||||
echo "CLEAN_VERSION=$(echo ${GITHUB_REF##*/} | tr '[:upper:]' '[:lower:]' | sed 's/^[v]//')" >> $GITHUB_ENV
|
||||
- name: Tag and push the main image
|
||||
run: |
|
||||
VERSION_TAG=${BASE}:${CLEAN_VERSION}
|
||||
PULL_TAG=${BASE}:${BUILD_TAG}
|
||||
docker pull ${PULL_TAG}
|
||||
docker tag ${PULL_TAG} ${VERSION_TAG}
|
||||
docker push ${VERSION_TAG}
|
||||
- name: Tag and push standard arm64
|
||||
run: |
|
||||
VERSION_TAG=${BASE}:${CLEAN_VERSION}-standard-arm64
|
||||
PULL_TAG=${BASE}:${BUILD_TAG}-standard-arm64
|
||||
docker pull ${PULL_TAG}
|
||||
docker tag ${PULL_TAG} ${VERSION_TAG}
|
||||
docker push ${VERSION_TAG}
|
||||
- name: Tag and push tensorrt
|
||||
run: |
|
||||
VERSION_TAG=${BASE}:${CLEAN_VERSION}-tensorrt
|
||||
PULL_TAG=${BASE}:${BUILD_TAG}-tensorrt
|
||||
docker pull ${PULL_TAG}
|
||||
docker tag ${PULL_TAG} ${VERSION_TAG}
|
||||
docker push ${VERSION_TAG}
|
||||
- name: Tag and push tensorrt-jp4
|
||||
run: |
|
||||
VERSION_TAG=${BASE}:${CLEAN_VERSION}-tensorrt-jp4
|
||||
PULL_TAG=${BASE}:${BUILD_TAG}-tensorrt-jp4
|
||||
docker pull ${PULL_TAG}
|
||||
docker tag ${PULL_TAG} ${VERSION_TAG}
|
||||
docker push ${VERSION_TAG}
|
||||
- name: Tag and push tensorrt-jp5
|
||||
run: |
|
||||
VERSION_TAG=${BASE}:${CLEAN_VERSION}-tensorrt-jp5
|
||||
PULL_TAG=${BASE}:${BUILD_TAG}-tensorrt-jp5
|
||||
docker pull ${PULL_TAG}
|
||||
docker tag ${PULL_TAG} ${VERSION_TAG}
|
||||
docker push ${VERSION_TAG}
|
26
.github/workflows/stale.yml
vendored
Normal file
26
.github/workflows/stale.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
# Close Stale Issues
|
||||
# Warns and then closes issues and PRs that have had no activity for a specified amount of time.
|
||||
# https://github.com/actions/stale
|
||||
|
||||
name: "Stalebot"
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # run stalebot once a day
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@main
|
||||
id: stale
|
||||
with:
|
||||
stale-issue-message: "This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions."
|
||||
close-issue-message: ""
|
||||
days-before-stale: 30
|
||||
days-before-close: 3
|
||||
exempt-draft-pr: true
|
||||
exempt-issue-labels: "pinned,security"
|
||||
exempt-pr-labels: "pinned,security,dependencies"
|
||||
operations-per-run: 120
|
||||
- name: Print outputs
|
||||
run: echo ${{ join(steps.stale.outputs.*, ',') }}
|
22
.gitignore
vendored
22
.gitignore
vendored
@@ -1,4 +1,20 @@
|
||||
*.pyc
|
||||
.DS_Store
|
||||
*.pyc
|
||||
*.swp
|
||||
debug
|
||||
.vscode
|
||||
config/config.yml
|
||||
.vscode/*
|
||||
!.vscode/launch.json
|
||||
config/*
|
||||
!config/*.example
|
||||
models
|
||||
*.mp4
|
||||
*.ts
|
||||
*.db
|
||||
*.csv
|
||||
frigate/version.py
|
||||
web/build
|
||||
web/node_modules
|
||||
web/coverage
|
||||
core
|
||||
!/web/**/*.ts
|
||||
.idea/*
|
588
.pylintrc
Normal file
588
.pylintrc
Normal file
@@ -0,0 +1,588 @@
|
||||
[MASTER]
|
||||
|
||||
# A comma-separated list of package or module names from where C extensions may
|
||||
# be loaded. Extensions are loading into the active Python interpreter and may
|
||||
# run arbitrary code.
|
||||
extension-pkg-whitelist=
|
||||
|
||||
# Specify a score threshold to be exceeded before program exits with error.
|
||||
fail-under=10.0
|
||||
|
||||
# Add files or directories to the blacklist. They should be base names, not
|
||||
# paths.
|
||||
ignore=CVS
|
||||
|
||||
# Add files or directories matching the regex patterns to the blacklist. The
|
||||
# regex matches against base names, not paths.
|
||||
ignore-patterns=
|
||||
|
||||
# Python code to execute, usually for sys.path manipulation such as
|
||||
# pygtk.require().
|
||||
#init-hook=
|
||||
|
||||
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
|
||||
# number of processors available to use.
|
||||
jobs=1
|
||||
|
||||
# Control the amount of potential inferred values when inferring a single
|
||||
# object. This can help the performance when dealing with large functions or
|
||||
# complex, nested conditions.
|
||||
limit-inference-results=100
|
||||
|
||||
# List of plugins (as comma separated values of python module names) to load,
|
||||
# usually to register additional checkers.
|
||||
load-plugins=
|
||||
|
||||
# Pickle collected data for later comparisons.
|
||||
persistent=yes
|
||||
|
||||
# When enabled, pylint would attempt to guess common misconfiguration and emit
|
||||
# user-friendly hints instead of false-positive error messages.
|
||||
suggestion-mode=yes
|
||||
|
||||
# Allow loading of arbitrary C extensions. Extensions are imported into the
|
||||
# active Python interpreter and may run arbitrary code.
|
||||
unsafe-load-any-extension=no
|
||||
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
|
||||
# Only show warnings with the listed confidence levels. Leave empty to show
|
||||
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED.
|
||||
confidence=
|
||||
|
||||
# Disable the message, report, category or checker with the given id(s). You
|
||||
# can either give multiple identifiers separated by comma (,) or put this
|
||||
# option multiple times (only on the command line, not in the configuration
|
||||
# file where it should appear only once). You can also use "--disable=all" to
|
||||
# disable everything first and then reenable specific checks. For example, if
|
||||
# you want to run only the similarities checker, you can use "--disable=all
|
||||
# --enable=similarities". If you want to run only the classes checker, but have
|
||||
# no Warning level messages displayed, use "--disable=all --enable=classes
|
||||
# --disable=W".
|
||||
disable=print-statement,
|
||||
parameter-unpacking,
|
||||
unpacking-in-except,
|
||||
old-raise-syntax,
|
||||
backtick,
|
||||
long-suffix,
|
||||
old-ne-operator,
|
||||
old-octal-literal,
|
||||
import-star-module-level,
|
||||
non-ascii-bytes-literal,
|
||||
raw-checker-failed,
|
||||
bad-inline-option,
|
||||
locally-disabled,
|
||||
file-ignored,
|
||||
suppressed-message,
|
||||
useless-suppression,
|
||||
deprecated-pragma,
|
||||
use-symbolic-message-instead,
|
||||
apply-builtin,
|
||||
basestring-builtin,
|
||||
buffer-builtin,
|
||||
cmp-builtin,
|
||||
coerce-builtin,
|
||||
execfile-builtin,
|
||||
file-builtin,
|
||||
long-builtin,
|
||||
raw_input-builtin,
|
||||
reduce-builtin,
|
||||
standarderror-builtin,
|
||||
unicode-builtin,
|
||||
xrange-builtin,
|
||||
coerce-method,
|
||||
delslice-method,
|
||||
getslice-method,
|
||||
setslice-method,
|
||||
no-absolute-import,
|
||||
old-division,
|
||||
dict-iter-method,
|
||||
dict-view-method,
|
||||
next-method-called,
|
||||
metaclass-assignment,
|
||||
indexing-exception,
|
||||
raising-string,
|
||||
reload-builtin,
|
||||
oct-method,
|
||||
hex-method,
|
||||
nonzero-method,
|
||||
cmp-method,
|
||||
input-builtin,
|
||||
round-builtin,
|
||||
intern-builtin,
|
||||
unichr-builtin,
|
||||
map-builtin-not-iterating,
|
||||
zip-builtin-not-iterating,
|
||||
range-builtin-not-iterating,
|
||||
filter-builtin-not-iterating,
|
||||
using-cmp-argument,
|
||||
eq-without-hash,
|
||||
div-method,
|
||||
idiv-method,
|
||||
rdiv-method,
|
||||
exception-message-attribute,
|
||||
invalid-str-codec,
|
||||
sys-max-int,
|
||||
bad-python3-import,
|
||||
deprecated-string-function,
|
||||
deprecated-str-translate-call,
|
||||
deprecated-itertools-function,
|
||||
deprecated-types-field,
|
||||
next-method-defined,
|
||||
dict-items-not-iterating,
|
||||
dict-keys-not-iterating,
|
||||
dict-values-not-iterating,
|
||||
deprecated-operator-function,
|
||||
deprecated-urllib-function,
|
||||
xreadlines-attribute,
|
||||
deprecated-sys-function,
|
||||
exception-escape,
|
||||
comprehension-escape
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
# multiple time (only on the command line, not in the configuration file where
|
||||
# it should appear only once). See also the "--disable" option for examples.
|
||||
enable=c-extension-no-member
|
||||
|
||||
|
||||
[REPORTS]
|
||||
|
||||
# Python expression which should return a score less than or equal to 10. You
|
||||
# have access to the variables 'error', 'warning', 'refactor', and 'convention'
|
||||
# which contain the number of messages in each category, as well as 'statement'
|
||||
# which is the total number of statements analyzed. This score is used by the
|
||||
# global evaluation report (RP0004).
|
||||
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
|
||||
|
||||
# Template used to display messages. This is a python new-style format string
|
||||
# used to format the message information. See doc for all details.
|
||||
#msg-template=
|
||||
|
||||
# Set the output format. Available formats are text, parseable, colorized, json
|
||||
# and msvs (visual studio). You can also give a reporter class, e.g.
|
||||
# mypackage.mymodule.MyReporterClass.
|
||||
output-format=text
|
||||
|
||||
# Tells whether to display a full report or only the messages.
|
||||
reports=no
|
||||
|
||||
# Activate the evaluation score.
|
||||
score=yes
|
||||
|
||||
|
||||
[REFACTORING]
|
||||
|
||||
# Maximum number of nested blocks for function / method body
|
||||
max-nested-blocks=5
|
||||
|
||||
# Complete name of functions that never returns. When checking for
|
||||
# inconsistent-return-statements if a never returning function is called then
|
||||
# it will be considered as an explicit return statement and no message will be
|
||||
# printed.
|
||||
never-returning-functions=sys.exit
|
||||
|
||||
|
||||
[SPELLING]
|
||||
|
||||
# Limits count of emitted suggestions for spelling mistakes.
|
||||
max-spelling-suggestions=4
|
||||
|
||||
# Spelling dictionary name. Available dictionaries: none. To make it work,
|
||||
# install the python-enchant package.
|
||||
spelling-dict=
|
||||
|
||||
# List of comma separated words that should not be checked.
|
||||
spelling-ignore-words=
|
||||
|
||||
# A path to a file that contains the private dictionary; one word per line.
|
||||
spelling-private-dict-file=
|
||||
|
||||
# Tells whether to store unknown words to the private dictionary (see the
|
||||
# --spelling-private-dict-file option) instead of raising a message.
|
||||
spelling-store-unknown-words=no
|
||||
|
||||
|
||||
[TYPECHECK]
|
||||
|
||||
# List of decorators that produce context managers, such as
|
||||
# contextlib.contextmanager. Add to this list to register other decorators that
|
||||
# produce valid context managers.
|
||||
contextmanager-decorators=contextlib.contextmanager
|
||||
|
||||
# List of members which are set dynamically and missed by pylint inference
|
||||
# system, and so shouldn't trigger E1101 when accessed. Python regular
|
||||
# expressions are accepted.
|
||||
generated-members=
|
||||
|
||||
# Tells whether missing members accessed in mixin class should be ignored. A
|
||||
# mixin class is detected if its name ends with "mixin" (case insensitive).
|
||||
ignore-mixin-members=yes
|
||||
|
||||
# Tells whether to warn about missing members when the owner of the attribute
|
||||
# is inferred to be None.
|
||||
ignore-none=yes
|
||||
|
||||
# This flag controls whether pylint should warn about no-member and similar
|
||||
# checks whenever an opaque object is returned when inferring. The inference
|
||||
# can return multiple potential results while evaluating a Python object, but
|
||||
# some branches might not be evaluated, which results in partial inference. In
|
||||
# that case, it might be useful to still emit no-member and other checks for
|
||||
# the rest of the inferred objects.
|
||||
ignore-on-opaque-inference=yes
|
||||
|
||||
# List of class names for which member attributes should not be checked (useful
|
||||
# for classes with dynamically set attributes). This supports the use of
|
||||
# qualified names.
|
||||
ignored-classes=optparse.Values,thread._local,_thread._local
|
||||
|
||||
# List of module names for which member attributes should not be checked
|
||||
# (useful for modules/projects where namespaces are manipulated during runtime
|
||||
# and thus existing member attributes cannot be deduced by static analysis). It
|
||||
# supports qualified module names, as well as Unix pattern matching.
|
||||
ignored-modules=
|
||||
|
||||
# Show a hint with possible names when a member name was not found. The aspect
|
||||
# of finding the hint is based on edit distance.
|
||||
missing-member-hint=yes
|
||||
|
||||
# The minimum edit distance a name should have in order to be considered a
|
||||
# similar match for a missing member name.
|
||||
missing-member-hint-distance=1
|
||||
|
||||
# The total number of similar names that should be taken in consideration when
|
||||
# showing a hint for a missing member.
|
||||
missing-member-max-choices=1
|
||||
|
||||
# List of decorators that change the signature of a decorated function.
|
||||
signature-mutators=
|
||||
|
||||
|
||||
[STRING]
|
||||
|
||||
# This flag controls whether inconsistent-quotes generates a warning when the
|
||||
# character used as a quote delimiter is used inconsistently within a module.
|
||||
check-quote-consistency=no
|
||||
|
||||
# This flag controls whether the implicit-str-concat should generate a warning
|
||||
# on implicit string concatenation in sequences defined over several lines.
|
||||
check-str-concat-over-line-jumps=no
|
||||
|
||||
|
||||
[FORMAT]
|
||||
|
||||
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
|
||||
expected-line-ending-format=
|
||||
|
||||
# Regexp for a line that is allowed to be longer than the limit.
|
||||
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
|
||||
|
||||
# Number of spaces of indent required inside a hanging or continued line.
|
||||
indent-after-paren=4
|
||||
|
||||
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
|
||||
# tab).
|
||||
indent-string=' '
|
||||
|
||||
# Maximum number of characters on a single line.
|
||||
max-line-length=100
|
||||
|
||||
# Maximum number of lines in a module.
|
||||
max-module-lines=1000
|
||||
|
||||
# Allow the body of a class to be on the same line as the declaration if body
|
||||
# contains single statement.
|
||||
single-line-class-stmt=no
|
||||
|
||||
# Allow the body of an if to be on the same line as the test if there is no
|
||||
# else.
|
||||
single-line-if-stmt=no
|
||||
|
||||
|
||||
[SIMILARITIES]
|
||||
|
||||
# Ignore comments when computing similarities.
|
||||
ignore-comments=yes
|
||||
|
||||
# Ignore docstrings when computing similarities.
|
||||
ignore-docstrings=yes
|
||||
|
||||
# Ignore imports when computing similarities.
|
||||
ignore-imports=no
|
||||
|
||||
# Minimum lines number of a similarity.
|
||||
min-similarity-lines=4
|
||||
|
||||
|
||||
[MISCELLANEOUS]
|
||||
|
||||
# List of note tags to take in consideration, separated by a comma.
|
||||
notes=FIXME,
|
||||
XXX,
|
||||
TODO
|
||||
|
||||
# Regular expression of note tags to take in consideration.
|
||||
#notes-rgx=
|
||||
|
||||
|
||||
[BASIC]
|
||||
|
||||
# Naming style matching correct argument names.
|
||||
argument-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct argument names. Overrides argument-
|
||||
# naming-style.
|
||||
#argument-rgx=
|
||||
|
||||
# Naming style matching correct attribute names.
|
||||
attr-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct attribute names. Overrides attr-naming-
|
||||
# style.
|
||||
#attr-rgx=
|
||||
|
||||
# Bad variable names which should always be refused, separated by a comma.
|
||||
bad-names=foo,
|
||||
bar,
|
||||
baz,
|
||||
toto,
|
||||
tutu,
|
||||
tata
|
||||
|
||||
# Bad variable names regexes, separated by a comma. If names match any regex,
|
||||
# they will always be refused
|
||||
bad-names-rgxs=
|
||||
|
||||
# Naming style matching correct class attribute names.
|
||||
class-attribute-naming-style=any
|
||||
|
||||
# Regular expression matching correct class attribute names. Overrides class-
|
||||
# attribute-naming-style.
|
||||
#class-attribute-rgx=
|
||||
|
||||
# Naming style matching correct class names.
|
||||
class-naming-style=PascalCase
|
||||
|
||||
# Regular expression matching correct class names. Overrides class-naming-
|
||||
# style.
|
||||
#class-rgx=
|
||||
|
||||
# Naming style matching correct constant names.
|
||||
const-naming-style=UPPER_CASE
|
||||
|
||||
# Regular expression matching correct constant names. Overrides const-naming-
|
||||
# style.
|
||||
#const-rgx=
|
||||
|
||||
# Minimum line length for functions/classes that require docstrings, shorter
|
||||
# ones are exempt.
|
||||
docstring-min-length=-1
|
||||
|
||||
# Naming style matching correct function names.
|
||||
function-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct function names. Overrides function-
|
||||
# naming-style.
|
||||
#function-rgx=
|
||||
|
||||
# Good variable names which should always be accepted, separated by a comma.
|
||||
good-names=i,
|
||||
j,
|
||||
k,
|
||||
ex,
|
||||
Run,
|
||||
_
|
||||
|
||||
# Good variable names regexes, separated by a comma. If names match any regex,
|
||||
# they will always be accepted
|
||||
good-names-rgxs=
|
||||
|
||||
# Include a hint for the correct naming format with invalid-name.
|
||||
include-naming-hint=no
|
||||
|
||||
# Naming style matching correct inline iteration names.
|
||||
inlinevar-naming-style=any
|
||||
|
||||
# Regular expression matching correct inline iteration names. Overrides
|
||||
# inlinevar-naming-style.
|
||||
#inlinevar-rgx=
|
||||
|
||||
# Naming style matching correct method names.
|
||||
method-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct method names. Overrides method-naming-
|
||||
# style.
|
||||
#method-rgx=
|
||||
|
||||
# Naming style matching correct module names.
|
||||
module-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct module names. Overrides module-naming-
|
||||
# style.
|
||||
#module-rgx=
|
||||
|
||||
# Colon-delimited sets of names that determine each other's naming style when
|
||||
# the name regexes allow several styles.
|
||||
name-group=
|
||||
|
||||
# Regular expression which should only match function or class names that do
|
||||
# not require a docstring.
|
||||
no-docstring-rgx=^_
|
||||
|
||||
# List of decorators that produce properties, such as abc.abstractproperty. Add
|
||||
# to this list to register other decorators that produce valid properties.
|
||||
# These decorators are taken in consideration only for invalid-name.
|
||||
property-classes=abc.abstractproperty
|
||||
|
||||
# Naming style matching correct variable names.
|
||||
variable-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct variable names. Overrides variable-
|
||||
# naming-style.
|
||||
#variable-rgx=
|
||||
|
||||
|
||||
[VARIABLES]
|
||||
|
||||
# List of additional names supposed to be defined in builtins. Remember that
|
||||
# you should avoid defining new builtins when possible.
|
||||
additional-builtins=
|
||||
|
||||
# Tells whether unused global variables should be treated as a violation.
|
||||
allow-global-unused-variables=yes
|
||||
|
||||
# List of strings which can identify a callback function by name. A callback
|
||||
# name must start or end with one of those strings.
|
||||
callbacks=cb_,
|
||||
_cb
|
||||
|
||||
# A regular expression matching the name of dummy variables (i.e. expected to
|
||||
# not be used).
|
||||
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
|
||||
|
||||
# Argument names that match this expression will be ignored. Default to name
|
||||
# with leading underscore.
|
||||
ignored-argument-names=_.*|^ignored_|^unused_
|
||||
|
||||
# Tells whether we should check for unused import in __init__ files.
|
||||
init-import=no
|
||||
|
||||
# List of qualified module names which can have objects that can redefine
|
||||
# builtins.
|
||||
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
|
||||
|
||||
|
||||
[LOGGING]
|
||||
|
||||
# The type of string formatting that logging methods do. `old` means using %
|
||||
# formatting, `new` is for `{}` formatting.
|
||||
logging-format-style=fstr
|
||||
|
||||
# Logging modules to check that the string format arguments are in logging
|
||||
# function parameter format.
|
||||
logging-modules=logging
|
||||
|
||||
|
||||
[DESIGN]
|
||||
|
||||
# Maximum number of arguments for function / method.
|
||||
max-args=5
|
||||
|
||||
# Maximum number of attributes for a class (see R0902).
|
||||
max-attributes=7
|
||||
|
||||
# Maximum number of boolean expressions in an if statement (see R0916).
|
||||
max-bool-expr=5
|
||||
|
||||
# Maximum number of branch for function / method body.
|
||||
max-branches=12
|
||||
|
||||
# Maximum number of locals for function / method body.
|
||||
max-locals=15
|
||||
|
||||
# Maximum number of parents for a class (see R0901).
|
||||
max-parents=7
|
||||
|
||||
# Maximum number of public methods for a class (see R0904).
|
||||
max-public-methods=20
|
||||
|
||||
# Maximum number of return / yield for function / method body.
|
||||
max-returns=6
|
||||
|
||||
# Maximum number of statements in function / method body.
|
||||
max-statements=50
|
||||
|
||||
# Minimum number of public methods for a class (see R0903).
|
||||
min-public-methods=2
|
||||
|
||||
|
||||
[CLASSES]
|
||||
|
||||
# List of method names used to declare (i.e. assign) instance attributes.
|
||||
defining-attr-methods=__init__,
|
||||
__new__,
|
||||
setUp,
|
||||
__post_init__
|
||||
|
||||
# List of member names, which should be excluded from the protected access
|
||||
# warning.
|
||||
exclude-protected=_asdict,
|
||||
_fields,
|
||||
_replace,
|
||||
_source,
|
||||
_make
|
||||
|
||||
# List of valid names for the first argument in a class method.
|
||||
valid-classmethod-first-arg=cls
|
||||
|
||||
# List of valid names for the first argument in a metaclass class method.
|
||||
valid-metaclass-classmethod-first-arg=cls
|
||||
|
||||
|
||||
[IMPORTS]
|
||||
|
||||
# List of modules that can be imported at any level, not just the top level
|
||||
# one.
|
||||
allow-any-import-level=
|
||||
|
||||
# Allow wildcard imports from modules that define __all__.
|
||||
allow-wildcard-with-all=no
|
||||
|
||||
# Analyse import fallback blocks. This can be used to support both Python 2 and
|
||||
# 3 compatible code, which means that the block might have code that exists
|
||||
# only in one or another interpreter, leading to false positives when analysed.
|
||||
analyse-fallback-blocks=no
|
||||
|
||||
# Deprecated modules which should not be used, separated by a comma.
|
||||
deprecated-modules=optparse,tkinter.tix
|
||||
|
||||
# Create a graph of external dependencies in the given file (report RP0402 must
|
||||
# not be disabled).
|
||||
ext-import-graph=
|
||||
|
||||
# Create a graph of every (i.e. internal and external) dependencies in the
|
||||
# given file (report RP0402 must not be disabled).
|
||||
import-graph=
|
||||
|
||||
# Create a graph of internal dependencies in the given file (report RP0402 must
|
||||
# not be disabled).
|
||||
int-import-graph=
|
||||
|
||||
# Force import order to recognize a module as part of the standard
|
||||
# compatibility libraries.
|
||||
known-standard-library=
|
||||
|
||||
# Force import order to recognize a module as part of a third party library.
|
||||
known-third-party=enchant
|
||||
|
||||
# Couples of modules and preferred modules, separated by a comma.
|
||||
preferred-modules=
|
||||
|
||||
|
||||
[EXCEPTIONS]
|
||||
|
||||
# Exceptions that will emit a warning when being caught. Defaults to
|
||||
# "BaseException, Exception".
|
||||
overgeneral-exceptions=BaseException,
|
||||
Exception
|
12
.vscode/launch.json
vendored
Normal file
12
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Python: Launch Frigate",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"module": "frigate",
|
||||
"justMyCode": true
|
||||
}
|
||||
]
|
||||
}
|
4
CODEOWNERS
Normal file
4
CODEOWNERS
Normal file
@@ -0,0 +1,4 @@
|
||||
# Community-supported boards
|
||||
/docker/tensorrt/ @madsciencetist @NateMeyer
|
||||
/docker/tensorrt/*arm64* @madsciencetist
|
||||
/docker/tensorrt/*jetson* @madsciencetist
|
65
Makefile
65
Makefile
@@ -1,49 +1,42 @@
|
||||
default_target: amd64_frigate
|
||||
default_target: local
|
||||
|
||||
amd64_wheels:
|
||||
docker build --tag blakeblackshear/frigate-wheels:amd64 --file docker/Dockerfile.wheels .
|
||||
COMMIT_HASH := $(shell git log -1 --pretty=format:"%h"|tail -1)
|
||||
VERSION = 0.13.0
|
||||
IMAGE_REPO ?= ghcr.io/blakeblackshear/frigate
|
||||
GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
CURRENT_UID := $(shell id -u)
|
||||
CURRENT_GID := $(shell id -g)
|
||||
BOARDS= #Initialized empty
|
||||
|
||||
amd64_ffmpeg:
|
||||
docker build --tag blakeblackshear/frigate-ffmpeg:amd64 --file docker/Dockerfile.ffmpeg.amd64 .
|
||||
include docker/*/*.mk
|
||||
|
||||
amd64_frigate:
|
||||
docker build --tag frigate-base --build-arg ARCH=amd64 --file docker/Dockerfile.base .
|
||||
docker build --tag frigate --file docker/Dockerfile.amd64 .
|
||||
build-boards: $(BOARDS:%=build-%)
|
||||
|
||||
amd64_all: amd64_wheels amd64_ffmpeg amd64_frigate
|
||||
push-boards: $(BOARDS:%=push-%)
|
||||
|
||||
amd64nvidia_wheels:
|
||||
docker build --tag blakeblackshear/frigate-wheels:amd64nvidia --file docker/Dockerfile.wheels .
|
||||
version:
|
||||
echo 'VERSION = "$(VERSION)-$(COMMIT_HASH)"' > frigate/version.py
|
||||
|
||||
amd64nvidia_ffmpeg:
|
||||
docker build --tag blakeblackshear/frigate-ffmpeg:amd64nvidia --file docker/Dockerfile.ffmpeg.amd64nvidia .
|
||||
local: version
|
||||
docker buildx build --target=frigate --tag frigate:latest --load --file docker/main/Dockerfile .
|
||||
|
||||
amd64nvidia_frigate:
|
||||
docker build --tag frigate-base --build-arg ARCH=amd64nvidia --file docker/Dockerfile.base .
|
||||
docker build --tag frigate --file docker/Dockerfile.amd64nvidia .
|
||||
amd64:
|
||||
docker buildx build --platform linux/amd64 --target=frigate --tag $(IMAGE_REPO):$(VERSION)-$(COMMIT_HASH) --file docker/main/Dockerfile .
|
||||
|
||||
amd64nvidia_all: amd64nvidia_wheels amd64nvidia_ffmpeg amd64nvidia_frigate
|
||||
arm64:
|
||||
docker buildx build --platform linux/arm64 --target=frigate --tag $(IMAGE_REPO):$(VERSION)-$(COMMIT_HASH) --file docker/main/Dockerfile .
|
||||
|
||||
aarch64_wheels:
|
||||
docker build --tag blakeblackshear/frigate-wheels:aarch64 --file docker/Dockerfile.wheels.aarch64 .
|
||||
build: version amd64 arm64
|
||||
docker buildx build --platform linux/arm64/v8,linux/amd64 --target=frigate --tag $(IMAGE_REPO):$(VERSION)-$(COMMIT_HASH) --file docker/main/Dockerfile .
|
||||
|
||||
aarch64_ffmpeg:
|
||||
docker build --tag blakeblackshear/frigate-ffmpeg:aarch64 --file docker/Dockerfile.ffmpeg.aarch64 .
|
||||
push: push-boards
|
||||
docker buildx build --push --platform linux/arm64/v8,linux/amd64 --target=frigate --tag $(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH) --file docker/main/Dockerfile .
|
||||
|
||||
aarch64_frigate:
|
||||
docker build --tag frigate-base --build-arg ARCH=aarch64 --file docker/Dockerfile.base .
|
||||
docker build --tag frigate --file docker/Dockerfile.aarch64 .
|
||||
run: local
|
||||
docker run --rm --publish=5000:5000 --volume=${PWD}/config:/config frigate:latest
|
||||
|
||||
armv7_all: armv7_wheels armv7_ffmpeg armv7_frigate
|
||||
run_tests: local
|
||||
docker run --rm --workdir=/opt/frigate --entrypoint= frigate:latest python3 -u -m unittest
|
||||
docker run --rm --workdir=/opt/frigate --entrypoint= frigate:latest python3 -u -m mypy --config-file frigate/mypy.ini frigate
|
||||
|
||||
armv7_wheels:
|
||||
docker build --tag blakeblackshear/frigate-wheels:armv7 --file docker/Dockerfile.wheels .
|
||||
|
||||
armv7_ffmpeg:
|
||||
docker build --tag blakeblackshear/frigate-ffmpeg:armv7 --file docker/Dockerfile.ffmpeg.armv7 .
|
||||
|
||||
armv7_frigate:
|
||||
docker build --tag frigate-base --build-arg ARCH=armv7 --file docker/Dockerfile.base .
|
||||
docker build --tag frigate --file docker/Dockerfile.armv7 .
|
||||
|
||||
armv7_all: armv7_wheels armv7_ffmpeg armv7_frigate
|
||||
.PHONY: run_tests
|
||||
|
783
README.md
783
README.md
@@ -1,783 +1,46 @@
|
||||
<p align="center">
|
||||
<img align="center" alt="logo" src="docs/frigate.png">
|
||||
<img align="center" alt="logo" src="docs/static/img/frigate.png">
|
||||
</p>
|
||||
|
||||
# Frigate - NVR With Realtime Object Detection for IP Cameras
|
||||
Uses OpenCV and Tensorflow to perform realtime object detection locally for IP cameras. Designed for integration with HomeAssistant or others via MQTT.
|
||||
|
||||
A complete and local NVR designed for [Home Assistant](https://www.home-assistant.io) with AI object detection. Uses OpenCV and Tensorflow to perform realtime object detection locally for IP cameras.
|
||||
|
||||
Use of a [Google Coral Accelerator](https://coral.ai/products/) is optional, but highly recommended. The Coral will outperform even the best CPUs and can process 100+ FPS with very little overhead.
|
||||
|
||||
- Tight integration with Home Assistant via a [custom component](https://github.com/blakeblackshear/frigate-hass-integration)
|
||||
- Designed to minimize resource use and maximize performance by only looking for objects when and where it is necessary
|
||||
- Leverages multiprocessing heavily with an emphasis on realtime over processing every frame
|
||||
- Uses a very low overhead motion detection to determine where to run object detection
|
||||
- Object detection with TensorFlow runs in separate processes for maximum FPS
|
||||
- Communicates over MQTT for easy integration into other systems
|
||||
- Records video with retention settings based on detected objects
|
||||
- 24/7 recording
|
||||
- Re-streaming via RTSP to reduce the number of connections to your camera
|
||||
- WebRTC & MSE support for low-latency live view
|
||||
|
||||
## Documentation
|
||||
- [How Frigate Works](docs/how-frigate-works.md)
|
||||
- [Recommended Hardware](#recommended-hardware)
|
||||
- [Installing](#installing)
|
||||
- [Configuration File](#configuration)
|
||||
- [Optimizing Performance](#optimizing-performance)
|
||||
- [Detectors](#detectors)
|
||||
- [Object Filters](#object-filters)
|
||||
- [Masks](#masks)
|
||||
- [Zones](#zones)
|
||||
- [Integration with HomeAssistant](#integration-with-homeassistant)
|
||||
- [MQTT Topics](#mqtt-topics)
|
||||
- [HTTP Endpoints](#http-endpoints)
|
||||
- [Custom Models](#custom-models)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
|
||||
## Recommended Hardware
|
||||
|Name|Inference Speed|Notes|
|
||||
|----|---------------|-----|
|
||||
|Atomic Pi|16ms|Good option for a dedicated low power board with a small number of cameras. Can leverage Intel QuickSync for stream decoding.|
|
||||
|Intel NUC NUC7i3BNK|8-10ms|Great performance. Can handle many cameras at 5fps depending on typical amounts of motion.|
|
||||
|BMAX B2 Plus|10-12ms|Good balance of performance and cost. Also capable of running many other services at the same time as frigate.|
|
||||
|Minisforum GK41|9-10ms|Great alternative to a NUC with dual Gigabit NICs. Easily handles several 1080p cameras.|
|
||||
|Raspberry Pi 3B (32bit)|60ms|Can handle a small number of cameras, but the detection speeds are slow due to USB 2.0.|
|
||||
|Raspberry Pi 4 (32bit)|15-20ms|Can handle a small number of cameras. The 2GB version runs fine.|
|
||||
|Raspberry Pi 4 (64bit)|10-15ms|Can handle a small number of cameras. The 2GB version runs fine.|
|
||||
View the documentation at https://docs.frigate.video
|
||||
|
||||
[Back to top](#documentation)
|
||||
## Donations
|
||||
|
||||
## Installing
|
||||
If you would like to make a donation to support development, please use [Github Sponsors](https://github.com/sponsors/blakeblackshear).
|
||||
|
||||
### HassOS Addon
|
||||
HassOS users can install via the addon repository. Frigate requires that an MQTT server be running.
|
||||
1. Navigate to Supervisor > Add-on Store > Repositories
|
||||
1. Add https://github.com/blakeblackshear/frigate-hass-addons
|
||||
1. Setup your configuration in the `Configuration` tab
|
||||
1. Start the addon container
|
||||
## Screenshots
|
||||
|
||||
### Docker
|
||||
Make sure you choose the right image for your architecture:
|
||||
|Arch|Image Name|
|
||||
|-|-|
|
||||
|amd64|blakeblackshear/frigate:stable-amd64|
|
||||
|armv7|blakeblackshear/frigate:stable-armv7|
|
||||
|aarch64|blakeblackshear/frigate:stable-aarch64|
|
||||
Integration into Home Assistant
|
||||
|
||||
It is recommended to run with docker-compose:
|
||||
```yaml
|
||||
frigate:
|
||||
container_name: frigate
|
||||
restart: unless-stopped
|
||||
privileged: true
|
||||
image: blakeblackshear/frigate:stable-amd64
|
||||
volumes:
|
||||
- /dev/bus/usb:/dev/bus/usb
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- <path_to_config>:/config
|
||||
- <path_to_directory_for_clips>:/clips
|
||||
- type: tmpfs # 1GB of memory, reduces SSD/SD Card wear
|
||||
target: /cache
|
||||
tmpfs:
|
||||
size: 100000000
|
||||
ports:
|
||||
- "5000:5000"
|
||||
environment:
|
||||
FRIGATE_RTSP_PASSWORD: "password"
|
||||
healthcheck:
|
||||
test: ["CMD", "wget" , "-q", "-O-", "http://localhost:5000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
start_period: 3m
|
||||
```
|
||||
<div>
|
||||
<a href="docs/static/img/media_browser.png"><img src="docs/static/img/media_browser.png" height=400></a>
|
||||
<a href="docs/static/img/notification.png"><img src="docs/static/img/notification.png" height=400></a>
|
||||
</div>
|
||||
|
||||
If you can't use docker compose, you can run the container with:
|
||||
```bash
|
||||
docker run --rm \
|
||||
--name frigate \
|
||||
--privileged \
|
||||
-v /dev/bus/usb:/dev/bus/usb \
|
||||
-v <path_to_config_dir>:/config:ro \
|
||||
-v /etc/localtime:/etc/localtime:ro \
|
||||
-p 5000:5000 \
|
||||
-e FRIGATE_RTSP_PASSWORD='password' \
|
||||
blakeblackshear/frigate:stable-amd64
|
||||
```
|
||||
Also comes with a builtin UI:
|
||||
|
||||
### Kubernetes
|
||||
Use the [helm chart](https://github.com/k8s-at-home/charts/tree/master/charts/frigate).
|
||||
|
||||
### Virtualization
|
||||
For ideal performance, Frigate needs access to underlying hardware for the Coral and GPU devices for ffmpeg decoding. Running Frigate in a VM on top of Proxmox, ESXi, Virtualbox, etc. is not recommended. The virtualization layer typically introduces a sizable amount of overhead for communication with Coral devices.
|
||||
|
||||
#### Proxmox
|
||||
Some people have had success running Frigate in LXC directly with the following config:
|
||||
```
|
||||
arch: amd64
|
||||
cores: 2
|
||||
features: nesting=1
|
||||
hostname: FrigateLXC
|
||||
memory: 4096
|
||||
net0: name=eth0,bridge=vmbr0,firewall=1,hwaddr=2E:76:AE:5A:58:48,ip=dhcp,ip6=auto,type=veth
|
||||
ostype: debian
|
||||
rootfs: local-lvm:vm-115-disk-0,size=12G
|
||||
swap: 512
|
||||
lxc.cgroup.devices.allow: c 189:385 rwm
|
||||
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file
|
||||
lxc.mount.entry: /dev/bus/usb/004/002 dev/bus/usb/004/002 none bind,optional,create=file
|
||||
lxc.apparmor.profile: unconfined
|
||||
lxc.cgroup.devices.allow: a
|
||||
lxc.cap.drop:
|
||||
```
|
||||
|
||||
### Calculating shm-size
|
||||
The default shm-size of 64m is fine for setups with 3 or less 1080p cameras. If frigate is exiting with "Bus error" messages, it could be because you have too many high resolution cameras and you need to specify a higher shm size.
|
||||
|
||||
You can calculate the necessary shm-size for each camera with the following formula:
|
||||
```
|
||||
(width * height * 1.5 * 7 + 270480)/1048576 = <shm size in mb>
|
||||
```
|
||||
[Back to top](#documentation)
|
||||
|
||||
## Configuration
|
||||
HassOS users can manage their configuration directly in the addon Configuration tab. For other installations, the default location for the config file is `/config/config.yml`. This can be overridden with the `CONFIG_FILE` environment variable. Camera specific ffmpeg parameters are documented [here](docs/cameras.md).
|
||||
|
||||
```yaml
|
||||
# Optional: port for http server (default: shown below)
|
||||
web_port: 5000
|
||||
|
||||
# Optional: detectors configuration
|
||||
# USB Coral devices will be auto detected with CPU fallback
|
||||
detectors:
|
||||
# Required: name of the detector
|
||||
coral:
|
||||
# Required: type of the detector
|
||||
# Valid values are 'edgetpu' (requires device property below) and 'cpu'.
|
||||
type: edgetpu
|
||||
# Optional: device name as defined here: https://coral.ai/docs/edgetpu/multiple-edgetpu/#using-the-tensorflow-lite-python-api
|
||||
device: usb
|
||||
|
||||
# Required: mqtt configuration
|
||||
mqtt:
|
||||
# Required: host name
|
||||
host: mqtt.server.com
|
||||
# Optional: port (default: shown below)
|
||||
port: 1883
|
||||
# Optional: topic prefix (default: shown below)
|
||||
# WARNING: must be unique if you are running multiple instances
|
||||
topic_prefix: frigate
|
||||
# Optional: client id (default: shown below)
|
||||
# WARNING: must be unique if you are running multiple instances
|
||||
client_id: frigate
|
||||
# Optional: user
|
||||
user: mqtt_user
|
||||
# Optional: password
|
||||
# NOTE: Environment variables that begin with 'FRIGATE_' may be referenced in {}.
|
||||
# eg. password: '{FRIGATE_MQTT_PASSWORD}'
|
||||
password: password
|
||||
|
||||
# Optional: Global configuration for saving clips
|
||||
save_clips:
|
||||
# Optional: Maximum length of time to retain video during long events. (default: shown below)
|
||||
# NOTE: If an object is being tracked for longer than this amount of time, the cache
|
||||
# will begin to expire and the resulting clip will be the last x seconds of the event.
|
||||
max_seconds: 300
|
||||
# Optional: Location to save event clips. (default: shown below)
|
||||
clips_dir: /clips
|
||||
# Optional: Location to save cache files for creating clips. (default: shown below)
|
||||
# NOTE: To reduce wear on SSDs and SD cards, use a tmpfs volume.
|
||||
cache_dir: /cache
|
||||
|
||||
# Optional: Global ffmpeg args
|
||||
# "ffmpeg" + global_args + input_args + "-i" + input + output_args
|
||||
ffmpeg:
|
||||
# Optional: global ffmpeg args (default: shown below)
|
||||
global_args:
|
||||
- -hide_banner
|
||||
- -loglevel
|
||||
- panic
|
||||
# Optional: global hwaccel args (default: shown below)
|
||||
# NOTE: See hardware acceleration docs for your specific device
|
||||
hwaccel_args: []
|
||||
# Optional: global input args (default: shown below)
|
||||
input_args:
|
||||
- -avoid_negative_ts
|
||||
- make_zero
|
||||
- -fflags
|
||||
- nobuffer
|
||||
- -flags
|
||||
- low_delay
|
||||
- -strict
|
||||
- experimental
|
||||
- -fflags
|
||||
- +genpts+discardcorrupt
|
||||
- -rtsp_transport
|
||||
- tcp
|
||||
- -stimeout
|
||||
- '5000000'
|
||||
- -use_wallclock_as_timestamps
|
||||
- '1'
|
||||
# Optional: global output args (default: shown below)
|
||||
output_args:
|
||||
- -f
|
||||
- rawvideo
|
||||
- -pix_fmt
|
||||
- yuv420p
|
||||
|
||||
# Optional: Global object filters for all cameras.
|
||||
# NOTE: can be overridden at the camera level
|
||||
objects:
|
||||
# Optional: list of objects to track from labelmap.txt (default: shown below)
|
||||
track:
|
||||
- person
|
||||
# Optional: filters to reduce false positives for specific object types
|
||||
filters:
|
||||
person:
|
||||
# Optional: minimum width*height of the bounding box for the detected object (default: 0)
|
||||
min_area: 5000
|
||||
# Optional: maximum width*height of the bounding box for the detected object (default: max_int)
|
||||
max_area: 100000
|
||||
# Optional: minimum score for the object to initiate tracking (default: shown below)
|
||||
min_score: 0.5
|
||||
# Optional: minimum decimal percentage for tracked object's computed score to be considered a true positive (default: shown below)
|
||||
threshold: 0.85
|
||||
|
||||
# Required: configuration section for cameras
|
||||
cameras:
|
||||
# Required: name of the camera
|
||||
back:
|
||||
# Required: ffmpeg settings for the camera
|
||||
ffmpeg:
|
||||
# Required: Source passed to ffmpeg after the -i parameter.
|
||||
# NOTE: Environment variables that begin with 'FRIGATE_' may be referenced in {}
|
||||
input: rtsp://viewer:{FRIGATE_RTSP_PASSWORD}@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2
|
||||
# Optional: camera specific global args (default: inherit)
|
||||
global_args:
|
||||
# Optional: camera specific hwaccel args (default: inherit)
|
||||
hwaccel_args:
|
||||
# Optional: camera specific input args (default: inherit)
|
||||
input_args:
|
||||
# Optional: camera specific output args (default: inherit)
|
||||
output_args:
|
||||
|
||||
# Optional: height of the frame
|
||||
# NOTE: Recommended to set this value, but frigate will attempt to autodetect.
|
||||
height: 720
|
||||
# Optional: width of the frame
|
||||
# NOTE: Recommended to set this value, but frigate will attempt to autodetect.
|
||||
width: 1280
|
||||
# Optional: desired fps for your camera
|
||||
# NOTE: Recommended value of 5. Ideally, try and reduce your FPS on the camera.
|
||||
# Frigate will attempt to autodetect if not specified.
|
||||
fps: 5
|
||||
|
||||
# Optional: motion mask
|
||||
# NOTE: see docs for more detailed info on creating masks
|
||||
mask: poly,0,900,1080,900,1080,1920,0,1920
|
||||
|
||||
# Optional: timeout for highest scoring image before allowing it
|
||||
# to be replaced by a newer image. (default: shown below)
|
||||
best_image_timeout: 60
|
||||
|
||||
# Optional: camera specific mqtt settings
|
||||
mqtt:
|
||||
# Optional: crop the camera frame to the detection region of the object (default: False)
|
||||
crop_to_region: True
|
||||
# Optional: resize the image before publishing over mqtt
|
||||
snapshot_height: 300
|
||||
|
||||
# Optional: zones for this camera
|
||||
zones:
|
||||
# Required: name of the zone
|
||||
# NOTE: This must be different than any camera names, but can match with another zone on another
|
||||
# camera.
|
||||
front_steps:
|
||||
# Required: List of x,y coordinates to define the polygon of the zone.
|
||||
# NOTE: Coordinates can be generated at https://www.image-map.net/
|
||||
coordinates: 545,1077,747,939,788,805
|
||||
# Optional: Zone level object filters.
|
||||
# NOTE: The global and camera filters are applied upstream.
|
||||
filters:
|
||||
person:
|
||||
min_area: 5000
|
||||
max_area: 100000
|
||||
threshold: 0.8
|
||||
|
||||
# Optional: save clips configuration
|
||||
# NOTE: This feature does not work if you have added "-vsync drop" in your input params.
|
||||
# This will only work for camera feeds that can be copied into the mp4 container format without
|
||||
# encoding such as h264. It may not work for some types of streams.
|
||||
save_clips:
|
||||
# Required: enables clips for the camera (default: shown below)
|
||||
enabled: False
|
||||
# Optional: Number of seconds before the event to include in the clips (default: shown below)
|
||||
pre_capture: 30
|
||||
# Optional: Objects to save clips for. (default: all tracked objects)
|
||||
objects:
|
||||
- person
|
||||
|
||||
# Optional: Configuration for the snapshots in the debug view and mqtt
|
||||
snapshots:
|
||||
# Optional: print a timestamp on the snapshots (default: shown below)
|
||||
show_timestamp: True
|
||||
# Optional: draw zones on the debug mjpeg feed (default: shown below)
|
||||
draw_zones: False
|
||||
# Optional: draw bounding boxes on the mqtt snapshots (default: shown below)
|
||||
draw_bounding_boxes: True
|
||||
|
||||
# Optional: Camera level object filters config. If defined, this is used instead of the global config.
|
||||
objects:
|
||||
track:
|
||||
- person
|
||||
- car
|
||||
filters:
|
||||
person:
|
||||
min_area: 5000
|
||||
max_area: 100000
|
||||
min_score: 0.5
|
||||
threshold: 0.85
|
||||
```
|
||||
[Back to top](#documentation)
|
||||
|
||||
## Optimizing Performance
|
||||
- **Google Coral**: It is strongly recommended to use a Google Coral, but Frigate will fall back to CPU in the event one is not found. Offloading TensorFlow to the Google Coral is an order of magnitude faster and will reduce your CPU load dramatically. A $60 device will outperform $2000 CPU.
|
||||
- **Resolution**: Choose a camera resolution where the smallest object you want to detect barely fits inside a 300x300px square. The model used by Frigate is trained on 300x300px images, so you will get worse performance and no improvement in accuracy by using a larger resolution since Frigate resizes the area where it is looking for objects to 300x300 anyway.
|
||||
- **FPS**: 5 frames per second should be adequate. Higher frame rates will require more CPU usage without improving detections or accuracy. Reducing the frame rate on your camera will have the greatest improvement on system resources.
|
||||
- **Hardware Acceleration**: Make sure you configure the `hwaccel_args` for your hardware. They provide a significant reduction in CPU usage if they are available.
|
||||
- **Masks**: Masks can be used to ignore motion and reduce your idle CPU load. If you have areas with regular motion such as timestamps or trees blowing in the wind, frigate will constantly try to determine if that motion is from a person or other object you are tracking. Those detections not only increase your average CPU usage, but also clog the pipeline for detecting objects elsewhere. If you are experiencing high values for `detection_fps` when no objects of interest are in the cameras, you should use masks to tell frigate to ignore movement from trees, bushes, timestamps, or any part of the image where detections should not be wasted looking for objects.
|
||||
|
||||
### FFmpeg Hardware Acceleration
|
||||
Frigate works on Raspberry Pi 3b/4 and x86 machines. It is recommended to update your configuration to enable hardware accelerated decoding in ffmpeg. Depending on your system, these parameters may not be compatible.
|
||||
|
||||
Raspberry Pi 3/4 (32-bit OS):
|
||||
```yaml
|
||||
ffmpeg:
|
||||
hwaccel_args:
|
||||
- -c:v
|
||||
- h264_mmal
|
||||
```
|
||||
|
||||
Raspberry Pi 3/4 (64-bit OS)
|
||||
```yaml
|
||||
ffmpeg:
|
||||
hwaccel_args:
|
||||
- -c:v
|
||||
- h264_v4l2m2m
|
||||
```
|
||||
|
||||
Intel-based CPUs (<10th Generation) via Quicksync (https://trac.ffmpeg.org/wiki/Hardware/QuickSync)
|
||||
```yaml
|
||||
ffmpeg:
|
||||
hwaccel_args:
|
||||
- -hwaccel
|
||||
- vaapi
|
||||
- -hwaccel_device
|
||||
- /dev/dri/renderD128
|
||||
- -hwaccel_output_format
|
||||
- yuv420p
|
||||
```
|
||||
|
||||
Intel-based CPUs (>=10th Generation) via Quicksync (https://trac.ffmpeg.org/wiki/Hardware/QuickSync)
|
||||
**Note:** You also need to set `LIBVA_DRIVER_NAME=iHD` as an environment variable on the container.
|
||||
```yaml
|
||||
ffmpeg:
|
||||
hwaccel_args:
|
||||
- -hwaccel
|
||||
- vaapi
|
||||
- -hwaccel_device
|
||||
- /dev/dri/renderD128
|
||||
```
|
||||
|
||||
Nvidia GPU based decoding via NVDEC is supported, but requires special configuration. See the [nvidia NVDEC documentation](docs/nvdec.md) for more details.
|
||||
|
||||
[Back to top](#documentation)
|
||||
|
||||
## Detectors
|
||||
By default Frigate will look for a USB Coral device and fall back to the CPU if it cannot be found. If you have PCI or multiple Coral devices, you need to configure your detector devices in the config file. When using multiple detectors, they run in dedicated processes, but pull from a common queue of requested detections across all cameras.
|
||||
|
||||
Frigate supports `edgetpu` and `cpu` as detector types. The device value should be specified according to the [Documentation for the TensorFlow Lite Python API](https://coral.ai/docs/edgetpu/multiple-edgetpu/#using-the-tensorflow-lite-python-api).
|
||||
|
||||
Single USB Coral:
|
||||
```yaml
|
||||
detectors:
|
||||
coral:
|
||||
type: edgetpu
|
||||
device: usb
|
||||
```
|
||||
|
||||
Multiple USB Corals:
|
||||
```yaml
|
||||
detectors:
|
||||
coral1:
|
||||
type: edgetpu
|
||||
device: usb:0
|
||||
coral2:
|
||||
type: edgetpu
|
||||
device: usb:1
|
||||
```
|
||||
|
||||
Mixing Corals:
|
||||
```yaml
|
||||
detectors:
|
||||
coral_usb:
|
||||
type: edgetpu
|
||||
device: usb
|
||||
coral_pci:
|
||||
type: edgetpu
|
||||
device: pci
|
||||
```
|
||||
|
||||
CPU Detectors (not recommended):
|
||||
```yaml
|
||||
detectors:
|
||||
cpu1:
|
||||
type: cpu
|
||||
cpu2:
|
||||
type: cpu
|
||||
```
|
||||
[Back to top](#documentation)
|
||||
|
||||
## Reducing False Positives
|
||||
Tune your object filters to adjust false positives: `min_area`, `max_area`, `min_score`, `threshold`.
|
||||
|
||||
For object filters in your configuration, any single detection below `min_score` will be ignored as a false positive. `threshold` is based on the median of the history of scores (padded to 3 values) for a tracked object. Consider the following frames when `min_score` is set to 0.6 and threshold is set to 0.85:
|
||||
|
||||
| Frame | Current Score | Score History | Computed Score | Detected Object |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | 0.7 | 0.0, 0, 0.7 | 0.0 | No
|
||||
| 2 | 0.55 | 0.0, 0.7, 0.0 | 0.0 | No
|
||||
| 3 | 0.85 | 0.7, 0.0, 0.85 | 0.7 | No
|
||||
| 4 | 0.90 | 0.7, 0.85, 0.95, 0.90 | 0.875 | Yes
|
||||
| 5 | 0.88 | 0.7, 0.85, 0.95, 0.90, 0.88 | 0.88 | Yes
|
||||
| 6 | 0.95 | 0.7, 0.85, 0.95, 0.90, 0.88, 0.95 | 0.89 | Yes
|
||||
|
||||
In frame 2, the score is below the `min_score` value, so frigate ignores it and it becomes a 0.0. The computed score is the median of the score history (padding to at least 3 values), and only when that computed score crosses the `threshold` is the object marked as a true positive. That happens in frame 4 in the example.
|
||||
|
||||
[Back to top](#documentation)
|
||||
|
||||
## Masks
|
||||
The following types of masks are supported:
|
||||
- `poly`: (Recommended) List of x,y points like zone configuration
|
||||
- `base64`: Base64 encoded image file
|
||||
- `image`: Image file in the `/config` directory
|
||||
|
||||
`base64` and `image` masks must be the same aspect ratio and resolution as your camera.
|
||||
|
||||
The mask in the second image would limit motion detection on this camera to only the front yard and not the street.
|
||||
|
||||
<a href="docs/example-mask-check-point.png"><img src="docs/example-mask-check-point.png" height="300"></a>
|
||||
<a href="docs/example-mask.bmp"><img src="docs/example-mask.bmp" height="300"></a>
|
||||
<a href="docs/example-mask-overlay.png"><img src="docs/example-mask-overlay.png" height="300"></a>
|
||||
|
||||
To create a poly mask:
|
||||
1. Download a camera snapshot image with the same resolution as the camera feed (`/<camera_name>/latest.jpg`).
|
||||
1. Upload the image to https://www.image-map.net/
|
||||
1. Select "shape" poly - start in the lowest left corner and place the first marker (point) and continue upwards and then to the right until the polygon shape covers the area that you want to mask out (ignore).
|
||||
1. When you are finished with the polygon click "Show me the code!" and copy all coordinates (point), ie. `"0,461,3,0,1919,0,1919,843,1699,492,1344,458,1346,336,973,317,869,375,866,432"`
|
||||
1. Adjust any -1 values to 0 and then add it all to the configuration (see the example configuration for correct indentation and placement)
|
||||
|
||||
Example of a finished row corresponding to the below example image:
|
||||
```yaml
|
||||
mask: 'poly,0,461,3,0,1919,0,1919,843,1699,492,1344,458,1346,336,973,317,869,375,866,432'
|
||||
```
|
||||
|
||||
<a href="docs/example-mask-poly.png"><img src="docs/example-mask-poly.png" height="300"></a>
|
||||
|
||||
You can test your mask by temporarily configuring it as a [zone](#zones) and enabling `draw_zones` in your config. Zones are visible on the [MJPEG feed](#camera_name).
|
||||
|
||||
[Back to top](#documentation)
|
||||
|
||||
## Zones
|
||||
Zones allow you to define a specific area of the frame and apply additional filters for object types so you can determine whether or not an object is within a particular area. Zones cannot have the same name as a camera. If desired, a single zone can include multiple cameras if you have multiple cameras covering the same area by configuring zones with the same name for each camera.
|
||||
|
||||
During testing, `draw_zones` should be set in the config to draw the zone on the frames so you can adjust as needed. The zone line will increase in thickness when any object enters the zone. Zones are visible on the [MJPEG feed](#camera_name).
|
||||
|
||||

|
||||
|
||||
[Back to top](#documentation)
|
||||
|
||||
## Recording Clips
|
||||
**Note**: Previous versions of frigate included `-vsync drop` in input parameters. This is not compatible with FFmpeg's segment feature and must be removed from your input parameters if you have overrides set.
|
||||
|
||||
Frigate can save video clips without any CPU overhead for encoding by simply copying the stream directly with FFmpeg. It leverages FFmpeg's segment functionality to maintain a cache of video for each camera. The cache files are written to disk at `cache_dir` and do not introduce memory overhead. When an object is being tracked, it will extend the cache to ensure it can assemble a clip when the event ends. Once the event ends, it again uses FFmpeg to assemble a clip by combining the video clips without any encoding by the CPU. Assembled clips are are saved to the `clips_dir` directory along with a json file containing the current information about the tracked object.
|
||||
|
||||
### Global Configuration Options
|
||||
- `max_seconds`: This limits the size of the cache when an object is being tracked. If an object is stationary and being tracked for a long time, the cache files will expire and this value will be the maximum clip length for the *end* of the event. For example, if this is set to 300 seconds and an object is being tracked for 600 seconds, the clip will end up being the last 300 seconds. Defaults to 300 seconds.
|
||||
|
||||
### Per-camera Configuration Options
|
||||
- `pre_capture`: Defines how much time should be included in the clip prior to the beginning of the event. Defaults to 30 seconds.
|
||||
- `objects`: List of object types to save clips for. Object types here must be listed for tracking at the camera or global configuration. Defaults to all tracked objects.
|
||||
|
||||
[Back to top](#documentation)
|
||||
|
||||
## Integration with HomeAssistant
|
||||
Setup a camera, binary_sensor, sensor and optionally automation as shown for each camera you define in frigate. Replace <camera_name> with the camera name as defined in the frigate `config.yml` (The `frigate_coral_fps` and `frigate_coral_inference` sensors only need to be defined once)
|
||||
|
||||
```yaml
|
||||
camera:
|
||||
- name: <camera_name> Last Person
|
||||
platform: mqtt
|
||||
topic: frigate/<camera_name>/person/snapshot
|
||||
- name: <camera_name> Last Car
|
||||
platform: mqtt
|
||||
topic: frigate/<camera_name>/car/snapshot
|
||||
|
||||
binary_sensor:
|
||||
- name: <camera_name> Person
|
||||
platform: mqtt
|
||||
state_topic: "frigate/<camera_name>/person"
|
||||
device_class: motion
|
||||
availability_topic: "frigate/available"
|
||||
|
||||
sensor:
|
||||
- platform: rest
|
||||
name: Frigate Debug
|
||||
resource: http://localhost:5000/debug/stats
|
||||
scan_interval: 5
|
||||
json_attributes:
|
||||
- <camera_name>
|
||||
- detection_fps
|
||||
- detectors
|
||||
value_template: 'OK'
|
||||
- platform: template
|
||||
sensors:
|
||||
<camera_name>_fps:
|
||||
value_template: '{{ states.sensor.frigate_debug.attributes["<camera_name>"]["camera_fps"] }}'
|
||||
unit_of_measurement: 'FPS'
|
||||
<camera_name>_skipped_fps:
|
||||
value_template: '{{ states.sensor.frigate_debug.attributes["<camera_name>"]["skipped_fps"] }}'
|
||||
unit_of_measurement: 'FPS'
|
||||
<camera_name>_detection_fps:
|
||||
value_template: '{{ states.sensor.frigate_debug.attributes["<camera_name>"]["detection_fps"] }}'
|
||||
unit_of_measurement: 'FPS'
|
||||
frigate_detection_fps:
|
||||
value_template: '{{ states.sensor.frigate_debug.attributes["detection_fps"] }}'
|
||||
unit_of_measurement: 'FPS'
|
||||
frigate_coral_inference:
|
||||
value_template: '{{ states.sensor.frigate_debug.attributes["detectors"]["coral"]["inference_speed"] }}'
|
||||
unit_of_measurement: 'ms'
|
||||
|
||||
automation:
|
||||
- alias: Alert me if a person is detected while armed away
|
||||
trigger:
|
||||
platform: state
|
||||
entity_id: binary_sensor.camera_person
|
||||
from: 'off'
|
||||
to: 'on'
|
||||
condition:
|
||||
- condition: state
|
||||
entity_id: alarm_control_panel.home_alarm
|
||||
state: armed_away
|
||||
action:
|
||||
- service: notify.user_telegram
|
||||
data:
|
||||
message: "A person was detected."
|
||||
data:
|
||||
photo:
|
||||
- url: http://<ip>:5000/<camera_name>/person/best.jpg
|
||||
caption: A person was detected.
|
||||
```
|
||||
|
||||
[Back to top](#documentation)
|
||||
|
||||
## HTTP Endpoints
|
||||
A web server is available on port 5000 with the following endpoints.
|
||||
|
||||
### `/<camera_name>`
|
||||
An mjpeg stream for debugging. Keep in mind the mjpeg endpoint is for debugging only and will put additional load on the system when in use.
|
||||
|
||||
You can access a higher resolution mjpeg stream by appending `h=height-in-pixels` to the endpoint. For example `http://localhost:5000/back?h=1080`. You can also increase the FPS by appending `fps=frame-rate` to the URL such as `http://localhost:5000/back?fps=10` or both with `?fps=10&h=1000`
|
||||
|
||||
### `/<camera_name>/<object_name>/best.jpg[?h=300&crop=1]`
|
||||
The best snapshot for any object type. It is a full resolution image by default.
|
||||
|
||||
Example parameters:
|
||||
- `h=300`: resizes the image to 300 pixes tall
|
||||
- `crop=1`: crops the image to the region of the detection rather than returning the entire image
|
||||
|
||||
### `/<camera_name>/latest.jpg[?h=300]`
|
||||
The most recent frame that frigate has finished processing. It is a full resolution image by default.
|
||||
|
||||
Example parameters:
|
||||
- `h=300`: resizes the image to 300 pixes tall
|
||||
|
||||
### `/debug/stats`
|
||||
Contains some granular debug info that can be used for sensors in HomeAssistant.
|
||||
|
||||
Sample response:
|
||||
```jsonc
|
||||
{
|
||||
/* Per Camera Stats */
|
||||
"back": {
|
||||
/***************
|
||||
* Frames per second being consumed from your camera. If this is higher
|
||||
* than it is supposed to be, you should set -r FPS in your input_args.
|
||||
* camera_fps = process_fps + skipped_fps
|
||||
***************/
|
||||
"camera_fps": 5.0,
|
||||
/***************
|
||||
* Number of times detection is run per second. This can be higher than
|
||||
* your camera FPS because frigate often looks at the same frame multiple times
|
||||
* or in multiple locations
|
||||
***************/
|
||||
"detection_fps": 1.5,
|
||||
/***************
|
||||
* PID for the ffmpeg process that consumes this camera
|
||||
***************/
|
||||
"ffmpeg_pid": 27,
|
||||
/***************
|
||||
* Timestamps of frames in various parts of processing
|
||||
***************/
|
||||
"frame_info": {
|
||||
/***************
|
||||
* Timestamp of the frame frigate is running object detection on.
|
||||
***************/
|
||||
"detect": 1596994991.91426,
|
||||
/***************
|
||||
* Timestamp of the frame frigate is processing detected objects on.
|
||||
* This is where MQTT messages are sent, zones are checked, etc.
|
||||
***************/
|
||||
"process": 1596994991.91426,
|
||||
/***************
|
||||
* Timestamp of the frame frigate last read from ffmpeg.
|
||||
***************/
|
||||
"read": 1596994991.91426
|
||||
},
|
||||
/***************
|
||||
* PID for the process that runs detection for this camera
|
||||
***************/
|
||||
"pid": 34,
|
||||
/***************
|
||||
* Frames per second being processed by frigate.
|
||||
***************/
|
||||
"process_fps": 5.1,
|
||||
/***************
|
||||
* Timestamp when the detection process started looking for a frame. If this value stays constant
|
||||
* for a long time, that means there aren't any frames in the frame queue.
|
||||
***************/
|
||||
"read_start": 1596994991.943814,
|
||||
/***************
|
||||
* Frames per second skip for processing by frigate.
|
||||
***************/
|
||||
"skipped_fps": 0.0
|
||||
},
|
||||
/***************
|
||||
* Sum of detection_fps across all cameras and detectors.
|
||||
* This should be the sum of all detection_fps values from cameras.
|
||||
***************/
|
||||
"detection_fps": 5.0,
|
||||
/* Detectors Stats */
|
||||
"detectors": {
|
||||
"coral": {
|
||||
/***************
|
||||
* Timestamp when object detection started. If this value stays non-zero and constant
|
||||
* for a long time, that means the detection process is stuck.
|
||||
***************/
|
||||
"detection_start": 0.0,
|
||||
/***************
|
||||
* Time spent running object detection in milliseconds.
|
||||
***************/
|
||||
"inference_speed": 10.48,
|
||||
/***************
|
||||
* PID for the shared process that runs object detection on the Coral.
|
||||
***************/
|
||||
"pid": 25321
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
[Back to top](#documentation)
|
||||
|
||||
## MQTT Topics
|
||||
These are the MQTT messages generated by Frigate. The default topic_prefix is `frigate`, but can be changed in the config file.
|
||||
|
||||
### `frigate/available`
|
||||
Designed to be used as an availability topic with HomeAssistant. Possible message are:
|
||||
"online": published when frigate is running (on startup)
|
||||
"offline": published right before frigate stops
|
||||
|
||||
### `frigate/<camera_name>/<object_name>`
|
||||
Publishes `ON` or `OFF` and is designed to be used a as a binary sensor in HomeAssistant for whether or not that object type is detected.
|
||||
|
||||
### `frigate/<camera_name>/<object_name>/snapshot`
|
||||
Publishes a jpeg encoded frame of the detected object type. When the object is no longer detected, the highest confidence image is published or the original image
|
||||
is published again.
|
||||
|
||||
The height and crop of snapshots can be configured in the config.
|
||||
|
||||
### `frigate/<camera_name>/events/start`
|
||||
Message published at the start of any tracked object. JSON looks as follows:
|
||||
```json
|
||||
{
|
||||
"label": "person",
|
||||
"score": 0.87890625,
|
||||
"box": [
|
||||
95,
|
||||
155,
|
||||
581,
|
||||
1182
|
||||
],
|
||||
"area": 499122,
|
||||
"region": [
|
||||
0,
|
||||
132,
|
||||
1080,
|
||||
1212
|
||||
],
|
||||
"frame_time": 1600208805.60284,
|
||||
"centroid": [
|
||||
338,
|
||||
668
|
||||
],
|
||||
"id": "1600208805.60284-k1l43p",
|
||||
"start_time": 1600208805.60284,
|
||||
"top_score": 0.87890625,
|
||||
"zones": [],
|
||||
"score_history": [
|
||||
0.87890625
|
||||
],
|
||||
"computed_score": 0.0,
|
||||
"false_positive": true
|
||||
}
|
||||
```
|
||||
|
||||
### `frigate/<camera_name>/events/end`
|
||||
Same as `frigate/<camera_name>/events/start`, but with an `end_time` property as well.
|
||||
|
||||
### `frigate/<zone_name>/<object_name>`
|
||||
Publishes `ON` when the object enters the zone and `OFF` when the object disappears or exits the zone. Designed to be used a as a binary sensor in HomeAssistant for whether or not that object type is detected in the zone.
|
||||
|
||||
[Back to top](#documentation)
|
||||
|
||||
## Custom Models
|
||||
Models for both CPU and EdgeTPU (Coral) are bundled in the image. You can use your own models with volume mounts:
|
||||
- CPU Model: `/cpu_model.tflite`
|
||||
- EdgeTPU Model: `/edgetpu_model.tflite`
|
||||
- Labels: `/labelmap.txt`
|
||||
|
||||
### Customizing the Labelmap
|
||||
The labelmap can be customized to your needs. A common reason to do this is to combine multiple object types that are easily confused when you don't need to be as granular such as car/truck. You must retain the same number of labels, but you can change the names. To change:
|
||||
|
||||
- Download the [COCO labelmap](https://dl.google.com/coral/canned_models/coco_labels.txt)
|
||||
- Modify the label names as desired. For example, change `7 truck` to `7 car`
|
||||
- Mount the new file at `/labelmap.txt` in the container with an additional volume
|
||||
```
|
||||
-v ./config/labelmap.txt:/labelmap.txt
|
||||
```
|
||||
|
||||
[Back to top](#documentation)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "ffmpeg didnt return a frame. something is wrong"
|
||||
Turn on logging for the camera by overriding the global_args and setting the log level to `info`:
|
||||
```yaml
|
||||
ffmpeg:
|
||||
global_args:
|
||||
- -hide_banner
|
||||
- -loglevel
|
||||
- info
|
||||
```
|
||||
|
||||
### "On connect called"
|
||||
If you see repeated "On connect called" messages in your config, check for another instance of frigate. This happens when multiple frigate containers are trying to connect to mqtt with the same client_id.
|
||||
|
||||
[Back to top](#documentation)
|
||||
<div>
|
||||
<a href="docs/static/img/home-ui.png"><img src="docs/static/img/home-ui.png" height=400></a>
|
||||
<a href="docs/static/img/camera-ui.png"><img src="docs/static/img/camera-ui.png" height=400></a>
|
||||
</div>
|
||||
|
||||

|
||||
|
521
audio-labelmap.txt
Normal file
521
audio-labelmap.txt
Normal file
@@ -0,0 +1,521 @@
|
||||
speech
|
||||
speech
|
||||
speech
|
||||
speech
|
||||
babbling
|
||||
speech
|
||||
yell
|
||||
bellow
|
||||
whoop
|
||||
yell
|
||||
yell
|
||||
yell
|
||||
whispering
|
||||
laughter
|
||||
laughter
|
||||
laughter
|
||||
snicker
|
||||
laughter
|
||||
laughter
|
||||
crying
|
||||
crying
|
||||
crying
|
||||
yell
|
||||
sigh
|
||||
singing
|
||||
choir
|
||||
sodeling
|
||||
chant
|
||||
mantra
|
||||
child_singing
|
||||
synthetic_singing
|
||||
rapping
|
||||
humming
|
||||
groan
|
||||
grunt
|
||||
whistling
|
||||
breathing
|
||||
wheeze
|
||||
snoring
|
||||
gasp
|
||||
pant
|
||||
snort
|
||||
cough
|
||||
throat_clearing
|
||||
sneeze
|
||||
sniff
|
||||
run
|
||||
shuffle
|
||||
footsteps
|
||||
chewing
|
||||
biting
|
||||
gargling
|
||||
stomach_rumble
|
||||
burping
|
||||
hiccup
|
||||
fart
|
||||
hands
|
||||
finger_snapping
|
||||
clapping
|
||||
heartbeat
|
||||
heart_murmur
|
||||
cheering
|
||||
applause
|
||||
chatter
|
||||
crowd
|
||||
speech
|
||||
children_playing
|
||||
animal
|
||||
pets
|
||||
dog
|
||||
bark
|
||||
yip
|
||||
howl
|
||||
bow-wow
|
||||
growling
|
||||
whimper_dog
|
||||
cat
|
||||
purr
|
||||
meow
|
||||
hiss
|
||||
caterwaul
|
||||
livestock
|
||||
horse
|
||||
clip-clop
|
||||
neigh
|
||||
cattle
|
||||
moo
|
||||
cowbell
|
||||
pig
|
||||
oink
|
||||
goat
|
||||
bleat
|
||||
sheep
|
||||
fowl
|
||||
chicken
|
||||
cluck
|
||||
cock-a-doodle-doo
|
||||
turkey
|
||||
gobble
|
||||
duck
|
||||
quack
|
||||
goose
|
||||
honk
|
||||
wild_animals
|
||||
roaring_cats
|
||||
roar
|
||||
bird
|
||||
chird
|
||||
chirp
|
||||
squawk
|
||||
pigeon
|
||||
coo
|
||||
crow
|
||||
caw
|
||||
owl
|
||||
hoot
|
||||
flapping_wings
|
||||
dogs
|
||||
rats
|
||||
mouse
|
||||
patter
|
||||
insect
|
||||
cricket
|
||||
mosquito
|
||||
fly
|
||||
buzz
|
||||
buzz
|
||||
frog
|
||||
croak
|
||||
snake
|
||||
rattle
|
||||
whale_vocalization
|
||||
music
|
||||
musical_instrument
|
||||
plucked_string_instrument
|
||||
guitar
|
||||
electric_guitar
|
||||
bass_guitar
|
||||
acoustic_guitar
|
||||
steel_guitar
|
||||
tapping
|
||||
strum
|
||||
banjo
|
||||
sitar
|
||||
mandolin
|
||||
zither
|
||||
ukulele
|
||||
keyboard
|
||||
piano
|
||||
electric_piano
|
||||
organ
|
||||
electronic_organ
|
||||
hammond_organ
|
||||
synthesizer
|
||||
sampler
|
||||
harpsichord
|
||||
percussion
|
||||
drum_kit
|
||||
drum_machine
|
||||
drum
|
||||
snare_drum
|
||||
rimshot
|
||||
drum_roll
|
||||
bass_drum
|
||||
timpani
|
||||
tabla
|
||||
cymbal
|
||||
hi-hat
|
||||
wood_block
|
||||
tambourine
|
||||
rattle
|
||||
maraca
|
||||
gong
|
||||
tubular_bells
|
||||
mallet_percussion
|
||||
marimba
|
||||
glockenspiel
|
||||
vibraphone
|
||||
steelpan
|
||||
orchestra
|
||||
brass_instrument
|
||||
french_horn
|
||||
trumpet
|
||||
trombone
|
||||
bowed_string_instrument
|
||||
string_section
|
||||
violin
|
||||
pizzicato
|
||||
cello
|
||||
double_bass
|
||||
wind_instrument
|
||||
flute
|
||||
saxophone
|
||||
clarinet
|
||||
harp
|
||||
bell
|
||||
church_bell
|
||||
jingle_bell
|
||||
bicycle_bell
|
||||
tuning_fork
|
||||
chime
|
||||
wind_chime
|
||||
change_ringing
|
||||
harmonica
|
||||
accordion
|
||||
bagpipes
|
||||
didgeridoo
|
||||
shofar
|
||||
theremin
|
||||
singing_bowl
|
||||
scratching
|
||||
pop_music
|
||||
hip_hop_music
|
||||
beatboxing
|
||||
rock_music
|
||||
heavy_metal
|
||||
punk_rock
|
||||
grunge
|
||||
progressive_rock
|
||||
rock_and_roll
|
||||
psychedelic_rock
|
||||
rhythm_and_blues
|
||||
soul_music
|
||||
reggae
|
||||
country
|
||||
swing_music
|
||||
bluegrass
|
||||
funk
|
||||
folk_music
|
||||
middle_eastern_music
|
||||
jazz
|
||||
disco
|
||||
classical_music
|
||||
opera
|
||||
electronic_music
|
||||
house_music
|
||||
techno
|
||||
dubstep
|
||||
drum_and_bass
|
||||
electronica
|
||||
electronic_dance_music
|
||||
ambient_music
|
||||
trance_music
|
||||
music_of_latin_america
|
||||
salsa_music
|
||||
flamenco
|
||||
blues
|
||||
music_for_children
|
||||
new-age_music
|
||||
vocal_music
|
||||
a_capella
|
||||
music_of_africa
|
||||
afrobeat
|
||||
christian_music
|
||||
gospel_music
|
||||
music_of_asia
|
||||
carnatic_music
|
||||
music_of_bollywood
|
||||
ska
|
||||
traditional_music
|
||||
independent_music
|
||||
song
|
||||
background_music
|
||||
theme_music
|
||||
jingle
|
||||
soundtrack_music
|
||||
lullaby
|
||||
video_game_music
|
||||
christmas_music
|
||||
dance_music
|
||||
wedding_music
|
||||
happy_music
|
||||
sad_music
|
||||
tender_music
|
||||
exciting_music
|
||||
angry_music
|
||||
scary_music
|
||||
wind
|
||||
rustling_leaves
|
||||
wind_noise
|
||||
thunderstorm
|
||||
thunder
|
||||
water
|
||||
rain
|
||||
raindrop
|
||||
rain_on_surface
|
||||
stream
|
||||
waterfall
|
||||
ocean
|
||||
waves
|
||||
steam
|
||||
gurgling
|
||||
fire
|
||||
crackle
|
||||
vehicle
|
||||
boat
|
||||
sailboat
|
||||
rowboat
|
||||
motorboat
|
||||
ship
|
||||
motor_vehicle
|
||||
car
|
||||
honk
|
||||
toot
|
||||
car_alarm
|
||||
power_windows
|
||||
skidding
|
||||
tire_squeal
|
||||
car_passing_by
|
||||
race_car
|
||||
truck
|
||||
air_brake
|
||||
air_horn
|
||||
reversing_beeps
|
||||
ice_cream_truck
|
||||
bus
|
||||
emergency_vehicle
|
||||
police_car
|
||||
ambulance
|
||||
fire_engine
|
||||
motorcycle
|
||||
traffic_noise
|
||||
rail_transport
|
||||
train
|
||||
train_whistle
|
||||
train_horn
|
||||
railroad_car
|
||||
train_wheels_squealing
|
||||
subway
|
||||
aircraft
|
||||
aircraft_engine
|
||||
jet_engine
|
||||
propeller
|
||||
helicopter
|
||||
fixed-wing_aircraft
|
||||
bicycle
|
||||
skateboard
|
||||
engine
|
||||
light_engine
|
||||
dental_drill's_drill
|
||||
lawn_mower
|
||||
chainsaw
|
||||
medium_engine
|
||||
heavy_engine
|
||||
engine_knocking
|
||||
engine_starting
|
||||
idling
|
||||
accelerating
|
||||
door
|
||||
doorbell
|
||||
ding-dong
|
||||
sliding_door
|
||||
slam
|
||||
knock
|
||||
tap
|
||||
squeak
|
||||
cupboard_open_or_close
|
||||
drawer_open_or_close
|
||||
dishes
|
||||
cutlery
|
||||
chopping
|
||||
frying
|
||||
microwave_oven
|
||||
blender
|
||||
water_tap
|
||||
sink
|
||||
bathtub
|
||||
hair_dryer
|
||||
toilet_flush
|
||||
toothbrush
|
||||
electric_toothbrush
|
||||
vacuum_cleaner
|
||||
zipper
|
||||
keys_jangling
|
||||
coin
|
||||
scissors
|
||||
electric_shaver
|
||||
shuffling_cards
|
||||
typing
|
||||
typewriter
|
||||
computer_keyboard
|
||||
writing
|
||||
alarm
|
||||
telephone
|
||||
telephone_bell_ringing
|
||||
ringtone
|
||||
telephone_dialing
|
||||
dial_tone
|
||||
busy_signal
|
||||
alarm_clock
|
||||
siren
|
||||
civil_defense_siren
|
||||
buzzer
|
||||
smoke_detector
|
||||
fire_alarm
|
||||
foghorn
|
||||
whistle
|
||||
steam_whistle
|
||||
mechanisms
|
||||
ratchet
|
||||
clock
|
||||
tick
|
||||
tick-tock
|
||||
gears
|
||||
pulleys
|
||||
sewing_machine
|
||||
mechanical_fan
|
||||
air_conditioning
|
||||
cash_register
|
||||
printer
|
||||
camera
|
||||
single-lens_reflex_camera
|
||||
tools
|
||||
hammer
|
||||
jackhammer
|
||||
sawing
|
||||
filing
|
||||
sanding
|
||||
power_tool
|
||||
drill
|
||||
explosion
|
||||
gunshot
|
||||
machine_gun
|
||||
fusillade
|
||||
artillery_fire
|
||||
cap_gun
|
||||
fireworks
|
||||
firecracker
|
||||
burst
|
||||
eruption
|
||||
boom
|
||||
wood
|
||||
chop
|
||||
splinter
|
||||
crack
|
||||
glass
|
||||
chink
|
||||
shatter
|
||||
liquid
|
||||
splash
|
||||
slosh
|
||||
squish
|
||||
drip
|
||||
pour
|
||||
trickle
|
||||
gush
|
||||
fill
|
||||
spray
|
||||
pump
|
||||
stir
|
||||
boiling
|
||||
sonar
|
||||
arrow
|
||||
whoosh
|
||||
thump
|
||||
thunk
|
||||
electronic_tuner
|
||||
effects_unit
|
||||
chorus_effect
|
||||
basketball_bounce
|
||||
bang
|
||||
slap
|
||||
whack
|
||||
smash
|
||||
breaking
|
||||
bouncing
|
||||
whip
|
||||
flap
|
||||
scratch
|
||||
scrape
|
||||
rub
|
||||
roll
|
||||
crushing
|
||||
crumpling
|
||||
tearing
|
||||
beep
|
||||
ping
|
||||
ding
|
||||
clang
|
||||
squeal
|
||||
creak
|
||||
rustle
|
||||
whir
|
||||
clatter
|
||||
sizzle
|
||||
clicking
|
||||
clickety-clack
|
||||
rumble
|
||||
plop
|
||||
jingle
|
||||
hum
|
||||
zing
|
||||
boing
|
||||
crunch
|
||||
silence
|
||||
sine_wave
|
||||
harmonic
|
||||
chirp_tone
|
||||
sound_effect
|
||||
pulse
|
||||
inside
|
||||
inside
|
||||
inside
|
||||
outside
|
||||
outside
|
||||
reverberation
|
||||
echo
|
||||
noise
|
||||
environmental_noise
|
||||
static
|
||||
mains_hum
|
||||
distortion
|
||||
sidetone
|
||||
cacophony
|
||||
white_noise
|
||||
pink_noise
|
||||
throbbing
|
||||
vibration
|
||||
television
|
||||
radio
|
||||
field_recording
|
73
benchmark.py
73
benchmark.py
@@ -1,12 +1,18 @@
|
||||
import os
|
||||
from statistics import mean
|
||||
import multiprocessing as mp
|
||||
import numpy as np
|
||||
import datetime
|
||||
from frigate.edgetpu import LocalObjectDetector, EdgeTPUProcess, RemoteObjectDetector, load_labels
|
||||
import multiprocessing as mp
|
||||
from statistics import mean
|
||||
|
||||
my_frame = np.expand_dims(np.full((300,300,3), 1, np.uint8), axis=0)
|
||||
labels = load_labels('/labelmap.txt')
|
||||
import numpy as np
|
||||
|
||||
from frigate.config import DetectorTypeEnum
|
||||
from frigate.object_detection import (
|
||||
ObjectDetectProcess,
|
||||
RemoteObjectDetector,
|
||||
load_labels,
|
||||
)
|
||||
|
||||
my_frame = np.expand_dims(np.full((300, 300, 3), 1, np.uint8), axis=0)
|
||||
labels = load_labels("/labelmap.txt")
|
||||
|
||||
######
|
||||
# Minimal same process runner
|
||||
@@ -39,20 +45,23 @@ labels = load_labels('/labelmap.txt')
|
||||
|
||||
|
||||
def start(id, num_detections, detection_queue, event):
|
||||
object_detector = RemoteObjectDetector(str(id), '/labelmap.txt', detection_queue, event)
|
||||
start = datetime.datetime.now().timestamp()
|
||||
object_detector = RemoteObjectDetector(
|
||||
str(id), "/labelmap.txt", detection_queue, event
|
||||
)
|
||||
start = datetime.datetime.now().timestamp()
|
||||
|
||||
frame_times = []
|
||||
for x in range(0, num_detections):
|
||||
start_frame = datetime.datetime.now().timestamp()
|
||||
detections = object_detector.detect(my_frame)
|
||||
frame_times.append(datetime.datetime.now().timestamp()-start_frame)
|
||||
frame_times = []
|
||||
for x in range(0, num_detections):
|
||||
start_frame = datetime.datetime.now().timestamp()
|
||||
object_detector.detect(my_frame)
|
||||
frame_times.append(datetime.datetime.now().timestamp() - start_frame)
|
||||
|
||||
duration = datetime.datetime.now().timestamp() - start
|
||||
object_detector.cleanup()
|
||||
print(f"{id} - Processed for {duration:.2f} seconds.")
|
||||
print(f"{id} - FPS: {object_detector.fps.eps():.2f}")
|
||||
print(f"{id} - Average frame processing time: {mean(frame_times)*1000:.2f}ms")
|
||||
|
||||
duration = datetime.datetime.now().timestamp()-start
|
||||
object_detector.cleanup()
|
||||
print(f"{id} - Processed for {duration:.2f} seconds.")
|
||||
print(f"{id} - FPS: {object_detector.fps.eps():.2f}")
|
||||
print(f"{id} - Average frame processing time: {mean(frame_times)*1000:.2f}ms")
|
||||
|
||||
######
|
||||
# Separate process runner
|
||||
@@ -71,23 +80,29 @@ camera_processes = []
|
||||
|
||||
events = {}
|
||||
for x in range(0, 10):
|
||||
events[str(x)] = mp.Event()
|
||||
events[str(x)] = mp.Event()
|
||||
detection_queue = mp.Queue()
|
||||
edgetpu_process_1 = EdgeTPUProcess(detection_queue, events, 'usb:0')
|
||||
edgetpu_process_2 = EdgeTPUProcess(detection_queue, events, 'usb:1')
|
||||
edgetpu_process_1 = ObjectDetectProcess(
|
||||
detection_queue, events, DetectorTypeEnum.edgetpu, "usb:0"
|
||||
)
|
||||
edgetpu_process_2 = ObjectDetectProcess(
|
||||
detection_queue, events, DetectorTypeEnum.edgetpu, "usb:1"
|
||||
)
|
||||
|
||||
for x in range(0, 10):
|
||||
camera_process = mp.Process(target=start, args=(x, 300, detection_queue, events[str(x)]))
|
||||
camera_process.daemon = True
|
||||
camera_processes.append(camera_process)
|
||||
camera_process = mp.Process(
|
||||
target=start, args=(x, 300, detection_queue, events[str(x)])
|
||||
)
|
||||
camera_process.daemon = True
|
||||
camera_processes.append(camera_process)
|
||||
|
||||
start_time = datetime.datetime.now().timestamp()
|
||||
|
||||
for p in camera_processes:
|
||||
p.start()
|
||||
p.start()
|
||||
|
||||
for p in camera_processes:
|
||||
p.join()
|
||||
p.join()
|
||||
|
||||
duration = datetime.datetime.now().timestamp()-start_time
|
||||
print(f"Total - Processed for {duration:.2f} seconds.")
|
||||
duration = datetime.datetime.now().timestamp() - start_time
|
||||
print(f"Total - Processed for {duration:.2f} seconds.")
|
||||
|
118
benchmark_motion.py
Normal file
118
benchmark_motion.py
Normal file
@@ -0,0 +1,118 @@
|
||||
import datetime
|
||||
import multiprocessing as mp
|
||||
import os
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
from frigate.config import MotionConfig
|
||||
from frigate.motion.improved_motion import ImprovedMotionDetector
|
||||
from frigate.util import create_mask
|
||||
|
||||
# get info on the video
|
||||
# cap = cv2.VideoCapture("debug/front_cam_2023_05_23_08_41__2023_05_23_08_43.mp4")
|
||||
# cap = cv2.VideoCapture("debug/motion_test_clips/rain_1.mp4")
|
||||
cap = cv2.VideoCapture("debug/motion_test_clips/lawn_mower_night_1.mp4")
|
||||
# cap = cv2.VideoCapture("airport.mp4")
|
||||
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
||||
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
||||
fps = cap.get(cv2.CAP_PROP_FPS)
|
||||
frame_shape = (height, width, 3)
|
||||
# Nick back:
|
||||
# "1280,0,1280,316,1170,216,1146,126,1016,127,979,82,839,0",
|
||||
# "310,350,300,402,224,405,241,354",
|
||||
# "378,0,375,26,0,23,0,0",
|
||||
# Front door:
|
||||
# "1080,0,1080,339,1010,280,1020,169,777,163,452,170,318,299,191,365,186,417,139,470,108,516,40,530,0,514,0,0",
|
||||
# "336,833,438,1024,346,1093,103,1052,24,814",
|
||||
# Back
|
||||
# "1855,0,1851,100,1289,96,1105,161,1045,119,890,121,890,0",
|
||||
# "505,95,506,138,388,153,384,114",
|
||||
# "689,72,689,122,549,134,547,89",
|
||||
# "261,134,264,176,169,195,167,158",
|
||||
# "145,159,146,202,70,220,65,183",
|
||||
|
||||
mask = create_mask(
|
||||
(height, width),
|
||||
[
|
||||
"1080,0,1080,339,1010,280,1020,169,777,163,452,170,318,299,191,365,186,417,139,470,108,516,40,530,0,514,0,0",
|
||||
"336,833,438,1024,346,1093,103,1052,24,814",
|
||||
],
|
||||
)
|
||||
|
||||
# create the motion config
|
||||
motion_config_1 = MotionConfig()
|
||||
motion_config_1.mask = np.zeros((height, width), np.uint8)
|
||||
motion_config_1.mask[:] = mask
|
||||
# motion_config_1.improve_contrast = 1
|
||||
motion_config_1.frame_height = 150
|
||||
# motion_config_1.frame_alpha = 0.02
|
||||
# motion_config_1.threshold = 30
|
||||
# motion_config_1.contour_area = 10
|
||||
|
||||
motion_config_2 = MotionConfig()
|
||||
motion_config_2.mask = np.zeros((height, width), np.uint8)
|
||||
motion_config_2.mask[:] = mask
|
||||
# motion_config_2.improve_contrast = 1
|
||||
motion_config_2.frame_height = 150
|
||||
# motion_config_2.frame_alpha = 0.01
|
||||
motion_config_2.threshold = 20
|
||||
# motion_config.contour_area = 10
|
||||
|
||||
save_images = True
|
||||
|
||||
improved_motion_detector_1 = ImprovedMotionDetector(
|
||||
frame_shape=frame_shape,
|
||||
config=motion_config_1,
|
||||
fps=fps,
|
||||
improve_contrast=mp.Value("i", motion_config_1.improve_contrast),
|
||||
threshold=mp.Value("i", motion_config_1.threshold),
|
||||
contour_area=mp.Value("i", motion_config_1.contour_area),
|
||||
name="default",
|
||||
)
|
||||
improved_motion_detector_1.save_images = save_images
|
||||
|
||||
improved_motion_detector_2 = ImprovedMotionDetector(
|
||||
frame_shape=frame_shape,
|
||||
config=motion_config_2,
|
||||
fps=fps,
|
||||
improve_contrast=mp.Value("i", motion_config_2.improve_contrast),
|
||||
threshold=mp.Value("i", motion_config_2.threshold),
|
||||
contour_area=mp.Value("i", motion_config_2.contour_area),
|
||||
name="compare",
|
||||
)
|
||||
improved_motion_detector_2.save_images = save_images
|
||||
|
||||
# read and process frames
|
||||
ret, frame = cap.read()
|
||||
frame_counter = 1
|
||||
while ret:
|
||||
yuv_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV_I420)
|
||||
|
||||
start_frame = datetime.datetime.now().timestamp()
|
||||
improved_motion_detector_1.detect(yuv_frame)
|
||||
|
||||
start_frame = datetime.datetime.now().timestamp()
|
||||
improved_motion_detector_2.detect(yuv_frame)
|
||||
|
||||
default_frame = f"debug/frames/default-{frame_counter}.jpg"
|
||||
compare_frame = f"debug/frames/compare-{frame_counter}.jpg"
|
||||
if os.path.exists(default_frame) and os.path.exists(compare_frame):
|
||||
images = [
|
||||
cv2.imread(default_frame),
|
||||
cv2.imread(compare_frame),
|
||||
]
|
||||
|
||||
cv2.imwrite(
|
||||
f"debug/frames/all-{frame_counter}.jpg",
|
||||
cv2.vconcat(images)
|
||||
if frame_shape[0] > frame_shape[1]
|
||||
else cv2.hconcat(images),
|
||||
)
|
||||
os.unlink(default_frame)
|
||||
os.unlink(compare_frame)
|
||||
frame_counter += 1
|
||||
|
||||
ret, frame = cap.read()
|
||||
|
||||
cap.release()
|
16
config/config.yml.example
Normal file
16
config/config.yml.example
Normal file
@@ -0,0 +1,16 @@
|
||||
mqtt:
|
||||
host: mqtt
|
||||
|
||||
cameras:
|
||||
test:
|
||||
ffmpeg:
|
||||
inputs:
|
||||
- path: /media/frigate/car-stopping.mp4
|
||||
input_args: -re -stream_loop -1 -fflags +genpts
|
||||
roles:
|
||||
- detect
|
||||
- rtmp
|
||||
detect:
|
||||
height: 1080
|
||||
width: 1920
|
||||
fps: 5
|
@@ -1,441 +0,0 @@
|
||||
import faulthandler; faulthandler.enable()
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
import traceback
|
||||
import signal
|
||||
import cv2
|
||||
import time
|
||||
import datetime
|
||||
import queue
|
||||
import yaml
|
||||
import json
|
||||
import threading
|
||||
import multiprocessing as mp
|
||||
import subprocess as sp
|
||||
import numpy as np
|
||||
import logging
|
||||
from flask import Flask, Response, make_response, jsonify, request
|
||||
import paho.mqtt.client as mqtt
|
||||
|
||||
from frigate.video import capture_camera, track_camera, get_ffmpeg_input, get_frame_shape, CameraCapture, start_or_restart_ffmpeg
|
||||
from frigate.object_processing import TrackedObjectProcessor
|
||||
from frigate.events import EventProcessor
|
||||
from frigate.util import EventsPerSecond
|
||||
from frigate.edgetpu import EdgeTPUProcess
|
||||
|
||||
FRIGATE_VARS = {k: v for k, v in os.environ.items() if k.startswith('FRIGATE_')}
|
||||
|
||||
CONFIG_FILE = os.environ.get('CONFIG_FILE', '/config/config.yml')
|
||||
|
||||
if CONFIG_FILE.endswith(".yml"):
|
||||
with open(CONFIG_FILE) as f:
|
||||
CONFIG = yaml.safe_load(f)
|
||||
elif CONFIG_FILE.endswith(".json"):
|
||||
with open(CONFIG_FILE) as f:
|
||||
CONFIG = json.load(f)
|
||||
|
||||
CACHE_DIR = CONFIG.get('save_clips', {}).get('cache_dir', '/cache')
|
||||
CLIPS_DIR = CONFIG.get('save_clips', {}).get('clips_dir', '/clips')
|
||||
|
||||
if not os.path.exists(CACHE_DIR) and not os.path.islink(CACHE_DIR):
|
||||
os.makedirs(CACHE_DIR)
|
||||
if not os.path.exists(CLIPS_DIR) and not os.path.islink(CLIPS_DIR):
|
||||
os.makedirs(CLIPS_DIR)
|
||||
|
||||
MQTT_HOST = CONFIG['mqtt']['host']
|
||||
MQTT_PORT = CONFIG.get('mqtt', {}).get('port', 1883)
|
||||
MQTT_TOPIC_PREFIX = CONFIG.get('mqtt', {}).get('topic_prefix', 'frigate')
|
||||
MQTT_USER = CONFIG.get('mqtt', {}).get('user')
|
||||
MQTT_PASS = CONFIG.get('mqtt', {}).get('password')
|
||||
if not MQTT_PASS is None:
|
||||
MQTT_PASS = MQTT_PASS.format(**FRIGATE_VARS)
|
||||
MQTT_CLIENT_ID = CONFIG.get('mqtt', {}).get('client_id', 'frigate')
|
||||
|
||||
# Set the default FFmpeg config
|
||||
FFMPEG_CONFIG = CONFIG.get('ffmpeg', {})
|
||||
FFMPEG_DEFAULT_CONFIG = {
|
||||
'global_args': FFMPEG_CONFIG.get('global_args',
|
||||
['-hide_banner','-loglevel','panic']),
|
||||
'hwaccel_args': FFMPEG_CONFIG.get('hwaccel_args',
|
||||
[]),
|
||||
'input_args': FFMPEG_CONFIG.get('input_args',
|
||||
['-avoid_negative_ts', 'make_zero',
|
||||
'-fflags', 'nobuffer',
|
||||
'-flags', 'low_delay',
|
||||
'-strict', 'experimental',
|
||||
'-fflags', '+genpts+discardcorrupt',
|
||||
'-rtsp_transport', 'tcp',
|
||||
'-stimeout', '5000000',
|
||||
'-use_wallclock_as_timestamps', '1']),
|
||||
'output_args': FFMPEG_CONFIG.get('output_args',
|
||||
['-f', 'rawvideo',
|
||||
'-pix_fmt', 'yuv420p'])
|
||||
}
|
||||
|
||||
GLOBAL_OBJECT_CONFIG = CONFIG.get('objects', {})
|
||||
|
||||
WEB_PORT = CONFIG.get('web_port', 5000)
|
||||
DETECTORS = CONFIG.get('detectors', {'coral': {'type': 'edgetpu', 'device': 'usb'}})
|
||||
|
||||
class FrigateWatchdog(threading.Thread):
|
||||
def __init__(self, camera_processes, config, detectors, detection_queue, out_events, tracked_objects_queue, stop_event):
|
||||
threading.Thread.__init__(self)
|
||||
self.camera_processes = camera_processes
|
||||
self.config = config
|
||||
self.detectors = detectors
|
||||
self.detection_queue = detection_queue
|
||||
self.out_events = out_events
|
||||
self.tracked_objects_queue = tracked_objects_queue
|
||||
self.stop_event = stop_event
|
||||
|
||||
def run(self):
|
||||
time.sleep(10)
|
||||
while True:
|
||||
# wait a bit before checking
|
||||
time.sleep(10)
|
||||
|
||||
if self.stop_event.is_set():
|
||||
print(f"Exiting watchdog...")
|
||||
break
|
||||
|
||||
now = datetime.datetime.now().timestamp()
|
||||
|
||||
# check the detection processes
|
||||
for detector in self.detectors.values():
|
||||
detection_start = detector.detection_start.value
|
||||
if (detection_start > 0.0 and
|
||||
now - detection_start > 10):
|
||||
print("Detection appears to be stuck. Restarting detection process")
|
||||
detector.start_or_restart()
|
||||
elif not detector.detect_process.is_alive():
|
||||
print("Detection appears to have stopped. Restarting detection process")
|
||||
detector.start_or_restart()
|
||||
|
||||
# check the camera processes
|
||||
for name, camera_process in self.camera_processes.items():
|
||||
process = camera_process['process']
|
||||
if not process.is_alive():
|
||||
print(f"Track process for {name} is not alive. Starting again...")
|
||||
camera_process['camera_fps'].value = 0.0
|
||||
camera_process['process_fps'].value = 0.0
|
||||
camera_process['detection_fps'].value = 0.0
|
||||
camera_process['read_start'].value = 0.0
|
||||
process = mp.Process(target=track_camera, args=(name, self.config,
|
||||
self.detection_queue, self.out_events[name], self.tracked_objects_queue, camera_process, self.stop_event))
|
||||
process.daemon = True
|
||||
camera_process['process'] = process
|
||||
process.start()
|
||||
print(f"Track process started for {name}: {process.pid}")
|
||||
|
||||
def main():
|
||||
stop_event = threading.Event()
|
||||
# connect to mqtt and setup last will
|
||||
def on_connect(client, userdata, flags, rc):
|
||||
print("On connect called")
|
||||
if rc != 0:
|
||||
if rc == 3:
|
||||
print ("MQTT Server unavailable")
|
||||
elif rc == 4:
|
||||
print ("MQTT Bad username or password")
|
||||
elif rc == 5:
|
||||
print ("MQTT Not authorized")
|
||||
else:
|
||||
print ("Unable to connect to MQTT: Connection refused. Error code: " + str(rc))
|
||||
# publish a message to signal that the service is running
|
||||
client.publish(MQTT_TOPIC_PREFIX+'/available', 'online', retain=True)
|
||||
client = mqtt.Client(client_id=MQTT_CLIENT_ID)
|
||||
client.on_connect = on_connect
|
||||
client.will_set(MQTT_TOPIC_PREFIX+'/available', payload='offline', qos=1, retain=True)
|
||||
if not MQTT_USER is None:
|
||||
client.username_pw_set(MQTT_USER, password=MQTT_PASS)
|
||||
client.connect(MQTT_HOST, MQTT_PORT, 60)
|
||||
client.loop_start()
|
||||
|
||||
##
|
||||
# Setup config defaults for cameras
|
||||
##
|
||||
for name, config in CONFIG['cameras'].items():
|
||||
config['snapshots'] = {
|
||||
'show_timestamp': config.get('snapshots', {}).get('show_timestamp', True),
|
||||
'draw_zones': config.get('snapshots', {}).get('draw_zones', False),
|
||||
'draw_bounding_boxes': config.get('snapshots', {}).get('draw_bounding_boxes', True)
|
||||
}
|
||||
config['zones'] = config.get('zones', {})
|
||||
|
||||
# Queue for cameras to push tracked objects to
|
||||
tracked_objects_queue = mp.Queue(maxsize=len(CONFIG['cameras'].keys())*2)
|
||||
|
||||
# Queue for clip processing
|
||||
event_queue = mp.Queue()
|
||||
|
||||
# create the detection pipes and shms
|
||||
out_events = {}
|
||||
camera_shms = []
|
||||
for name in CONFIG['cameras'].keys():
|
||||
out_events[name] = mp.Event()
|
||||
shm_in = mp.shared_memory.SharedMemory(name=name, create=True, size=300*300*3)
|
||||
shm_out = mp.shared_memory.SharedMemory(name=f"out-{name}", create=True, size=20*6*4)
|
||||
camera_shms.append(shm_in)
|
||||
camera_shms.append(shm_out)
|
||||
|
||||
detection_queue = mp.Queue()
|
||||
|
||||
detectors = {}
|
||||
for name, detector in DETECTORS.items():
|
||||
if detector['type'] == 'cpu':
|
||||
detectors[name] = EdgeTPUProcess(detection_queue, out_events=out_events, tf_device='cpu')
|
||||
if detector['type'] == 'edgetpu':
|
||||
detectors[name] = EdgeTPUProcess(detection_queue, out_events=out_events, tf_device=detector['device'])
|
||||
|
||||
# create the camera processes
|
||||
camera_process_info = {}
|
||||
for name, config in CONFIG['cameras'].items():
|
||||
# Merge the ffmpeg config with the global config
|
||||
ffmpeg = config.get('ffmpeg', {})
|
||||
ffmpeg_input = get_ffmpeg_input(ffmpeg['input'])
|
||||
ffmpeg_global_args = ffmpeg.get('global_args', FFMPEG_DEFAULT_CONFIG['global_args'])
|
||||
ffmpeg_hwaccel_args = ffmpeg.get('hwaccel_args', FFMPEG_DEFAULT_CONFIG['hwaccel_args'])
|
||||
ffmpeg_input_args = ffmpeg.get('input_args', FFMPEG_DEFAULT_CONFIG['input_args'])
|
||||
ffmpeg_output_args = ffmpeg.get('output_args', FFMPEG_DEFAULT_CONFIG['output_args'])
|
||||
if not config.get('fps') is None:
|
||||
ffmpeg_output_args = ["-r", str(config.get('fps'))] + ffmpeg_output_args
|
||||
if config.get('save_clips', {}).get('enabled', False):
|
||||
ffmpeg_output_args = [
|
||||
"-f",
|
||||
"segment",
|
||||
"-segment_time",
|
||||
"10",
|
||||
"-segment_format",
|
||||
"mp4",
|
||||
"-reset_timestamps",
|
||||
"1",
|
||||
"-strftime",
|
||||
"1",
|
||||
"-c",
|
||||
"copy",
|
||||
"-an",
|
||||
"-map",
|
||||
"0",
|
||||
f"{os.path.join(CACHE_DIR, name)}-%Y%m%d%H%M%S.mp4"
|
||||
] + ffmpeg_output_args
|
||||
ffmpeg_cmd = (['ffmpeg'] +
|
||||
ffmpeg_global_args +
|
||||
ffmpeg_hwaccel_args +
|
||||
ffmpeg_input_args +
|
||||
['-i', ffmpeg_input] +
|
||||
ffmpeg_output_args +
|
||||
['pipe:'])
|
||||
|
||||
config['ffmpeg_cmd'] = ffmpeg_cmd
|
||||
|
||||
if 'width' in config and 'height' in config:
|
||||
frame_shape = (config['height'], config['width'], 3)
|
||||
else:
|
||||
frame_shape = get_frame_shape(ffmpeg_input)
|
||||
|
||||
config['frame_shape'] = frame_shape
|
||||
config['take_frame'] = config.get('take_frame', 1)
|
||||
|
||||
camera_process_info[name] = {
|
||||
'camera_fps': mp.Value('d', 0.0),
|
||||
'skipped_fps': mp.Value('d', 0.0),
|
||||
'process_fps': mp.Value('d', 0.0),
|
||||
'detection_fps': mp.Value('d', 0.0),
|
||||
'detection_frame': mp.Value('d', 0.0),
|
||||
'read_start': mp.Value('d', 0.0),
|
||||
'ffmpeg_pid': mp.Value('i', 0),
|
||||
'frame_queue': mp.Queue(maxsize=2)
|
||||
}
|
||||
|
||||
# merge global object config into camera object config
|
||||
camera_objects_config = config.get('objects', {})
|
||||
# get objects to track for camera
|
||||
objects_to_track = camera_objects_config.get('track', GLOBAL_OBJECT_CONFIG.get('track', ['person']))
|
||||
# get object filters
|
||||
object_filters = camera_objects_config.get('filters', GLOBAL_OBJECT_CONFIG.get('filters', {}))
|
||||
config['objects'] = {
|
||||
'track': objects_to_track,
|
||||
'filters': object_filters
|
||||
}
|
||||
|
||||
capture_process = mp.Process(target=capture_camera, args=(name, config,
|
||||
camera_process_info[name], stop_event))
|
||||
capture_process.daemon = True
|
||||
camera_process_info[name]['capture_process'] = capture_process
|
||||
|
||||
camera_process = mp.Process(target=track_camera, args=(name, config,
|
||||
detection_queue, out_events[name], tracked_objects_queue, camera_process_info[name], stop_event))
|
||||
camera_process.daemon = True
|
||||
camera_process_info[name]['process'] = camera_process
|
||||
|
||||
# start the camera_processes
|
||||
for name, camera_process in camera_process_info.items():
|
||||
camera_process['capture_process'].start()
|
||||
print(f"Camera capture process started for {name}: {camera_process['capture_process'].pid}")
|
||||
camera_process['process'].start()
|
||||
print(f"Camera process started for {name}: {camera_process['process'].pid}")
|
||||
|
||||
event_processor = EventProcessor(CONFIG, camera_process_info, CACHE_DIR, CLIPS_DIR, event_queue, stop_event)
|
||||
event_processor.start()
|
||||
|
||||
object_processor = TrackedObjectProcessor(CONFIG['cameras'], client, MQTT_TOPIC_PREFIX, tracked_objects_queue, event_queue, stop_event)
|
||||
object_processor.start()
|
||||
|
||||
frigate_watchdog = FrigateWatchdog(camera_process_info, CONFIG['cameras'], detectors, detection_queue, out_events, tracked_objects_queue, stop_event)
|
||||
frigate_watchdog.start()
|
||||
|
||||
def receiveSignal(signalNumber, frame):
|
||||
print('Received:', signalNumber)
|
||||
stop_event.set()
|
||||
event_processor.join()
|
||||
object_processor.join()
|
||||
frigate_watchdog.join()
|
||||
|
||||
for detector in detectors.values():
|
||||
detector.stop()
|
||||
for shm in camera_shms:
|
||||
shm.close()
|
||||
shm.unlink()
|
||||
sys.exit()
|
||||
|
||||
signal.signal(signal.SIGTERM, receiveSignal)
|
||||
signal.signal(signal.SIGINT, receiveSignal)
|
||||
|
||||
# create a flask app that encodes frames a mjpeg on demand
|
||||
app = Flask(__name__)
|
||||
log = logging.getLogger('werkzeug')
|
||||
log.setLevel(logging.ERROR)
|
||||
|
||||
@app.route('/')
|
||||
def ishealthy():
|
||||
# return a healh
|
||||
return "Frigate is running. Alive and healthy!"
|
||||
|
||||
@app.route('/debug/stack')
|
||||
def processor_stack():
|
||||
frame = sys._current_frames().get(object_processor.ident, None)
|
||||
if frame:
|
||||
return "<br>".join(traceback.format_stack(frame)), 200
|
||||
else:
|
||||
return "no frame found", 200
|
||||
|
||||
@app.route('/debug/print_stack')
|
||||
def print_stack():
|
||||
pid = int(request.args.get('pid', 0))
|
||||
if pid == 0:
|
||||
return "missing pid", 200
|
||||
else:
|
||||
os.kill(pid, signal.SIGUSR1)
|
||||
return "check logs", 200
|
||||
|
||||
@app.route('/debug/stats')
|
||||
def stats():
|
||||
stats = {}
|
||||
|
||||
total_detection_fps = 0
|
||||
|
||||
for name, camera_stats in camera_process_info.items():
|
||||
total_detection_fps += camera_stats['detection_fps'].value
|
||||
stats[name] = {
|
||||
'camera_fps': round(camera_stats['camera_fps'].value, 2),
|
||||
'process_fps': round(camera_stats['process_fps'].value, 2),
|
||||
'skipped_fps': round(camera_stats['skipped_fps'].value, 2),
|
||||
'detection_fps': round(camera_stats['detection_fps'].value, 2),
|
||||
'pid': camera_stats['process'].pid,
|
||||
'capture_pid': camera_stats['capture_process'].pid,
|
||||
'frame_info': {
|
||||
'detect': camera_stats['detection_frame'].value,
|
||||
'process': object_processor.camera_data[name]['current_frame_time']
|
||||
}
|
||||
}
|
||||
|
||||
stats['detectors'] = {}
|
||||
for name, detector in detectors.items():
|
||||
stats['detectors'][name] = {
|
||||
'inference_speed': round(detector.avg_inference_speed.value*1000, 2),
|
||||
'detection_start': detector.detection_start.value,
|
||||
'pid': detector.detect_process.pid
|
||||
}
|
||||
stats['detection_fps'] = round(total_detection_fps, 2)
|
||||
|
||||
return jsonify(stats)
|
||||
|
||||
@app.route('/<camera_name>/<label>/best.jpg')
|
||||
def best(camera_name, label):
|
||||
if camera_name in CONFIG['cameras']:
|
||||
best_object = object_processor.get_best(camera_name, label)
|
||||
best_frame = best_object.get('frame')
|
||||
if best_frame is None:
|
||||
best_frame = np.zeros((720,1280,3), np.uint8)
|
||||
else:
|
||||
best_frame = cv2.cvtColor(best_frame, cv2.COLOR_YUV2BGR_I420)
|
||||
|
||||
crop = bool(request.args.get('crop', 0, type=int))
|
||||
if crop:
|
||||
region = best_object.get('region', [0,0,300,300])
|
||||
best_frame = best_frame[region[1]:region[3], region[0]:region[2]]
|
||||
|
||||
height = int(request.args.get('h', str(best_frame.shape[0])))
|
||||
width = int(height*best_frame.shape[1]/best_frame.shape[0])
|
||||
|
||||
best_frame = cv2.resize(best_frame, dsize=(width, height), interpolation=cv2.INTER_AREA)
|
||||
ret, jpg = cv2.imencode('.jpg', best_frame)
|
||||
response = make_response(jpg.tobytes())
|
||||
response.headers['Content-Type'] = 'image/jpg'
|
||||
return response
|
||||
else:
|
||||
return "Camera named {} not found".format(camera_name), 404
|
||||
|
||||
@app.route('/<camera_name>')
|
||||
def mjpeg_feed(camera_name):
|
||||
fps = int(request.args.get('fps', '3'))
|
||||
height = int(request.args.get('h', '360'))
|
||||
if camera_name in CONFIG['cameras']:
|
||||
# return a multipart response
|
||||
return Response(imagestream(camera_name, fps, height),
|
||||
mimetype='multipart/x-mixed-replace; boundary=frame')
|
||||
else:
|
||||
return "Camera named {} not found".format(camera_name), 404
|
||||
|
||||
@app.route('/<camera_name>/latest.jpg')
|
||||
def latest_frame(camera_name):
|
||||
if camera_name in CONFIG['cameras']:
|
||||
# max out at specified FPS
|
||||
frame = object_processor.get_current_frame(camera_name)
|
||||
if frame is None:
|
||||
frame = np.zeros((720,1280,3), np.uint8)
|
||||
|
||||
height = int(request.args.get('h', str(frame.shape[0])))
|
||||
width = int(height*frame.shape[1]/frame.shape[0])
|
||||
|
||||
frame = cv2.resize(frame, dsize=(width, height), interpolation=cv2.INTER_AREA)
|
||||
|
||||
ret, jpg = cv2.imencode('.jpg', frame)
|
||||
response = make_response(jpg.tobytes())
|
||||
response.headers['Content-Type'] = 'image/jpg'
|
||||
return response
|
||||
else:
|
||||
return "Camera named {} not found".format(camera_name), 404
|
||||
|
||||
def imagestream(camera_name, fps, height):
|
||||
while True:
|
||||
# max out at specified FPS
|
||||
time.sleep(1/fps)
|
||||
frame = object_processor.get_current_frame(camera_name, draw=True)
|
||||
if frame is None:
|
||||
frame = np.zeros((height,int(height*16/9),3), np.uint8)
|
||||
|
||||
width = int(height*frame.shape[1]/frame.shape[0])
|
||||
frame = cv2.resize(frame, dsize=(width, height), interpolation=cv2.INTER_LINEAR)
|
||||
|
||||
ret, jpg = cv2.imencode('.jpg', frame)
|
||||
yield (b'--frame\r\n'
|
||||
b'Content-Type: image/jpeg\r\n\r\n' + jpg.tobytes() + b'\r\n\r\n')
|
||||
|
||||
app.run(host='0.0.0.0', port=WEB_PORT, debug=False)
|
||||
|
||||
object_processor.join()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
40
docker-compose.yml
Normal file
40
docker-compose.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
version: "3"
|
||||
services:
|
||||
devcontainer:
|
||||
container_name: frigate-devcontainer
|
||||
# add groups from host for render, plugdev, video
|
||||
group_add:
|
||||
- "109" # render
|
||||
- "110" # render
|
||||
- "44" # video
|
||||
- "46" # plugdev
|
||||
shm_size: "256mb"
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/main/Dockerfile
|
||||
# Use target devcontainer-trt for TensorRT dev
|
||||
target: devcontainer
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
count: 1
|
||||
capabilities: [gpu]
|
||||
environment:
|
||||
YOLO_MODELS: yolov7-320
|
||||
devices:
|
||||
- /dev/bus/usb:/dev/bus/usb
|
||||
# - /dev/dri:/dev/dri # for intel hwaccel, needs to be updated for your hardware
|
||||
volumes:
|
||||
- .:/workspace/frigate:cached
|
||||
- ./web/dist:/opt/frigate/web:cached
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- ./config:/config
|
||||
- ./debug:/media/frigate
|
||||
- /dev/bus/usb:/dev/bus/usb
|
||||
mqtt:
|
||||
container_name: mqtt
|
||||
image: eclipse-mosquitto:1.6
|
||||
ports:
|
||||
- "1883:1883"
|
@@ -1,22 +0,0 @@
|
||||
FROM frigate-base
|
||||
LABEL maintainer "blakeb@blakeshome.com"
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
# Install packages for apt repo
|
||||
RUN apt-get -qq update \
|
||||
&& apt-get -qq install --no-install-recommends -y \
|
||||
# ffmpeg runtime dependencies
|
||||
libgomp1 \
|
||||
# runtime dependencies
|
||||
libopenexr24 \
|
||||
libgstreamer1.0-0 \
|
||||
libgstreamer-plugins-base1.0-0 \
|
||||
libopenblas-base \
|
||||
libjpeg-turbo8 \
|
||||
libpng16-16 \
|
||||
libtiff5 \
|
||||
libdc1394-22 \
|
||||
## Tensorflow lite
|
||||
&& pip3 install https://github.com/google-coral/pycoral/releases/download/release-frogfish/tflite_runtime-2.5.0-cp38-cp38-linux_aarch64.whl \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& (apt-get autoremove -y; apt-get autoclean -y)
|
@@ -1,18 +0,0 @@
|
||||
FROM frigate-base
|
||||
LABEL maintainer "blakeb@blakeshome.com"
|
||||
|
||||
# By default, use the i965 driver
|
||||
ENV LIBVA_DRIVER_NAME=i965
|
||||
# Install packages for apt repo
|
||||
RUN apt-get -qq update \
|
||||
&& apt-get -qq install --no-install-recommends -y \
|
||||
# ffmpeg dependencies
|
||||
libgomp1 \
|
||||
# VAAPI drivers for Intel hardware accel
|
||||
libva-drm2 libva2 i965-va-driver vainfo intel-media-va-driver \
|
||||
## Tensorflow lite
|
||||
&& wget -q https://github.com/google-coral/pycoral/releases/download/release-frogfish/tflite_runtime-2.5.0-cp38-cp38-linux_x86_64.whl \
|
||||
&& python3.8 -m pip install tflite_runtime-2.5.0-cp38-cp38-linux_x86_64.whl \
|
||||
&& rm tflite_runtime-2.5.0-cp38-cp38-linux_x86_64.whl \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& (apt-get autoremove -y; apt-get autoclean -y)
|
@@ -1,47 +0,0 @@
|
||||
FROM frigate-base
|
||||
LABEL maintainer "blakeb@blakeshome.com"
|
||||
|
||||
# Install packages for apt repo
|
||||
RUN apt-get -qq update \
|
||||
&& apt-get -qq install --no-install-recommends -y \
|
||||
# ffmpeg dependencies
|
||||
libgomp1 \
|
||||
## Tensorflow lite
|
||||
&& wget -q https://github.com/google-coral/pycoral/releases/download/release-frogfish/tflite_runtime-2.5.0-cp38-cp38-linux_x86_64.whl \
|
||||
&& python3.8 -m pip install tflite_runtime-2.5.0-cp38-cp38-linux_x86_64.whl \
|
||||
&& rm tflite_runtime-2.5.0-cp38-cp38-linux_x86_64.whl \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& (apt-get autoremove -y; apt-get autoclean -y)
|
||||
|
||||
|
||||
# nvidia layer (see https://gitlab.com/nvidia/container-images/cuda/blob/master/dist/11.1/ubuntu20.04-x86_64/base/Dockerfile)
|
||||
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility,video
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gnupg2 curl ca-certificates && \
|
||||
curl -fsSL https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/7fa2af80.pub | apt-key add - && \
|
||||
echo "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64 /" > /etc/apt/sources.list.d/cuda.list && \
|
||||
echo "deb https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu2004/x86_64 /" > /etc/apt/sources.list.d/nvidia-ml.list && \
|
||||
apt-get purge --autoremove -y curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV CUDA_VERSION 11.1.1
|
||||
|
||||
# For libraries in the cuda-compat-* package: https://docs.nvidia.com/cuda/eula/index.html#attachment-a
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
cuda-cudart-11-1=11.1.74-1 \
|
||||
cuda-compat-11-1 \
|
||||
&& ln -s cuda-11.1 /usr/local/cuda && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Required for nvidia-docker v1
|
||||
RUN echo "/usr/local/nvidia/lib" >> /etc/ld.so.conf.d/nvidia.conf && \
|
||||
echo "/usr/local/nvidia/lib64" >> /etc/ld.so.conf.d/nvidia.conf
|
||||
|
||||
ENV PATH /usr/local/nvidia/bin:/usr/local/cuda/bin:${PATH}
|
||||
ENV LD_LIBRARY_PATH /usr/local/nvidia/lib:/usr/local/nvidia/lib64
|
||||
|
||||
# nvidia-container-runtime
|
||||
ENV NVIDIA_VISIBLE_DEVICES all
|
||||
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility,video
|
||||
ENV NVIDIA_REQUIRE_CUDA "cuda>=11.1 brand=tesla,driver>=418,driver<419 brand=tesla,driver>=440,driver<441 brand=tesla,driver>=450,driver<451"
|
@@ -1,24 +0,0 @@
|
||||
FROM frigate-base
|
||||
LABEL maintainer "blakeb@blakeshome.com"
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
# Install packages for apt repo
|
||||
RUN apt-get -qq update \
|
||||
&& apt-get -qq install --no-install-recommends -y \
|
||||
# ffmpeg runtime dependencies
|
||||
libgomp1 \
|
||||
# runtime dependencies
|
||||
libopenexr24 \
|
||||
libgstreamer1.0-0 \
|
||||
libgstreamer-plugins-base1.0-0 \
|
||||
libopenblas-base \
|
||||
libjpeg-turbo8 \
|
||||
libpng16-16 \
|
||||
libtiff5 \
|
||||
libdc1394-22 \
|
||||
libaom0 \
|
||||
libx265-179 \
|
||||
## Tensorflow lite
|
||||
&& pip3 install https://github.com/google-coral/pycoral/releases/download/release-frogfish/tflite_runtime-2.5.0-cp38-cp38-linux_armv7l.whl \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& (apt-get autoremove -y; apt-get autoclean -y)
|
@@ -1,44 +0,0 @@
|
||||
ARG ARCH=amd64
|
||||
FROM blakeblackshear/frigate-wheels:${ARCH} as wheels
|
||||
FROM blakeblackshear/frigate-ffmpeg:${ARCH} as ffmpeg
|
||||
|
||||
FROM ubuntu:20.04
|
||||
LABEL maintainer "blakeb@blakeshome.com"
|
||||
|
||||
COPY --from=ffmpeg /usr/local /usr/local/
|
||||
|
||||
COPY --from=wheels /wheels/. /wheels/
|
||||
|
||||
ENV FLASK_ENV=development
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
# Install packages for apt repo
|
||||
RUN apt-get -qq update \
|
||||
&& apt-get upgrade -y \
|
||||
&& apt-get -qq install --no-install-recommends -y \
|
||||
gnupg wget unzip tzdata \
|
||||
&& apt-get -qq install --no-install-recommends -y \
|
||||
python3-pip \
|
||||
&& pip3 install -U /wheels/*.whl \
|
||||
&& APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn apt-key adv --fetch-keys https://packages.cloud.google.com/apt/doc/apt-key.gpg \
|
||||
&& echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" > /etc/apt/sources.list.d/coral-edgetpu.list \
|
||||
&& echo "libedgetpu1-max libedgetpu/accepted-eula select true" | debconf-set-selections \
|
||||
&& apt-get -qq update && apt-get -qq install --no-install-recommends -y \
|
||||
libedgetpu1-max=15.0 \
|
||||
&& rm -rf /var/lib/apt/lists/* /wheels \
|
||||
&& (apt-get autoremove -y; apt-get autoclean -y)
|
||||
|
||||
# get model and labels
|
||||
ARG MODEL_REFS=7064b94dd5b996189242320359dbab8b52c94a84
|
||||
COPY labelmap.txt /labelmap.txt
|
||||
RUN wget -q https://github.com/google-coral/edgetpu/raw/$MODEL_REFS/test_data/ssd_mobilenet_v2_coco_quant_postprocess_edgetpu.tflite -O /edgetpu_model.tflite
|
||||
RUN wget -q https://github.com/google-coral/edgetpu/raw/$MODEL_REFS/test_data/ssd_mobilenet_v2_coco_quant_postprocess.tflite -O /cpu_model.tflite
|
||||
|
||||
RUN mkdir /cache /clips
|
||||
|
||||
WORKDIR /opt/frigate/
|
||||
ADD frigate frigate/
|
||||
COPY detect_objects.py .
|
||||
COPY benchmark.py .
|
||||
COPY process_clip.py .
|
||||
|
||||
CMD ["python3", "-u", "detect_objects.py"]
|
@@ -1,533 +0,0 @@
|
||||
# inspired by:
|
||||
# https://github.com/collelog/ffmpeg/blob/master/4.3.1-alpine-rpi4-arm64v8.Dockerfile
|
||||
# https://github.com/mmastrac/ffmpeg-omx-rpi-docker/blob/master/Dockerfile
|
||||
# https://github.com/jrottenberg/ffmpeg/pull/158/files
|
||||
# https://github.com/jrottenberg/ffmpeg/pull/239
|
||||
FROM ubuntu:20.04 AS base
|
||||
|
||||
WORKDIR /tmp/workdir
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get -yqq update && \
|
||||
apt-get install -yq --no-install-recommends ca-certificates expat libgomp1 && \
|
||||
apt-get autoremove -y && \
|
||||
apt-get clean -y
|
||||
|
||||
FROM base as build
|
||||
|
||||
ENV FFMPEG_VERSION=4.3.1 \
|
||||
AOM_VERSION=v1.0.0 \
|
||||
FDKAAC_VERSION=0.1.5 \
|
||||
FONTCONFIG_VERSION=2.12.4 \
|
||||
FREETYPE_VERSION=2.5.5 \
|
||||
FRIBIDI_VERSION=0.19.7 \
|
||||
KVAZAAR_VERSION=1.2.0 \
|
||||
LAME_VERSION=3.100 \
|
||||
LIBASS_VERSION=0.13.7 \
|
||||
LIBPTHREAD_STUBS_VERSION=0.4 \
|
||||
LIBVIDSTAB_VERSION=1.1.0 \
|
||||
LIBXCB_VERSION=1.13.1 \
|
||||
XCBPROTO_VERSION=1.13 \
|
||||
OGG_VERSION=1.3.2 \
|
||||
OPENCOREAMR_VERSION=0.1.5 \
|
||||
OPUS_VERSION=1.2 \
|
||||
OPENJPEG_VERSION=2.1.2 \
|
||||
THEORA_VERSION=1.1.1 \
|
||||
VORBIS_VERSION=1.3.5 \
|
||||
VPX_VERSION=1.8.0 \
|
||||
WEBP_VERSION=1.0.2 \
|
||||
X264_VERSION=20170226-2245-stable \
|
||||
X265_VERSION=3.1.1 \
|
||||
XAU_VERSION=1.0.9 \
|
||||
XORG_MACROS_VERSION=1.19.2 \
|
||||
XPROTO_VERSION=7.0.31 \
|
||||
XVID_VERSION=1.3.4 \
|
||||
LIBXML2_VERSION=2.9.10 \
|
||||
LIBBLURAY_VERSION=1.1.2 \
|
||||
LIBZMQ_VERSION=4.3.2 \
|
||||
SRC=/usr/local
|
||||
|
||||
ARG FREETYPE_SHA256SUM="5d03dd76c2171a7601e9ce10551d52d4471cf92cd205948e60289251daddffa8 freetype-2.5.5.tar.gz"
|
||||
ARG FRIBIDI_SHA256SUM="3fc96fa9473bd31dcb5500bdf1aa78b337ba13eb8c301e7c28923fea982453a8 0.19.7.tar.gz"
|
||||
ARG LIBASS_SHA256SUM="8fadf294bf701300d4605e6f1d92929304187fca4b8d8a47889315526adbafd7 0.13.7.tar.gz"
|
||||
ARG LIBVIDSTAB_SHA256SUM="14d2a053e56edad4f397be0cb3ef8eb1ec3150404ce99a426c4eb641861dc0bb v1.1.0.tar.gz"
|
||||
ARG OGG_SHA256SUM="e19ee34711d7af328cb26287f4137e70630e7261b17cbe3cd41011d73a654692 libogg-1.3.2.tar.gz"
|
||||
ARG OPUS_SHA256SUM="77db45a87b51578fbc49555ef1b10926179861d854eb2613207dc79d9ec0a9a9 opus-1.2.tar.gz"
|
||||
ARG THEORA_SHA256SUM="40952956c47811928d1e7922cda3bc1f427eb75680c3c37249c91e949054916b libtheora-1.1.1.tar.gz"
|
||||
ARG VORBIS_SHA256SUM="6efbcecdd3e5dfbf090341b485da9d176eb250d893e3eb378c428a2db38301ce libvorbis-1.3.5.tar.gz"
|
||||
ARG XVID_SHA256SUM="4e9fd62728885855bc5007fe1be58df42e5e274497591fec37249e1052ae316f xvidcore-1.3.4.tar.gz"
|
||||
ARG LIBXML2_SHA256SUM="f07dab13bf42d2b8db80620cce7419b3b87827cc937c8bb20fe13b8571ee9501 libxml2-v2.9.10.tar.gz"
|
||||
ARG LIBBLURAY_SHA256SUM="a3dd452239b100dc9da0d01b30e1692693e2a332a7d29917bf84bb10ea7c0b42 libbluray-1.1.2.tar.bz2"
|
||||
ARG LIBZMQ_SHA256SUM="02ecc88466ae38cf2c8d79f09cfd2675ba299a439680b64ade733e26a349edeb v4.3.2.tar.gz"
|
||||
|
||||
|
||||
ARG LD_LIBRARY_PATH=/opt/ffmpeg/lib
|
||||
ARG MAKEFLAGS="-j2"
|
||||
ARG PKG_CONFIG_PATH="/opt/ffmpeg/share/pkgconfig:/opt/ffmpeg/lib/pkgconfig:/opt/ffmpeg/lib64/pkgconfig"
|
||||
ARG PREFIX=/opt/ffmpeg
|
||||
ARG LD_LIBRARY_PATH="/opt/ffmpeg/lib:/opt/ffmpeg/lib64:/usr/lib64:/usr/lib:/lib64:/lib"
|
||||
|
||||
|
||||
RUN buildDeps="autoconf \
|
||||
automake \
|
||||
cmake \
|
||||
curl \
|
||||
bzip2 \
|
||||
libexpat1-dev \
|
||||
g++ \
|
||||
gcc \
|
||||
git \
|
||||
gperf \
|
||||
libtool \
|
||||
make \
|
||||
nasm \
|
||||
perl \
|
||||
pkg-config \
|
||||
python \
|
||||
libssl-dev \
|
||||
yasm \
|
||||
linux-headers-raspi2 \
|
||||
libomxil-bellagio-dev \
|
||||
zlib1g-dev" && \
|
||||
apt-get -yqq update && \
|
||||
apt-get install -yq --no-install-recommends ${buildDeps}
|
||||
## opencore-amr https://sourceforge.net/projects/opencore-amr/
|
||||
RUN \
|
||||
DIR=/tmp/opencore-amr && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://versaweb.dl.sourceforge.net/project/opencore-amr/opencore-amr/opencore-amr-${OPENCOREAMR_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
## x264 http://www.videolan.org/developers/x264.html
|
||||
RUN \
|
||||
DIR=/tmp/x264 && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://download.videolan.org/pub/videolan/x264/snapshots/x264-snapshot-${X264_VERSION}.tar.bz2 | \
|
||||
tar -jx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared --enable-pic --disable-cli && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### x265 http://x265.org/
|
||||
RUN \
|
||||
DIR=/tmp/x265 && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://download.videolan.org/pub/videolan/x265/x265_${X265_VERSION}.tar.gz | \
|
||||
tar -zx && \
|
||||
cd x265_${X265_VERSION}/build/linux && \
|
||||
sed -i "/-DEXTRA_LIB/ s/$/ -DCMAKE_INSTALL_PREFIX=\${PREFIX}/" multilib.sh && \
|
||||
sed -i "/^cmake/ s/$/ -DENABLE_CLI=OFF/" multilib.sh && \
|
||||
export CXXFLAGS="${CXXFLAGS} -fPIC" && \
|
||||
./multilib.sh && \
|
||||
make -C 8bit install && \
|
||||
rm -rf ${DIR}
|
||||
### libogg https://www.xiph.org/ogg/
|
||||
RUN \
|
||||
DIR=/tmp/ogg && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xiph.org/releases/ogg/libogg-${OGG_VERSION}.tar.gz && \
|
||||
echo ${OGG_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f libogg-${OGG_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### libopus https://www.opus-codec.org/
|
||||
RUN \
|
||||
DIR=/tmp/opus && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://archive.mozilla.org/pub/opus/opus-${OPUS_VERSION}.tar.gz && \
|
||||
echo ${OPUS_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f opus-${OPUS_VERSION}.tar.gz && \
|
||||
autoreconf -fiv && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### libvorbis https://xiph.org/vorbis/
|
||||
RUN \
|
||||
DIR=/tmp/vorbis && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xiph.org/releases/vorbis/libvorbis-${VORBIS_VERSION}.tar.gz && \
|
||||
echo ${VORBIS_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f libvorbis-${VORBIS_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --with-ogg="${PREFIX}" --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### libtheora http://www.theora.org/
|
||||
RUN \
|
||||
DIR=/tmp/theora && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xiph.org/releases/theora/libtheora-${THEORA_VERSION}.tar.gz && \
|
||||
echo ${THEORA_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f libtheora-${THEORA_VERSION}.tar.gz && \
|
||||
curl -sL 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' -o config.guess && \
|
||||
curl -sL 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' -o config.sub && \
|
||||
./configure --prefix="${PREFIX}" --with-ogg="${PREFIX}" --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### libvpx https://www.webmproject.org/code/
|
||||
RUN \
|
||||
DIR=/tmp/vpx && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://codeload.github.com/webmproject/libvpx/tar.gz/v${VPX_VERSION} | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-vp8 --enable-vp9 --enable-vp9-highbitdepth --enable-pic --enable-shared \
|
||||
--disable-debug --disable-examples --disable-docs --disable-install-bins && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### libwebp https://developers.google.com/speed/webp/
|
||||
RUN \
|
||||
DIR=/tmp/vebp && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-${WEBP_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### libmp3lame http://lame.sourceforge.net/
|
||||
RUN \
|
||||
DIR=/tmp/lame && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://versaweb.dl.sourceforge.net/project/lame/lame/$(echo ${LAME_VERSION} | sed -e 's/[^0-9]*\([0-9]*\)[.]\([0-9]*\)[.]\([0-9]*\)\([0-9A-Za-z-]*\)/\1.\2/')/lame-${LAME_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --bindir="${PREFIX}/bin" --enable-shared --enable-nasm --disable-frontend && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### xvid https://www.xvid.com/
|
||||
RUN \
|
||||
DIR=/tmp/xvid && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xvid.org/downloads/xvidcore-${XVID_VERSION}.tar.gz && \
|
||||
echo ${XVID_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx -f xvidcore-${XVID_VERSION}.tar.gz && \
|
||||
cd xvidcore/build/generic && \
|
||||
./configure --prefix="${PREFIX}" --bindir="${PREFIX}/bin" && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### fdk-aac https://github.com/mstorsjo/fdk-aac
|
||||
RUN \
|
||||
DIR=/tmp/fdk-aac && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://github.com/mstorsjo/fdk-aac/archive/v${FDKAAC_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
autoreconf -fiv && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared --datadir="${DIR}" && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
## openjpeg https://github.com/uclouvain/openjpeg
|
||||
RUN \
|
||||
DIR=/tmp/openjpeg && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
export CFLAGS="${CFLAGS} -DPNG_ARM_NEON_OPT=0" && \
|
||||
cmake -DBUILD_THIRDPARTY:BOOL=ON -DCMAKE_INSTALL_PREFIX="${PREFIX}" . && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
## freetype https://www.freetype.org/
|
||||
RUN \
|
||||
DIR=/tmp/freetype && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://download.savannah.gnu.org/releases/freetype/freetype-${FREETYPE_VERSION}.tar.gz && \
|
||||
echo ${FREETYPE_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f freetype-${FREETYPE_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
## libvstab https://github.com/georgmartius/vid.stab
|
||||
RUN \
|
||||
DIR=/tmp/vid.stab && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/georgmartius/vid.stab/archive/v${LIBVIDSTAB_VERSION}.tar.gz && \
|
||||
echo ${LIBVIDSTAB_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f v${LIBVIDSTAB_VERSION}.tar.gz && \
|
||||
cmake -DCMAKE_INSTALL_PREFIX="${PREFIX}" . && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
## fridibi https://www.fribidi.org/
|
||||
RUN \
|
||||
DIR=/tmp/fribidi && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/fribidi/fribidi/archive/${FRIBIDI_VERSION}.tar.gz && \
|
||||
echo ${FRIBIDI_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f ${FRIBIDI_VERSION}.tar.gz && \
|
||||
sed -i 's/^SUBDIRS =.*/SUBDIRS=gen.tab charset lib bin/' Makefile.am && \
|
||||
./bootstrap --no-config --auto && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make -j1 && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
## fontconfig https://www.freedesktop.org/wiki/Software/fontconfig/
|
||||
RUN \
|
||||
DIR=/tmp/fontconfig && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.freedesktop.org/software/fontconfig/release/fontconfig-${FONTCONFIG_VERSION}.tar.bz2 && \
|
||||
tar -jx --strip-components=1 -f fontconfig-${FONTCONFIG_VERSION}.tar.bz2 && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
## libass https://github.com/libass/libass
|
||||
RUN \
|
||||
DIR=/tmp/libass && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/libass/libass/archive/${LIBASS_VERSION}.tar.gz && \
|
||||
echo ${LIBASS_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f ${LIBASS_VERSION}.tar.gz && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
## kvazaar https://github.com/ultravideo/kvazaar
|
||||
RUN \
|
||||
DIR=/tmp/kvazaar && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/ultravideo/kvazaar/archive/v${KVAZAAR_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f v${KVAZAAR_VERSION}.tar.gz && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/aom && \
|
||||
git clone --branch ${AOM_VERSION} --depth 1 https://aomedia.googlesource.com/aom ${DIR} ; \
|
||||
cd ${DIR} ; \
|
||||
rm -rf CMakeCache.txt CMakeFiles ; \
|
||||
mkdir -p ./aom_build ; \
|
||||
cd ./aom_build ; \
|
||||
cmake -DCMAKE_INSTALL_PREFIX="${PREFIX}" -DBUILD_SHARED_LIBS=1 ..; \
|
||||
make ; \
|
||||
make install ; \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libxcb (and supporting libraries) for screen capture https://xcb.freedesktop.org/
|
||||
RUN \
|
||||
DIR=/tmp/xorg-macros && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.x.org/archive//individual/util/util-macros-${XORG_MACROS_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f util-macros-${XORG_MACROS_VERSION}.tar.gz && \
|
||||
./configure --srcdir=${DIR} --prefix="${PREFIX}" && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/xproto && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.x.org/archive/individual/proto/xproto-${XPROTO_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f xproto-${XPROTO_VERSION}.tar.gz && \
|
||||
curl -sL 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' -o config.guess && \
|
||||
curl -sL 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' -o config.sub && \
|
||||
./configure --srcdir=${DIR} --prefix="${PREFIX}" && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libXau && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.x.org/archive/individual/lib/libXau-${XAU_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f libXau-${XAU_VERSION}.tar.gz && \
|
||||
./configure --srcdir=${DIR} --prefix="${PREFIX}" && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libpthread-stubs && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://xcb.freedesktop.org/dist/libpthread-stubs-${LIBPTHREAD_STUBS_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f libpthread-stubs-${LIBPTHREAD_STUBS_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libxcb-proto && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://xcb.freedesktop.org/dist/xcb-proto-${XCBPROTO_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f xcb-proto-${XCBPROTO_VERSION}.tar.gz && \
|
||||
ACLOCAL_PATH="${PREFIX}/share/aclocal" ./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libxcb && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://xcb.freedesktop.org/dist/libxcb-${LIBXCB_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f libxcb-${LIBXCB_VERSION}.tar.gz && \
|
||||
ACLOCAL_PATH="${PREFIX}/share/aclocal" ./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libxml2 - for libbluray
|
||||
RUN \
|
||||
DIR=/tmp/libxml2 && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://gitlab.gnome.org/GNOME/libxml2/-/archive/v${LIBXML2_VERSION}/libxml2-v${LIBXML2_VERSION}.tar.gz && \
|
||||
echo ${LIBXML2_SHA256SUM} | sha256sum --check && \
|
||||
tar -xz --strip-components=1 -f libxml2-v${LIBXML2_VERSION}.tar.gz && \
|
||||
./autogen.sh --prefix="${PREFIX}" --with-ftp=no --with-http=no --with-python=no && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libbluray - Requires libxml, freetype, and fontconfig
|
||||
RUN \
|
||||
DIR=/tmp/libbluray && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://download.videolan.org/pub/videolan/libbluray/${LIBBLURAY_VERSION}/libbluray-${LIBBLURAY_VERSION}.tar.bz2 && \
|
||||
echo ${LIBBLURAY_SHA256SUM} | sha256sum --check && \
|
||||
tar -jx --strip-components=1 -f libbluray-${LIBBLURAY_VERSION}.tar.bz2 && \
|
||||
./configure --prefix="${PREFIX}" --disable-examples --disable-bdjava-jar --disable-static --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libzmq https://github.com/zeromq/libzmq/
|
||||
RUN \
|
||||
DIR=/tmp/libzmq && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/zeromq/libzmq/archive/v${LIBZMQ_VERSION}.tar.gz && \
|
||||
echo ${LIBZMQ_SHA256SUM} | sha256sum --check && \
|
||||
tar -xz --strip-components=1 -f v${LIBZMQ_VERSION}.tar.gz && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make -j $(nproc) && \
|
||||
make check && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## ffmpeg https://ffmpeg.org/
|
||||
RUN \
|
||||
DIR=/tmp/ffmpeg && mkdir -p ${DIR} && cd ${DIR} && \
|
||||
curl -sLO https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2 && \
|
||||
tar -jx --strip-components=1 -f ffmpeg-${FFMPEG_VERSION}.tar.bz2
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/ffmpeg && mkdir -p ${DIR} && cd ${DIR} && \
|
||||
./configure \
|
||||
--disable-debug \
|
||||
--disable-doc \
|
||||
--disable-ffplay \
|
||||
--enable-shared \
|
||||
--enable-avresample \
|
||||
--enable-libopencore-amrnb \
|
||||
--enable-libopencore-amrwb \
|
||||
--enable-gpl \
|
||||
--enable-libass \
|
||||
--enable-fontconfig \
|
||||
--enable-libfreetype \
|
||||
--enable-libvidstab \
|
||||
--enable-libmp3lame \
|
||||
--enable-libopus \
|
||||
--enable-libtheora \
|
||||
--enable-libvorbis \
|
||||
--enable-libvpx \
|
||||
--enable-libwebp \
|
||||
--enable-libxcb \
|
||||
--enable-libx265 \
|
||||
--enable-libxvid \
|
||||
--enable-libx264 \
|
||||
--enable-nonfree \
|
||||
--enable-openssl \
|
||||
--enable-libfdk_aac \
|
||||
--enable-postproc \
|
||||
--enable-small \
|
||||
--enable-version3 \
|
||||
--enable-libbluray \
|
||||
--enable-libzmq \
|
||||
--extra-libs=-ldl \
|
||||
--prefix="${PREFIX}" \
|
||||
--enable-libopenjpeg \
|
||||
--enable-libkvazaar \
|
||||
--enable-libaom \
|
||||
--extra-libs=-lpthread \
|
||||
# --enable-omx \
|
||||
# --enable-omx-rpi \
|
||||
# --enable-mmal \
|
||||
--enable-v4l2_m2m \
|
||||
--enable-neon \
|
||||
--extra-cflags="-I${PREFIX}/include" \
|
||||
--extra-ldflags="-L${PREFIX}/lib" && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
make tools/zmqsend && cp tools/zmqsend ${PREFIX}/bin/ && \
|
||||
make distclean && \
|
||||
hash -r && \
|
||||
cd tools && \
|
||||
make qt-faststart && cp qt-faststart ${PREFIX}/bin/
|
||||
|
||||
## cleanup
|
||||
RUN \
|
||||
ldd ${PREFIX}/bin/ffmpeg | grep opt/ffmpeg | cut -d ' ' -f 3 | xargs -i cp {} /usr/local/lib/ && \
|
||||
for lib in /usr/local/lib/*.so.*; do ln -s "${lib##*/}" "${lib%%.so.*}".so; done && \
|
||||
cp ${PREFIX}/bin/* /usr/local/bin/ && \
|
||||
cp -r ${PREFIX}/share/ffmpeg /usr/local/share/ && \
|
||||
LD_LIBRARY_PATH=/usr/local/lib ffmpeg -buildconf && \
|
||||
cp -r ${PREFIX}/include/libav* ${PREFIX}/include/libpostproc ${PREFIX}/include/libsw* /usr/local/include && \
|
||||
mkdir -p /usr/local/lib/pkgconfig && \
|
||||
for pc in ${PREFIX}/lib/pkgconfig/libav*.pc ${PREFIX}/lib/pkgconfig/libpostproc.pc ${PREFIX}/lib/pkgconfig/libsw*.pc; do \
|
||||
sed "s:${PREFIX}:/usr/local:g" <"$pc" >/usr/local/lib/pkgconfig/"${pc##*/}"; \
|
||||
done
|
||||
|
||||
FROM base AS release
|
||||
|
||||
ENV LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64:/lib:/lib64
|
||||
|
||||
CMD ["--help"]
|
||||
ENTRYPOINT ["ffmpeg"]
|
||||
|
||||
COPY --from=build /usr/local /usr/local/
|
||||
|
||||
# Run ffmpeg with -c:v h264_v4l2m2m to enable HW accell for decoding on raspberry pi4 64-bit
|
@@ -1,526 +0,0 @@
|
||||
# inspired by:
|
||||
# https://github.com/collelog/ffmpeg/blob/master/4.3.1-alpine-rpi4-arm64v8.Dockerfile
|
||||
# https://github.com/jrottenberg/ffmpeg/pull/158/files
|
||||
# https://github.com/jrottenberg/ffmpeg/pull/239
|
||||
FROM ubuntu:20.04 AS base
|
||||
|
||||
WORKDIR /tmp/workdir
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get -yqq update && \
|
||||
apt-get install -yq --no-install-recommends ca-certificates expat libgomp1 && \
|
||||
apt-get autoremove -y && \
|
||||
apt-get clean -y
|
||||
|
||||
FROM base as build
|
||||
|
||||
ENV FFMPEG_VERSION=4.3.1 \
|
||||
AOM_VERSION=v1.0.0 \
|
||||
FDKAAC_VERSION=0.1.5 \
|
||||
FONTCONFIG_VERSION=2.12.4 \
|
||||
FREETYPE_VERSION=2.5.5 \
|
||||
FRIBIDI_VERSION=0.19.7 \
|
||||
KVAZAAR_VERSION=1.2.0 \
|
||||
LAME_VERSION=3.100 \
|
||||
LIBASS_VERSION=0.13.7 \
|
||||
LIBPTHREAD_STUBS_VERSION=0.4 \
|
||||
LIBVIDSTAB_VERSION=1.1.0 \
|
||||
LIBXCB_VERSION=1.13.1 \
|
||||
XCBPROTO_VERSION=1.13 \
|
||||
OGG_VERSION=1.3.2 \
|
||||
OPENCOREAMR_VERSION=0.1.5 \
|
||||
OPUS_VERSION=1.2 \
|
||||
OPENJPEG_VERSION=2.1.2 \
|
||||
THEORA_VERSION=1.1.1 \
|
||||
VORBIS_VERSION=1.3.5 \
|
||||
VPX_VERSION=1.8.0 \
|
||||
WEBP_VERSION=1.0.2 \
|
||||
X264_VERSION=20170226-2245-stable \
|
||||
X265_VERSION=3.1.1 \
|
||||
XAU_VERSION=1.0.9 \
|
||||
XORG_MACROS_VERSION=1.19.2 \
|
||||
XPROTO_VERSION=7.0.31 \
|
||||
XVID_VERSION=1.3.4 \
|
||||
LIBXML2_VERSION=2.9.10 \
|
||||
LIBBLURAY_VERSION=1.1.2 \
|
||||
LIBZMQ_VERSION=4.3.2 \
|
||||
SRC=/usr/local
|
||||
|
||||
ARG FREETYPE_SHA256SUM="5d03dd76c2171a7601e9ce10551d52d4471cf92cd205948e60289251daddffa8 freetype-2.5.5.tar.gz"
|
||||
ARG FRIBIDI_SHA256SUM="3fc96fa9473bd31dcb5500bdf1aa78b337ba13eb8c301e7c28923fea982453a8 0.19.7.tar.gz"
|
||||
ARG LIBASS_SHA256SUM="8fadf294bf701300d4605e6f1d92929304187fca4b8d8a47889315526adbafd7 0.13.7.tar.gz"
|
||||
ARG LIBVIDSTAB_SHA256SUM="14d2a053e56edad4f397be0cb3ef8eb1ec3150404ce99a426c4eb641861dc0bb v1.1.0.tar.gz"
|
||||
ARG OGG_SHA256SUM="e19ee34711d7af328cb26287f4137e70630e7261b17cbe3cd41011d73a654692 libogg-1.3.2.tar.gz"
|
||||
ARG OPUS_SHA256SUM="77db45a87b51578fbc49555ef1b10926179861d854eb2613207dc79d9ec0a9a9 opus-1.2.tar.gz"
|
||||
ARG THEORA_SHA256SUM="40952956c47811928d1e7922cda3bc1f427eb75680c3c37249c91e949054916b libtheora-1.1.1.tar.gz"
|
||||
ARG VORBIS_SHA256SUM="6efbcecdd3e5dfbf090341b485da9d176eb250d893e3eb378c428a2db38301ce libvorbis-1.3.5.tar.gz"
|
||||
ARG XVID_SHA256SUM="4e9fd62728885855bc5007fe1be58df42e5e274497591fec37249e1052ae316f xvidcore-1.3.4.tar.gz"
|
||||
ARG LIBXML2_SHA256SUM="f07dab13bf42d2b8db80620cce7419b3b87827cc937c8bb20fe13b8571ee9501 libxml2-v2.9.10.tar.gz"
|
||||
ARG LIBBLURAY_SHA256SUM="a3dd452239b100dc9da0d01b30e1692693e2a332a7d29917bf84bb10ea7c0b42 libbluray-1.1.2.tar.bz2"
|
||||
ARG LIBZMQ_SHA256SUM="02ecc88466ae38cf2c8d79f09cfd2675ba299a439680b64ade733e26a349edeb v4.3.2.tar.gz"
|
||||
|
||||
|
||||
ARG LD_LIBRARY_PATH=/opt/ffmpeg/lib
|
||||
ARG MAKEFLAGS="-j2"
|
||||
ARG PKG_CONFIG_PATH="/opt/ffmpeg/share/pkgconfig:/opt/ffmpeg/lib/pkgconfig:/opt/ffmpeg/lib64/pkgconfig"
|
||||
ARG PREFIX=/opt/ffmpeg
|
||||
ARG LD_LIBRARY_PATH="/opt/ffmpeg/lib:/opt/ffmpeg/lib64:/usr/lib64:/usr/lib:/lib64:/lib"
|
||||
|
||||
|
||||
RUN buildDeps="autoconf \
|
||||
automake \
|
||||
cmake \
|
||||
curl \
|
||||
bzip2 \
|
||||
libexpat1-dev \
|
||||
g++ \
|
||||
gcc \
|
||||
git \
|
||||
gperf \
|
||||
libtool \
|
||||
make \
|
||||
nasm \
|
||||
perl \
|
||||
pkg-config \
|
||||
python \
|
||||
libssl-dev \
|
||||
yasm \
|
||||
libva-dev \
|
||||
zlib1g-dev" && \
|
||||
apt-get -yqq update && \
|
||||
apt-get install -yq --no-install-recommends ${buildDeps}
|
||||
## opencore-amr https://sourceforge.net/projects/opencore-amr/
|
||||
RUN \
|
||||
DIR=/tmp/opencore-amr && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://versaweb.dl.sourceforge.net/project/opencore-amr/opencore-amr/opencore-amr-${OPENCOREAMR_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## x264 http://www.videolan.org/developers/x264.html
|
||||
RUN \
|
||||
DIR=/tmp/x264 && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://download.videolan.org/pub/videolan/x264/snapshots/x264-snapshot-${X264_VERSION}.tar.bz2 | \
|
||||
tar -jx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared --enable-pic --disable-cli && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### x265 http://x265.org/
|
||||
RUN \
|
||||
DIR=/tmp/x265 && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://download.videolan.org/pub/videolan/x265/x265_${X265_VERSION}.tar.gz | \
|
||||
tar -zx && \
|
||||
cd x265_${X265_VERSION}/build/linux && \
|
||||
sed -i "/-DEXTRA_LIB/ s/$/ -DCMAKE_INSTALL_PREFIX=\${PREFIX}/" multilib.sh && \
|
||||
sed -i "/^cmake/ s/$/ -DENABLE_CLI=OFF/" multilib.sh && \
|
||||
./multilib.sh && \
|
||||
make -C 8bit install && \
|
||||
rm -rf ${DIR}
|
||||
### libogg https://www.xiph.org/ogg/
|
||||
RUN \
|
||||
DIR=/tmp/ogg && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xiph.org/releases/ogg/libogg-${OGG_VERSION}.tar.gz && \
|
||||
echo ${OGG_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f libogg-${OGG_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libopus https://www.opus-codec.org/
|
||||
RUN \
|
||||
DIR=/tmp/opus && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://archive.mozilla.org/pub/opus/opus-${OPUS_VERSION}.tar.gz && \
|
||||
echo ${OPUS_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f opus-${OPUS_VERSION}.tar.gz && \
|
||||
autoreconf -fiv && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libvorbis https://xiph.org/vorbis/
|
||||
RUN \
|
||||
DIR=/tmp/vorbis && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xiph.org/releases/vorbis/libvorbis-${VORBIS_VERSION}.tar.gz && \
|
||||
echo ${VORBIS_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f libvorbis-${VORBIS_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --with-ogg="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libtheora http://www.theora.org/
|
||||
RUN \
|
||||
DIR=/tmp/theora && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xiph.org/releases/theora/libtheora-${THEORA_VERSION}.tar.gz && \
|
||||
echo ${THEORA_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f libtheora-${THEORA_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --with-ogg="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libvpx https://www.webmproject.org/code/
|
||||
RUN \
|
||||
DIR=/tmp/vpx && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://codeload.github.com/webmproject/libvpx/tar.gz/v${VPX_VERSION} | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-vp8 --enable-vp9 --enable-vp9-highbitdepth --enable-pic --enable-shared \
|
||||
--disable-debug --disable-examples --disable-docs --disable-install-bins && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libwebp https://developers.google.com/speed/webp/
|
||||
RUN \
|
||||
DIR=/tmp/vebp && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-${WEBP_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libmp3lame http://lame.sourceforge.net/
|
||||
RUN \
|
||||
DIR=/tmp/lame && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://versaweb.dl.sourceforge.net/project/lame/lame/$(echo ${LAME_VERSION} | sed -e 's/[^0-9]*\([0-9]*\)[.]\([0-9]*\)[.]\([0-9]*\)\([0-9A-Za-z-]*\)/\1.\2/')/lame-${LAME_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --bindir="${PREFIX}/bin" --enable-shared --enable-nasm --disable-frontend && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### xvid https://www.xvid.com/
|
||||
RUN \
|
||||
DIR=/tmp/xvid && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xvid.org/downloads/xvidcore-${XVID_VERSION}.tar.gz && \
|
||||
echo ${XVID_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx -f xvidcore-${XVID_VERSION}.tar.gz && \
|
||||
cd xvidcore/build/generic && \
|
||||
./configure --prefix="${PREFIX}" --bindir="${PREFIX}/bin" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### fdk-aac https://github.com/mstorsjo/fdk-aac
|
||||
RUN \
|
||||
DIR=/tmp/fdk-aac && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://github.com/mstorsjo/fdk-aac/archive/v${FDKAAC_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
autoreconf -fiv && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared --datadir="${DIR}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## openjpeg https://github.com/uclouvain/openjpeg
|
||||
RUN \
|
||||
DIR=/tmp/openjpeg && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
cmake -DBUILD_THIRDPARTY:BOOL=ON -DCMAKE_INSTALL_PREFIX="${PREFIX}" . && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## freetype https://www.freetype.org/
|
||||
RUN \
|
||||
DIR=/tmp/freetype && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://download.savannah.gnu.org/releases/freetype/freetype-${FREETYPE_VERSION}.tar.gz && \
|
||||
echo ${FREETYPE_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f freetype-${FREETYPE_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## libvstab https://github.com/georgmartius/vid.stab
|
||||
RUN \
|
||||
DIR=/tmp/vid.stab && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/georgmartius/vid.stab/archive/v${LIBVIDSTAB_VERSION}.tar.gz && \
|
||||
echo ${LIBVIDSTAB_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f v${LIBVIDSTAB_VERSION}.tar.gz && \
|
||||
cmake -DCMAKE_INSTALL_PREFIX="${PREFIX}" . && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## fridibi https://www.fribidi.org/
|
||||
RUN \
|
||||
DIR=/tmp/fribidi && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/fribidi/fribidi/archive/${FRIBIDI_VERSION}.tar.gz && \
|
||||
echo ${FRIBIDI_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f ${FRIBIDI_VERSION}.tar.gz && \
|
||||
sed -i 's/^SUBDIRS =.*/SUBDIRS=gen.tab charset lib bin/' Makefile.am && \
|
||||
./bootstrap --no-config --auto && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make -j1 && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## fontconfig https://www.freedesktop.org/wiki/Software/fontconfig/
|
||||
RUN \
|
||||
DIR=/tmp/fontconfig && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.freedesktop.org/software/fontconfig/release/fontconfig-${FONTCONFIG_VERSION}.tar.bz2 && \
|
||||
tar -jx --strip-components=1 -f fontconfig-${FONTCONFIG_VERSION}.tar.bz2 && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## libass https://github.com/libass/libass
|
||||
RUN \
|
||||
DIR=/tmp/libass && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/libass/libass/archive/${LIBASS_VERSION}.tar.gz && \
|
||||
echo ${LIBASS_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f ${LIBASS_VERSION}.tar.gz && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## kvazaar https://github.com/ultravideo/kvazaar
|
||||
RUN \
|
||||
DIR=/tmp/kvazaar && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/ultravideo/kvazaar/archive/v${KVAZAAR_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f v${KVAZAAR_VERSION}.tar.gz && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/aom && \
|
||||
git clone --branch ${AOM_VERSION} --depth 1 https://aomedia.googlesource.com/aom ${DIR} ; \
|
||||
cd ${DIR} ; \
|
||||
rm -rf CMakeCache.txt CMakeFiles ; \
|
||||
mkdir -p ./aom_build ; \
|
||||
cd ./aom_build ; \
|
||||
cmake -DCMAKE_INSTALL_PREFIX="${PREFIX}" -DBUILD_SHARED_LIBS=1 ..; \
|
||||
make ; \
|
||||
make install ; \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libxcb (and supporting libraries) for screen capture https://xcb.freedesktop.org/
|
||||
RUN \
|
||||
DIR=/tmp/xorg-macros && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.x.org/archive//individual/util/util-macros-${XORG_MACROS_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f util-macros-${XORG_MACROS_VERSION}.tar.gz && \
|
||||
./configure --srcdir=${DIR} --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/xproto && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.x.org/archive/individual/proto/xproto-${XPROTO_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f xproto-${XPROTO_VERSION}.tar.gz && \
|
||||
./configure --srcdir=${DIR} --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libXau && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.x.org/archive/individual/lib/libXau-${XAU_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f libXau-${XAU_VERSION}.tar.gz && \
|
||||
./configure --srcdir=${DIR} --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libpthread-stubs && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://xcb.freedesktop.org/dist/libpthread-stubs-${LIBPTHREAD_STUBS_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f libpthread-stubs-${LIBPTHREAD_STUBS_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libxcb-proto && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://xcb.freedesktop.org/dist/xcb-proto-${XCBPROTO_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f xcb-proto-${XCBPROTO_VERSION}.tar.gz && \
|
||||
ACLOCAL_PATH="${PREFIX}/share/aclocal" ./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libxcb && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://xcb.freedesktop.org/dist/libxcb-${LIBXCB_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f libxcb-${LIBXCB_VERSION}.tar.gz && \
|
||||
ACLOCAL_PATH="${PREFIX}/share/aclocal" ./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libxml2 - for libbluray
|
||||
RUN \
|
||||
DIR=/tmp/libxml2 && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://gitlab.gnome.org/GNOME/libxml2/-/archive/v${LIBXML2_VERSION}/libxml2-v${LIBXML2_VERSION}.tar.gz && \
|
||||
echo ${LIBXML2_SHA256SUM} | sha256sum --check && \
|
||||
tar -xz --strip-components=1 -f libxml2-v${LIBXML2_VERSION}.tar.gz && \
|
||||
./autogen.sh --prefix="${PREFIX}" --with-ftp=no --with-http=no --with-python=no && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libbluray - Requires libxml, freetype, and fontconfig
|
||||
RUN \
|
||||
DIR=/tmp/libbluray && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://download.videolan.org/pub/videolan/libbluray/${LIBBLURAY_VERSION}/libbluray-${LIBBLURAY_VERSION}.tar.bz2 && \
|
||||
echo ${LIBBLURAY_SHA256SUM} | sha256sum --check && \
|
||||
tar -jx --strip-components=1 -f libbluray-${LIBBLURAY_VERSION}.tar.bz2 && \
|
||||
./configure --prefix="${PREFIX}" --disable-examples --disable-bdjava-jar --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libzmq https://github.com/zeromq/libzmq/
|
||||
RUN \
|
||||
DIR=/tmp/libzmq && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/zeromq/libzmq/archive/v${LIBZMQ_VERSION}.tar.gz && \
|
||||
echo ${LIBZMQ_SHA256SUM} | sha256sum --check && \
|
||||
tar -xz --strip-components=1 -f v${LIBZMQ_VERSION}.tar.gz && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make check && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## ffmpeg https://ffmpeg.org/
|
||||
RUN \
|
||||
DIR=/tmp/ffmpeg && mkdir -p ${DIR} && cd ${DIR} && \
|
||||
curl -sLO https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2 && \
|
||||
tar -jx --strip-components=1 -f ffmpeg-${FFMPEG_VERSION}.tar.bz2
|
||||
|
||||
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/ffmpeg && mkdir -p ${DIR} && cd ${DIR} && \
|
||||
./configure \
|
||||
--disable-debug \
|
||||
--disable-doc \
|
||||
--disable-ffplay \
|
||||
--enable-shared \
|
||||
--enable-avresample \
|
||||
--enable-libopencore-amrnb \
|
||||
--enable-libopencore-amrwb \
|
||||
--enable-gpl \
|
||||
--enable-libass \
|
||||
--enable-fontconfig \
|
||||
--enable-libfreetype \
|
||||
--enable-libvidstab \
|
||||
--enable-libmp3lame \
|
||||
--enable-libopus \
|
||||
--enable-libtheora \
|
||||
--enable-libvorbis \
|
||||
--enable-libvpx \
|
||||
--enable-libwebp \
|
||||
--enable-libxcb \
|
||||
--enable-libx265 \
|
||||
--enable-libxvid \
|
||||
--enable-libx264 \
|
||||
--enable-nonfree \
|
||||
--enable-openssl \
|
||||
--enable-libfdk_aac \
|
||||
--enable-postproc \
|
||||
--enable-small \
|
||||
--enable-version3 \
|
||||
--enable-libbluray \
|
||||
--enable-libzmq \
|
||||
--extra-libs=-ldl \
|
||||
--prefix="${PREFIX}" \
|
||||
--enable-libopenjpeg \
|
||||
--enable-libkvazaar \
|
||||
--enable-libaom \
|
||||
--extra-libs=-lpthread \
|
||||
--enable-vaapi \
|
||||
--extra-cflags="-I${PREFIX}/include" \
|
||||
--extra-ldflags="-L${PREFIX}/lib" && \
|
||||
make && \
|
||||
make install && \
|
||||
make tools/zmqsend && cp tools/zmqsend ${PREFIX}/bin/ && \
|
||||
make distclean && \
|
||||
hash -r && \
|
||||
cd tools && \
|
||||
make qt-faststart && cp qt-faststart ${PREFIX}/bin/
|
||||
|
||||
## cleanup
|
||||
RUN \
|
||||
ldd ${PREFIX}/bin/ffmpeg | grep opt/ffmpeg | cut -d ' ' -f 3 | xargs -i cp {} /usr/local/lib/ && \
|
||||
for lib in /usr/local/lib/*.so.*; do ln -s "${lib##*/}" "${lib%%.so.*}".so; done && \
|
||||
cp ${PREFIX}/bin/* /usr/local/bin/ && \
|
||||
cp -r ${PREFIX}/share/ffmpeg /usr/local/share/ && \
|
||||
LD_LIBRARY_PATH=/usr/local/lib ffmpeg -buildconf && \
|
||||
cp -r ${PREFIX}/include/libav* ${PREFIX}/include/libpostproc ${PREFIX}/include/libsw* /usr/local/include && \
|
||||
mkdir -p /usr/local/lib/pkgconfig && \
|
||||
for pc in ${PREFIX}/lib/pkgconfig/libav*.pc ${PREFIX}/lib/pkgconfig/libpostproc.pc ${PREFIX}/lib/pkgconfig/libsw*.pc; do \
|
||||
sed "s:${PREFIX}:/usr/local:g" <"$pc" >/usr/local/lib/pkgconfig/"${pc##*/}"; \
|
||||
done
|
||||
|
||||
FROM base AS release
|
||||
|
||||
ENV LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64:/lib:/lib64
|
||||
|
||||
CMD ["--help"]
|
||||
ENTRYPOINT ["ffmpeg"]
|
||||
|
||||
COPY --from=build /usr/local /usr/local/
|
||||
|
||||
RUN \
|
||||
apt-get update -y && \
|
||||
apt-get install -y --no-install-recommends libva-drm2 libva2 i965-va-driver && \
|
||||
rm -rf /var/lib/apt/lists/*
|
@@ -1,610 +0,0 @@
|
||||
# inspired by https://github.com/jrottenberg/ffmpeg/blob/master/docker-images/4.3/ubuntu1804/Dockerfile
|
||||
|
||||
# ffmpeg - http://ffmpeg.org/download.html
|
||||
#
|
||||
# From https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu
|
||||
#
|
||||
# https://hub.docker.com/r/jrottenberg/ffmpeg/
|
||||
#
|
||||
#
|
||||
|
||||
FROM nvidia/cuda:11.1-devel-ubuntu20.04 AS devel-base
|
||||
|
||||
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility,video
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
WORKDIR /tmp/workdir
|
||||
|
||||
RUN apt-get -yqq update && \
|
||||
apt-get install -yq --no-install-recommends ca-certificates expat libgomp1 && \
|
||||
apt-get autoremove -y && \
|
||||
apt-get clean -y
|
||||
|
||||
FROM nvidia/cuda:11.1-runtime-ubuntu20.04 AS runtime-base
|
||||
|
||||
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility,video
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
WORKDIR /tmp/workdir
|
||||
|
||||
RUN apt-get -yqq update && \
|
||||
apt-get install -yq --no-install-recommends ca-certificates expat libgomp1 libxcb-shape0-dev && \
|
||||
apt-get autoremove -y && \
|
||||
apt-get clean -y
|
||||
|
||||
|
||||
FROM devel-base as build
|
||||
|
||||
ENV NVIDIA_HEADERS_VERSION=9.1.23.1
|
||||
|
||||
ENV FFMPEG_VERSION=4.3.1 \
|
||||
AOM_VERSION=v1.0.0 \
|
||||
FDKAAC_VERSION=0.1.5 \
|
||||
FONTCONFIG_VERSION=2.12.4 \
|
||||
FREETYPE_VERSION=2.5.5 \
|
||||
FRIBIDI_VERSION=0.19.7 \
|
||||
KVAZAAR_VERSION=1.2.0 \
|
||||
LAME_VERSION=3.100 \
|
||||
LIBASS_VERSION=0.13.7 \
|
||||
LIBPTHREAD_STUBS_VERSION=0.4 \
|
||||
LIBVIDSTAB_VERSION=1.1.0 \
|
||||
LIBXCB_VERSION=1.13.1 \
|
||||
XCBPROTO_VERSION=1.13 \
|
||||
OGG_VERSION=1.3.2 \
|
||||
OPENCOREAMR_VERSION=0.1.5 \
|
||||
OPUS_VERSION=1.2 \
|
||||
OPENJPEG_VERSION=2.1.2 \
|
||||
THEORA_VERSION=1.1.1 \
|
||||
VORBIS_VERSION=1.3.5 \
|
||||
VPX_VERSION=1.8.0 \
|
||||
WEBP_VERSION=1.0.2 \
|
||||
X264_VERSION=20170226-2245-stable \
|
||||
X265_VERSION=3.1.1 \
|
||||
XAU_VERSION=1.0.9 \
|
||||
XORG_MACROS_VERSION=1.19.2 \
|
||||
XPROTO_VERSION=7.0.31 \
|
||||
XVID_VERSION=1.3.4 \
|
||||
LIBXML2_VERSION=2.9.10 \
|
||||
LIBBLURAY_VERSION=1.1.2 \
|
||||
LIBZMQ_VERSION=4.3.2 \
|
||||
LIBSRT_VERSION=1.4.1 \
|
||||
LIBARIBB24_VERSION=1.0.3 \
|
||||
LIBPNG_VERSION=1.6.9 \
|
||||
SRC=/usr/local
|
||||
|
||||
ARG FREETYPE_SHA256SUM="5d03dd76c2171a7601e9ce10551d52d4471cf92cd205948e60289251daddffa8 freetype-2.5.5.tar.gz"
|
||||
ARG FRIBIDI_SHA256SUM="3fc96fa9473bd31dcb5500bdf1aa78b337ba13eb8c301e7c28923fea982453a8 0.19.7.tar.gz"
|
||||
ARG LIBASS_SHA256SUM="8fadf294bf701300d4605e6f1d92929304187fca4b8d8a47889315526adbafd7 0.13.7.tar.gz"
|
||||
ARG LIBVIDSTAB_SHA256SUM="14d2a053e56edad4f397be0cb3ef8eb1ec3150404ce99a426c4eb641861dc0bb v1.1.0.tar.gz"
|
||||
ARG OGG_SHA256SUM="e19ee34711d7af328cb26287f4137e70630e7261b17cbe3cd41011d73a654692 libogg-1.3.2.tar.gz"
|
||||
ARG OPUS_SHA256SUM="77db45a87b51578fbc49555ef1b10926179861d854eb2613207dc79d9ec0a9a9 opus-1.2.tar.gz"
|
||||
ARG THEORA_SHA256SUM="40952956c47811928d1e7922cda3bc1f427eb75680c3c37249c91e949054916b libtheora-1.1.1.tar.gz"
|
||||
ARG VORBIS_SHA256SUM="6efbcecdd3e5dfbf090341b485da9d176eb250d893e3eb378c428a2db38301ce libvorbis-1.3.5.tar.gz"
|
||||
ARG XVID_SHA256SUM="4e9fd62728885855bc5007fe1be58df42e5e274497591fec37249e1052ae316f xvidcore-1.3.4.tar.gz"
|
||||
ARG LIBXML2_SHA256SUM="f07dab13bf42d2b8db80620cce7419b3b87827cc937c8bb20fe13b8571ee9501 libxml2-v2.9.10.tar.gz"
|
||||
ARG LIBBLURAY_SHA256SUM="a3dd452239b100dc9da0d01b30e1692693e2a332a7d29917bf84bb10ea7c0b42 libbluray-1.1.2.tar.bz2"
|
||||
ARG LIBZMQ_SHA256SUM="02ecc88466ae38cf2c8d79f09cfd2675ba299a439680b64ade733e26a349edeb v4.3.2.tar.gz"
|
||||
ARG LIBARIBB24_SHA256SUM="f61560738926e57f9173510389634d8c06cabedfa857db4b28fb7704707ff128 v1.0.3.tar.gz"
|
||||
|
||||
|
||||
ARG LD_LIBRARY_PATH=/opt/ffmpeg/lib
|
||||
ARG MAKEFLAGS="-j2"
|
||||
ARG PKG_CONFIG_PATH="/opt/ffmpeg/share/pkgconfig:/opt/ffmpeg/lib/pkgconfig:/opt/ffmpeg/lib64/pkgconfig"
|
||||
ARG PREFIX=/opt/ffmpeg
|
||||
ARG LD_LIBRARY_PATH="/opt/ffmpeg/lib:/opt/ffmpeg/lib64"
|
||||
|
||||
|
||||
RUN buildDeps="autoconf \
|
||||
automake \
|
||||
cmake \
|
||||
curl \
|
||||
bzip2 \
|
||||
libexpat1-dev \
|
||||
g++ \
|
||||
gcc \
|
||||
git \
|
||||
gperf \
|
||||
libtool \
|
||||
make \
|
||||
nasm \
|
||||
perl \
|
||||
pkg-config \
|
||||
python \
|
||||
libssl-dev \
|
||||
yasm \
|
||||
zlib1g-dev" && \
|
||||
apt-get -yqq update && \
|
||||
apt-get install -yq --no-install-recommends ${buildDeps}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/nv-codec-headers && \
|
||||
git clone https://github.com/FFmpeg/nv-codec-headers ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
git checkout n${NVIDIA_HEADERS_VERSION} && \
|
||||
make PREFIX="${PREFIX}" && \
|
||||
make install PREFIX="${PREFIX}" && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## opencore-amr https://sourceforge.net/projects/opencore-amr/
|
||||
RUN \
|
||||
DIR=/tmp/opencore-amr && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://versaweb.dl.sourceforge.net/project/opencore-amr/opencore-amr/opencore-amr-${OPENCOREAMR_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## x264 http://www.videolan.org/developers/x264.html
|
||||
RUN \
|
||||
DIR=/tmp/x264 && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://download.videolan.org/pub/videolan/x264/snapshots/x264-snapshot-${X264_VERSION}.tar.bz2 | \
|
||||
tar -jx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared --enable-pic --disable-cli && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### x265 http://x265.org/
|
||||
RUN \
|
||||
DIR=/tmp/x265 && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://download.videolan.org/pub/videolan/x265/x265_${X265_VERSION}.tar.gz | \
|
||||
tar -zx && \
|
||||
cd x265_${X265_VERSION}/build/linux && \
|
||||
sed -i "/-DEXTRA_LIB/ s/$/ -DCMAKE_INSTALL_PREFIX=\${PREFIX}/" multilib.sh && \
|
||||
sed -i "/^cmake/ s/$/ -DENABLE_CLI=OFF/" multilib.sh && \
|
||||
./multilib.sh && \
|
||||
make -C 8bit install && \
|
||||
rm -rf ${DIR}
|
||||
### libogg https://www.xiph.org/ogg/
|
||||
RUN \
|
||||
DIR=/tmp/ogg && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xiph.org/releases/ogg/libogg-${OGG_VERSION}.tar.gz && \
|
||||
echo ${OGG_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f libogg-${OGG_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libopus https://www.opus-codec.org/
|
||||
RUN \
|
||||
DIR=/tmp/opus && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://archive.mozilla.org/pub/opus/opus-${OPUS_VERSION}.tar.gz && \
|
||||
echo ${OPUS_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f opus-${OPUS_VERSION}.tar.gz && \
|
||||
autoreconf -fiv && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libvorbis https://xiph.org/vorbis/
|
||||
RUN \
|
||||
DIR=/tmp/vorbis && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xiph.org/releases/vorbis/libvorbis-${VORBIS_VERSION}.tar.gz && \
|
||||
echo ${VORBIS_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f libvorbis-${VORBIS_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --with-ogg="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libtheora http://www.theora.org/
|
||||
RUN \
|
||||
DIR=/tmp/theora && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xiph.org/releases/theora/libtheora-${THEORA_VERSION}.tar.gz && \
|
||||
echo ${THEORA_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f libtheora-${THEORA_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --with-ogg="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libvpx https://www.webmproject.org/code/
|
||||
RUN \
|
||||
DIR=/tmp/vpx && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://codeload.github.com/webmproject/libvpx/tar.gz/v${VPX_VERSION} | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-vp8 --enable-vp9 --enable-vp9-highbitdepth --enable-pic --enable-shared \
|
||||
--disable-debug --disable-examples --disable-docs --disable-install-bins && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libwebp https://developers.google.com/speed/webp/
|
||||
RUN \
|
||||
DIR=/tmp/vebp && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-${WEBP_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libmp3lame http://lame.sourceforge.net/
|
||||
RUN \
|
||||
DIR=/tmp/lame && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://versaweb.dl.sourceforge.net/project/lame/lame/$(echo ${LAME_VERSION} | sed -e 's/[^0-9]*\([0-9]*\)[.]\([0-9]*\)[.]\([0-9]*\)\([0-9A-Za-z-]*\)/\1.\2/')/lame-${LAME_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --bindir="${PREFIX}/bin" --enable-shared --enable-nasm --disable-frontend && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### xvid https://www.xvid.com/
|
||||
RUN \
|
||||
DIR=/tmp/xvid && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xvid.org/downloads/xvidcore-${XVID_VERSION}.tar.gz && \
|
||||
echo ${XVID_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx -f xvidcore-${XVID_VERSION}.tar.gz && \
|
||||
cd xvidcore/build/generic && \
|
||||
./configure --prefix="${PREFIX}" --bindir="${PREFIX}/bin" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### fdk-aac https://github.com/mstorsjo/fdk-aac
|
||||
RUN \
|
||||
DIR=/tmp/fdk-aac && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://github.com/mstorsjo/fdk-aac/archive/v${FDKAAC_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
autoreconf -fiv && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared --datadir="${DIR}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## openjpeg https://github.com/uclouvain/openjpeg
|
||||
RUN \
|
||||
DIR=/tmp/openjpeg && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
cmake -DBUILD_THIRDPARTY:BOOL=ON -DCMAKE_INSTALL_PREFIX="${PREFIX}" . && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## freetype https://www.freetype.org/
|
||||
RUN \
|
||||
DIR=/tmp/freetype && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://download.savannah.gnu.org/releases/freetype/freetype-${FREETYPE_VERSION}.tar.gz && \
|
||||
echo ${FREETYPE_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f freetype-${FREETYPE_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## libvstab https://github.com/georgmartius/vid.stab
|
||||
RUN \
|
||||
DIR=/tmp/vid.stab && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/georgmartius/vid.stab/archive/v${LIBVIDSTAB_VERSION}.tar.gz && \
|
||||
echo ${LIBVIDSTAB_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f v${LIBVIDSTAB_VERSION}.tar.gz && \
|
||||
cmake -DCMAKE_INSTALL_PREFIX="${PREFIX}" . && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## fridibi https://www.fribidi.org/
|
||||
RUN \
|
||||
DIR=/tmp/fribidi && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/fribidi/fribidi/archive/${FRIBIDI_VERSION}.tar.gz && \
|
||||
echo ${FRIBIDI_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f ${FRIBIDI_VERSION}.tar.gz && \
|
||||
sed -i 's/^SUBDIRS =.*/SUBDIRS=gen.tab charset lib bin/' Makefile.am && \
|
||||
./bootstrap --no-config --auto && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make -j1 && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## fontconfig https://www.freedesktop.org/wiki/Software/fontconfig/
|
||||
RUN \
|
||||
DIR=/tmp/fontconfig && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.freedesktop.org/software/fontconfig/release/fontconfig-${FONTCONFIG_VERSION}.tar.bz2 && \
|
||||
tar -jx --strip-components=1 -f fontconfig-${FONTCONFIG_VERSION}.tar.bz2 && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## libass https://github.com/libass/libass
|
||||
RUN \
|
||||
DIR=/tmp/libass && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/libass/libass/archive/${LIBASS_VERSION}.tar.gz && \
|
||||
echo ${LIBASS_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f ${LIBASS_VERSION}.tar.gz && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## kvazaar https://github.com/ultravideo/kvazaar
|
||||
RUN \
|
||||
DIR=/tmp/kvazaar && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/ultravideo/kvazaar/archive/v${KVAZAAR_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f v${KVAZAAR_VERSION}.tar.gz && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/aom && \
|
||||
git clone --branch ${AOM_VERSION} --depth 1 https://aomedia.googlesource.com/aom ${DIR} ; \
|
||||
cd ${DIR} ; \
|
||||
rm -rf CMakeCache.txt CMakeFiles ; \
|
||||
mkdir -p ./aom_build ; \
|
||||
cd ./aom_build ; \
|
||||
cmake -DCMAKE_INSTALL_PREFIX="${PREFIX}" -DBUILD_SHARED_LIBS=1 ..; \
|
||||
make ; \
|
||||
make install ; \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libxcb (and supporting libraries) for screen capture https://xcb.freedesktop.org/
|
||||
RUN \
|
||||
DIR=/tmp/xorg-macros && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.x.org/archive//individual/util/util-macros-${XORG_MACROS_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f util-macros-${XORG_MACROS_VERSION}.tar.gz && \
|
||||
./configure --srcdir=${DIR} --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/xproto && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.x.org/archive/individual/proto/xproto-${XPROTO_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f xproto-${XPROTO_VERSION}.tar.gz && \
|
||||
./configure --srcdir=${DIR} --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libXau && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.x.org/archive/individual/lib/libXau-${XAU_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f libXau-${XAU_VERSION}.tar.gz && \
|
||||
./configure --srcdir=${DIR} --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libpthread-stubs && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://xcb.freedesktop.org/dist/libpthread-stubs-${LIBPTHREAD_STUBS_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f libpthread-stubs-${LIBPTHREAD_STUBS_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libxcb-proto && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://xcb.freedesktop.org/dist/xcb-proto-${XCBPROTO_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f xcb-proto-${XCBPROTO_VERSION}.tar.gz && \
|
||||
ACLOCAL_PATH="${PREFIX}/share/aclocal" ./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libxcb && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://xcb.freedesktop.org/dist/libxcb-${LIBXCB_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f libxcb-${LIBXCB_VERSION}.tar.gz && \
|
||||
ACLOCAL_PATH="${PREFIX}/share/aclocal" ./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libxml2 - for libbluray
|
||||
RUN \
|
||||
DIR=/tmp/libxml2 && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://gitlab.gnome.org/GNOME/libxml2/-/archive/v${LIBXML2_VERSION}/libxml2-v${LIBXML2_VERSION}.tar.gz && \
|
||||
echo ${LIBXML2_SHA256SUM} | sha256sum --check && \
|
||||
tar -xz --strip-components=1 -f libxml2-v${LIBXML2_VERSION}.tar.gz && \
|
||||
./autogen.sh --prefix="${PREFIX}" --with-ftp=no --with-http=no --with-python=no && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libbluray - Requires libxml, freetype, and fontconfig
|
||||
RUN \
|
||||
DIR=/tmp/libbluray && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://download.videolan.org/pub/videolan/libbluray/${LIBBLURAY_VERSION}/libbluray-${LIBBLURAY_VERSION}.tar.bz2 && \
|
||||
echo ${LIBBLURAY_SHA256SUM} | sha256sum --check && \
|
||||
tar -jx --strip-components=1 -f libbluray-${LIBBLURAY_VERSION}.tar.bz2 && \
|
||||
./configure --prefix="${PREFIX}" --disable-examples --disable-bdjava-jar --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libzmq https://github.com/zeromq/libzmq/
|
||||
RUN \
|
||||
DIR=/tmp/libzmq && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/zeromq/libzmq/archive/v${LIBZMQ_VERSION}.tar.gz && \
|
||||
echo ${LIBZMQ_SHA256SUM} | sha256sum --check && \
|
||||
tar -xz --strip-components=1 -f v${LIBZMQ_VERSION}.tar.gz && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make check && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libsrt https://github.com/Haivision/srt
|
||||
RUN \
|
||||
DIR=/tmp/srt && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/Haivision/srt/archive/v${LIBSRT_VERSION}.tar.gz && \
|
||||
tar -xz --strip-components=1 -f v${LIBSRT_VERSION}.tar.gz && \
|
||||
cmake -DCMAKE_INSTALL_PREFIX="${PREFIX}" . && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libpng
|
||||
RUN \
|
||||
DIR=/tmp/png && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
git clone https://git.code.sf.net/p/libpng/code ${DIR} -b v${LIBPNG_VERSION} --depth 1 && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make check && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libaribb24
|
||||
RUN \
|
||||
DIR=/tmp/b24 && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/nkoriyama/aribb24/archive/v${LIBARIBB24_VERSION}.tar.gz && \
|
||||
echo ${LIBARIBB24_SHA256SUM} | sha256sum --check && \
|
||||
tar -xz --strip-components=1 -f v${LIBARIBB24_VERSION}.tar.gz && \
|
||||
autoreconf -fiv && \
|
||||
./configure CFLAGS="-I${PREFIX}/include -fPIC" --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## ffmpeg https://ffmpeg.org/
|
||||
RUN \
|
||||
DIR=/tmp/ffmpeg && mkdir -p ${DIR} && cd ${DIR} && \
|
||||
curl -sLO https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2 && \
|
||||
tar -jx --strip-components=1 -f ffmpeg-${FFMPEG_VERSION}.tar.bz2
|
||||
|
||||
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/ffmpeg && mkdir -p ${DIR} && cd ${DIR} && \
|
||||
./configure \
|
||||
--disable-debug \
|
||||
--disable-doc \
|
||||
--disable-ffplay \
|
||||
--enable-shared \
|
||||
--enable-avresample \
|
||||
--enable-libopencore-amrnb \
|
||||
--enable-libopencore-amrwb \
|
||||
--enable-gpl \
|
||||
--enable-libass \
|
||||
--enable-fontconfig \
|
||||
--enable-libfreetype \
|
||||
--enable-libvidstab \
|
||||
--enable-libmp3lame \
|
||||
--enable-libopus \
|
||||
--enable-libtheora \
|
||||
--enable-libvorbis \
|
||||
--enable-libvpx \
|
||||
--enable-libwebp \
|
||||
--enable-libxcb \
|
||||
--enable-libx265 \
|
||||
--enable-libxvid \
|
||||
--enable-libx264 \
|
||||
--enable-nonfree \
|
||||
--enable-openssl \
|
||||
--enable-libfdk_aac \
|
||||
--enable-postproc \
|
||||
--enable-small \
|
||||
--enable-version3 \
|
||||
--enable-libbluray \
|
||||
--enable-libzmq \
|
||||
--extra-libs=-ldl \
|
||||
--prefix="${PREFIX}" \
|
||||
--enable-libopenjpeg \
|
||||
--enable-libkvazaar \
|
||||
--enable-libaom \
|
||||
--extra-libs=-lpthread \
|
||||
--enable-libsrt \
|
||||
--enable-libaribb24 \
|
||||
--enable-nvenc \
|
||||
--enable-cuda \
|
||||
--enable-cuvid \
|
||||
--enable-libnpp \
|
||||
--extra-cflags="-I${PREFIX}/include -I${PREFIX}/include/ffnvcodec -I/usr/local/cuda/include/" \
|
||||
--extra-ldflags="-L${PREFIX}/lib -L/usr/local/cuda/lib64 -L/usr/local/cuda/lib32/" && \
|
||||
make && \
|
||||
make install && \
|
||||
make tools/zmqsend && cp tools/zmqsend ${PREFIX}/bin/ && \
|
||||
make distclean && \
|
||||
hash -r && \
|
||||
cd tools && \
|
||||
make qt-faststart && cp qt-faststart ${PREFIX}/bin/
|
||||
|
||||
## cleanup
|
||||
RUN \
|
||||
LD_LIBRARY_PATH="${PREFIX}/lib:${PREFIX}/lib64:${LD_LIBRARY_PATH}" ldd ${PREFIX}/bin/ffmpeg | grep opt/ffmpeg | cut -d ' ' -f 3 | xargs -i cp {} /usr/local/lib/ && \
|
||||
for lib in /usr/local/lib/*.so.*; do ln -s "${lib##*/}" "${lib%%.so.*}".so; done && \
|
||||
cp ${PREFIX}/bin/* /usr/local/bin/ && \
|
||||
cp -r ${PREFIX}/share/* /usr/local/share/ && \
|
||||
LD_LIBRARY_PATH=/usr/local/lib ffmpeg -buildconf && \
|
||||
cp -r ${PREFIX}/include/libav* ${PREFIX}/include/libpostproc ${PREFIX}/include/libsw* /usr/local/include && \
|
||||
mkdir -p /usr/local/lib/pkgconfig && \
|
||||
for pc in ${PREFIX}/lib/pkgconfig/libav*.pc ${PREFIX}/lib/pkgconfig/libpostproc.pc ${PREFIX}/lib/pkgconfig/libsw*.pc; do \
|
||||
sed "s:${PREFIX}:/usr/local:g; s:/lib64:/lib:g" <"$pc" >/usr/local/lib/pkgconfig/"${pc##*/}"; \
|
||||
done
|
||||
|
||||
|
||||
|
||||
FROM runtime-base AS release
|
||||
MAINTAINER Julien Rottenberg <julien@rottenberg.info>
|
||||
|
||||
ENV LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64
|
||||
|
||||
CMD ["--help"]
|
||||
ENTRYPOINT ["ffmpeg"]
|
||||
|
||||
# copy only needed files, without copying nvidia dev files
|
||||
COPY --from=build /usr/local/bin /usr/local/bin/
|
||||
COPY --from=build /usr/local/share /usr/local/share/
|
||||
COPY --from=build /usr/local/lib /usr/local/lib/
|
||||
COPY --from=build /usr/local/include /usr/local/include/
|
||||
|
||||
# Let's make sure the app built correctly
|
||||
# Convenient to verify on https://hub.docker.com/r/jrottenberg/ffmpeg/builds/ console output
|
@@ -1,549 +0,0 @@
|
||||
# inspired by:
|
||||
# https://github.com/collelog/ffmpeg/blob/master/4.3.1-alpine-rpi4-arm64v8.Dockerfile
|
||||
# https://github.com/mmastrac/ffmpeg-omx-rpi-docker/blob/master/Dockerfile
|
||||
# https://github.com/jrottenberg/ffmpeg/pull/158/files
|
||||
# https://github.com/jrottenberg/ffmpeg/pull/239
|
||||
FROM ubuntu:20.04 AS base
|
||||
|
||||
WORKDIR /tmp/workdir
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get -yqq update && \
|
||||
apt-get install -yq --no-install-recommends ca-certificates expat libgomp1 && \
|
||||
apt-get autoremove -y && \
|
||||
apt-get clean -y
|
||||
|
||||
FROM base as build
|
||||
|
||||
ENV FFMPEG_VERSION=4.3.1 \
|
||||
AOM_VERSION=v1.0.0 \
|
||||
FDKAAC_VERSION=0.1.5 \
|
||||
FONTCONFIG_VERSION=2.12.4 \
|
||||
FREETYPE_VERSION=2.5.5 \
|
||||
FRIBIDI_VERSION=0.19.7 \
|
||||
KVAZAAR_VERSION=1.2.0 \
|
||||
LAME_VERSION=3.100 \
|
||||
LIBASS_VERSION=0.13.7 \
|
||||
LIBPTHREAD_STUBS_VERSION=0.4 \
|
||||
LIBVIDSTAB_VERSION=1.1.0 \
|
||||
LIBXCB_VERSION=1.13.1 \
|
||||
XCBPROTO_VERSION=1.13 \
|
||||
OGG_VERSION=1.3.2 \
|
||||
OPENCOREAMR_VERSION=0.1.5 \
|
||||
OPUS_VERSION=1.2 \
|
||||
OPENJPEG_VERSION=2.1.2 \
|
||||
THEORA_VERSION=1.1.1 \
|
||||
VORBIS_VERSION=1.3.5 \
|
||||
VPX_VERSION=1.8.0 \
|
||||
WEBP_VERSION=1.0.2 \
|
||||
X264_VERSION=20170226-2245-stable \
|
||||
X265_VERSION=3.1.1 \
|
||||
XAU_VERSION=1.0.9 \
|
||||
XORG_MACROS_VERSION=1.19.2 \
|
||||
XPROTO_VERSION=7.0.31 \
|
||||
XVID_VERSION=1.3.4 \
|
||||
LIBXML2_VERSION=2.9.10 \
|
||||
LIBBLURAY_VERSION=1.1.2 \
|
||||
LIBZMQ_VERSION=4.3.3 \
|
||||
SRC=/usr/local
|
||||
|
||||
ARG FREETYPE_SHA256SUM="5d03dd76c2171a7601e9ce10551d52d4471cf92cd205948e60289251daddffa8 freetype-2.5.5.tar.gz"
|
||||
ARG FRIBIDI_SHA256SUM="3fc96fa9473bd31dcb5500bdf1aa78b337ba13eb8c301e7c28923fea982453a8 0.19.7.tar.gz"
|
||||
ARG LIBASS_SHA256SUM="8fadf294bf701300d4605e6f1d92929304187fca4b8d8a47889315526adbafd7 0.13.7.tar.gz"
|
||||
ARG LIBVIDSTAB_SHA256SUM="14d2a053e56edad4f397be0cb3ef8eb1ec3150404ce99a426c4eb641861dc0bb v1.1.0.tar.gz"
|
||||
ARG OGG_SHA256SUM="e19ee34711d7af328cb26287f4137e70630e7261b17cbe3cd41011d73a654692 libogg-1.3.2.tar.gz"
|
||||
ARG OPUS_SHA256SUM="77db45a87b51578fbc49555ef1b10926179861d854eb2613207dc79d9ec0a9a9 opus-1.2.tar.gz"
|
||||
ARG THEORA_SHA256SUM="40952956c47811928d1e7922cda3bc1f427eb75680c3c37249c91e949054916b libtheora-1.1.1.tar.gz"
|
||||
ARG VORBIS_SHA256SUM="6efbcecdd3e5dfbf090341b485da9d176eb250d893e3eb378c428a2db38301ce libvorbis-1.3.5.tar.gz"
|
||||
ARG XVID_SHA256SUM="4e9fd62728885855bc5007fe1be58df42e5e274497591fec37249e1052ae316f xvidcore-1.3.4.tar.gz"
|
||||
ARG LIBXML2_SHA256SUM="f07dab13bf42d2b8db80620cce7419b3b87827cc937c8bb20fe13b8571ee9501 libxml2-v2.9.10.tar.gz"
|
||||
ARG LIBBLURAY_SHA256SUM="a3dd452239b100dc9da0d01b30e1692693e2a332a7d29917bf84bb10ea7c0b42 libbluray-1.1.2.tar.bz2"
|
||||
|
||||
|
||||
ARG LD_LIBRARY_PATH=/opt/ffmpeg/lib
|
||||
ARG MAKEFLAGS="-j2"
|
||||
ARG PKG_CONFIG_PATH="/opt/ffmpeg/share/pkgconfig:/opt/ffmpeg/lib/pkgconfig:/opt/ffmpeg/lib64/pkgconfig:/opt/vc/lib/pkgconfig"
|
||||
ARG PREFIX=/opt/ffmpeg
|
||||
ARG LD_LIBRARY_PATH="/opt/ffmpeg/lib:/opt/ffmpeg/lib64:/usr/lib64:/usr/lib:/lib64:/lib:/opt/vc/lib"
|
||||
|
||||
|
||||
RUN buildDeps="autoconf \
|
||||
automake \
|
||||
cmake \
|
||||
curl \
|
||||
bzip2 \
|
||||
libexpat1-dev \
|
||||
g++ \
|
||||
gcc \
|
||||
git \
|
||||
gperf \
|
||||
libtool \
|
||||
make \
|
||||
nasm \
|
||||
perl \
|
||||
pkg-config \
|
||||
python \
|
||||
sudo \
|
||||
libssl-dev \
|
||||
yasm \
|
||||
linux-headers-raspi2 \
|
||||
libomxil-bellagio-dev \
|
||||
libx265-dev \
|
||||
libaom-dev \
|
||||
zlib1g-dev" && \
|
||||
apt-get -yqq update && \
|
||||
apt-get install -yq --no-install-recommends ${buildDeps}
|
||||
## opencore-amr https://sourceforge.net/projects/opencore-amr/
|
||||
RUN \
|
||||
DIR=/tmp/opencore-amr && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://versaweb.dl.sourceforge.net/project/opencore-amr/opencore-amr/opencore-amr-${OPENCOREAMR_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
## x264 http://www.videolan.org/developers/x264.html
|
||||
RUN \
|
||||
DIR=/tmp/x264 && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://download.videolan.org/pub/videolan/x264/snapshots/x264-snapshot-${X264_VERSION}.tar.bz2 | \
|
||||
tar -jx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared --enable-pic --disable-cli && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
# ### x265 http://x265.org/
|
||||
# RUN \
|
||||
# DIR=/tmp/x265 && \
|
||||
# mkdir -p ${DIR} && \
|
||||
# cd ${DIR} && \
|
||||
# curl -sL https://download.videolan.org/pub/videolan/x265/x265_${X265_VERSION}.tar.gz | \
|
||||
# tar -zx && \
|
||||
# cd x265_${X265_VERSION}/build/linux && \
|
||||
# sed -i "/-DEXTRA_LIB/ s/$/ -DCMAKE_INSTALL_PREFIX=\${PREFIX}/" multilib.sh && \
|
||||
# sed -i "/^cmake/ s/$/ -DENABLE_CLI=OFF/" multilib.sh && \
|
||||
# # export CXXFLAGS="${CXXFLAGS} -fPIC" && \
|
||||
# ./multilib.sh && \
|
||||
# make -C 8bit install && \
|
||||
# rm -rf ${DIR}
|
||||
### libogg https://www.xiph.org/ogg/
|
||||
RUN \
|
||||
DIR=/tmp/ogg && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xiph.org/releases/ogg/libogg-${OGG_VERSION}.tar.gz && \
|
||||
echo ${OGG_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f libogg-${OGG_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### libopus https://www.opus-codec.org/
|
||||
RUN \
|
||||
DIR=/tmp/opus && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://archive.mozilla.org/pub/opus/opus-${OPUS_VERSION}.tar.gz && \
|
||||
echo ${OPUS_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f opus-${OPUS_VERSION}.tar.gz && \
|
||||
autoreconf -fiv && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### libvorbis https://xiph.org/vorbis/
|
||||
RUN \
|
||||
DIR=/tmp/vorbis && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xiph.org/releases/vorbis/libvorbis-${VORBIS_VERSION}.tar.gz && \
|
||||
echo ${VORBIS_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f libvorbis-${VORBIS_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --with-ogg="${PREFIX}" --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### libtheora http://www.theora.org/
|
||||
RUN \
|
||||
DIR=/tmp/theora && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xiph.org/releases/theora/libtheora-${THEORA_VERSION}.tar.gz && \
|
||||
echo ${THEORA_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f libtheora-${THEORA_VERSION}.tar.gz && \
|
||||
curl -sL 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' -o config.guess && \
|
||||
curl -sL 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' -o config.sub && \
|
||||
./configure --prefix="${PREFIX}" --with-ogg="${PREFIX}" --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### libvpx https://www.webmproject.org/code/
|
||||
RUN \
|
||||
DIR=/tmp/vpx && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://codeload.github.com/webmproject/libvpx/tar.gz/v${VPX_VERSION} | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-vp8 --enable-vp9 --enable-vp9-highbitdepth --enable-pic --enable-shared \
|
||||
--disable-debug --disable-examples --disable-docs --disable-install-bins && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### libwebp https://developers.google.com/speed/webp/
|
||||
RUN \
|
||||
DIR=/tmp/vebp && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-${WEBP_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### libmp3lame http://lame.sourceforge.net/
|
||||
RUN \
|
||||
DIR=/tmp/lame && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://versaweb.dl.sourceforge.net/project/lame/lame/$(echo ${LAME_VERSION} | sed -e 's/[^0-9]*\([0-9]*\)[.]\([0-9]*\)[.]\([0-9]*\)\([0-9A-Za-z-]*\)/\1.\2/')/lame-${LAME_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --bindir="${PREFIX}/bin" --enable-shared --enable-nasm --disable-frontend && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### xvid https://www.xvid.com/
|
||||
RUN \
|
||||
DIR=/tmp/xvid && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xvid.org/downloads/xvidcore-${XVID_VERSION}.tar.gz && \
|
||||
echo ${XVID_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx -f xvidcore-${XVID_VERSION}.tar.gz && \
|
||||
cd xvidcore/build/generic && \
|
||||
./configure --prefix="${PREFIX}" --bindir="${PREFIX}/bin" && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
### fdk-aac https://github.com/mstorsjo/fdk-aac
|
||||
RUN \
|
||||
DIR=/tmp/fdk-aac && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://github.com/mstorsjo/fdk-aac/archive/v${FDKAAC_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
autoreconf -fiv && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared --datadir="${DIR}" && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
## openjpeg https://github.com/uclouvain/openjpeg
|
||||
RUN \
|
||||
DIR=/tmp/openjpeg && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
export CFLAGS="${CFLAGS} -DPNG_ARM_NEON_OPT=0" && \
|
||||
cmake -DBUILD_THIRDPARTY:BOOL=ON -DCMAKE_INSTALL_PREFIX="${PREFIX}" . && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
## freetype https://www.freetype.org/
|
||||
RUN \
|
||||
DIR=/tmp/freetype && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://download.savannah.gnu.org/releases/freetype/freetype-${FREETYPE_VERSION}.tar.gz && \
|
||||
echo ${FREETYPE_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f freetype-${FREETYPE_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
## libvstab https://github.com/georgmartius/vid.stab
|
||||
RUN \
|
||||
DIR=/tmp/vid.stab && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/georgmartius/vid.stab/archive/v${LIBVIDSTAB_VERSION}.tar.gz && \
|
||||
echo ${LIBVIDSTAB_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f v${LIBVIDSTAB_VERSION}.tar.gz && \
|
||||
cmake -DCMAKE_INSTALL_PREFIX="${PREFIX}" . && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
## fridibi https://www.fribidi.org/
|
||||
RUN \
|
||||
DIR=/tmp/fribidi && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/fribidi/fribidi/archive/${FRIBIDI_VERSION}.tar.gz && \
|
||||
echo ${FRIBIDI_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f ${FRIBIDI_VERSION}.tar.gz && \
|
||||
sed -i 's/^SUBDIRS =.*/SUBDIRS=gen.tab charset lib bin/' Makefile.am && \
|
||||
./bootstrap --no-config --auto && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make -j1 && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
## fontconfig https://www.freedesktop.org/wiki/Software/fontconfig/
|
||||
RUN \
|
||||
DIR=/tmp/fontconfig && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.freedesktop.org/software/fontconfig/release/fontconfig-${FONTCONFIG_VERSION}.tar.bz2 && \
|
||||
tar -jx --strip-components=1 -f fontconfig-${FONTCONFIG_VERSION}.tar.bz2 && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
## libass https://github.com/libass/libass
|
||||
RUN \
|
||||
DIR=/tmp/libass && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/libass/libass/archive/${LIBASS_VERSION}.tar.gz && \
|
||||
echo ${LIBASS_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f ${LIBASS_VERSION}.tar.gz && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
## kvazaar https://github.com/ultravideo/kvazaar
|
||||
RUN \
|
||||
DIR=/tmp/kvazaar && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/ultravideo/kvazaar/archive/v${KVAZAAR_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f v${KVAZAAR_VERSION}.tar.gz && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
# RUN \
|
||||
# DIR=/tmp/aom && \
|
||||
# git clone --branch ${AOM_VERSION} --depth 1 https://aomedia.googlesource.com/aom ${DIR} ; \
|
||||
# cd ${DIR} ; \
|
||||
# rm -rf CMakeCache.txt CMakeFiles ; \
|
||||
# mkdir -p ./aom_build ; \
|
||||
# cd ./aom_build ; \
|
||||
# cmake -DCMAKE_INSTALL_PREFIX="${PREFIX}" -DBUILD_SHARED_LIBS=1 ..; \
|
||||
# make ; \
|
||||
# make install ; \
|
||||
# rm -rf ${DIR}
|
||||
|
||||
## libxcb (and supporting libraries) for screen capture https://xcb.freedesktop.org/
|
||||
RUN \
|
||||
DIR=/tmp/xorg-macros && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.x.org/archive//individual/util/util-macros-${XORG_MACROS_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f util-macros-${XORG_MACROS_VERSION}.tar.gz && \
|
||||
./configure --srcdir=${DIR} --prefix="${PREFIX}" && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/xproto && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.x.org/archive/individual/proto/xproto-${XPROTO_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f xproto-${XPROTO_VERSION}.tar.gz && \
|
||||
curl -sL 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' -o config.guess && \
|
||||
curl -sL 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' -o config.sub && \
|
||||
./configure --srcdir=${DIR} --prefix="${PREFIX}" && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libXau && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.x.org/archive/individual/lib/libXau-${XAU_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f libXau-${XAU_VERSION}.tar.gz && \
|
||||
./configure --srcdir=${DIR} --prefix="${PREFIX}" && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libpthread-stubs && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://xcb.freedesktop.org/dist/libpthread-stubs-${LIBPTHREAD_STUBS_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f libpthread-stubs-${LIBPTHREAD_STUBS_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libxcb-proto && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://xcb.freedesktop.org/dist/xcb-proto-${XCBPROTO_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f xcb-proto-${XCBPROTO_VERSION}.tar.gz && \
|
||||
ACLOCAL_PATH="${PREFIX}/share/aclocal" ./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libxcb && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://xcb.freedesktop.org/dist/libxcb-${LIBXCB_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f libxcb-${LIBXCB_VERSION}.tar.gz && \
|
||||
ACLOCAL_PATH="${PREFIX}/share/aclocal" ./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libxml2 - for libbluray
|
||||
RUN \
|
||||
DIR=/tmp/libxml2 && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://gitlab.gnome.org/GNOME/libxml2/-/archive/v${LIBXML2_VERSION}/libxml2-v${LIBXML2_VERSION}.tar.gz && \
|
||||
echo ${LIBXML2_SHA256SUM} | sha256sum --check && \
|
||||
tar -xz --strip-components=1 -f libxml2-v${LIBXML2_VERSION}.tar.gz && \
|
||||
./autogen.sh --prefix="${PREFIX}" --with-ftp=no --with-http=no --with-python=no && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libbluray - Requires libxml, freetype, and fontconfig
|
||||
RUN \
|
||||
DIR=/tmp/libbluray && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://download.videolan.org/pub/videolan/libbluray/${LIBBLURAY_VERSION}/libbluray-${LIBBLURAY_VERSION}.tar.bz2 && \
|
||||
echo ${LIBBLURAY_SHA256SUM} | sha256sum --check && \
|
||||
tar -jx --strip-components=1 -f libbluray-${LIBBLURAY_VERSION}.tar.bz2 && \
|
||||
./configure --prefix="${PREFIX}" --disable-examples --disable-bdjava-jar --disable-static --enable-shared && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libzmq https://github.com/zeromq/libzmq/
|
||||
RUN \
|
||||
DIR=/tmp/libzmq && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/zeromq/libzmq/archive/v${LIBZMQ_VERSION}.tar.gz && \
|
||||
tar -xz --strip-components=1 -f v${LIBZMQ_VERSION}.tar.gz && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make -j $(nproc) && \
|
||||
# make check && \
|
||||
make -j $(nproc) install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## userland https://github.com/raspberrypi/userland
|
||||
RUN \
|
||||
DIR=/tmp/userland && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
git clone --depth 1 https://github.com/raspberrypi/userland.git . && \
|
||||
./buildme && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## ffmpeg https://ffmpeg.org/
|
||||
RUN \
|
||||
DIR=/tmp/ffmpeg && mkdir -p ${DIR} && cd ${DIR} && \
|
||||
curl -sLO https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2 && \
|
||||
tar -jx --strip-components=1 -f ffmpeg-${FFMPEG_VERSION}.tar.bz2
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/ffmpeg && mkdir -p ${DIR} && cd ${DIR} && \
|
||||
./configure \
|
||||
--disable-debug \
|
||||
--disable-doc \
|
||||
--disable-ffplay \
|
||||
--enable-shared \
|
||||
--enable-avresample \
|
||||
--enable-libopencore-amrnb \
|
||||
--enable-libopencore-amrwb \
|
||||
--enable-gpl \
|
||||
--enable-libass \
|
||||
--enable-fontconfig \
|
||||
--enable-libfreetype \
|
||||
--enable-libvidstab \
|
||||
--enable-libmp3lame \
|
||||
--enable-libopus \
|
||||
--enable-libtheora \
|
||||
--enable-libvorbis \
|
||||
--enable-libvpx \
|
||||
--enable-libwebp \
|
||||
--enable-libxcb \
|
||||
--enable-libx265 \
|
||||
--enable-libxvid \
|
||||
--enable-libx264 \
|
||||
--enable-nonfree \
|
||||
--enable-openssl \
|
||||
--enable-libfdk_aac \
|
||||
--enable-postproc \
|
||||
--enable-small \
|
||||
--enable-version3 \
|
||||
--enable-libbluray \
|
||||
--enable-libzmq \
|
||||
--extra-libs=-ldl \
|
||||
--prefix="${PREFIX}" \
|
||||
--enable-libopenjpeg \
|
||||
--enable-libkvazaar \
|
||||
--enable-libaom \
|
||||
--extra-libs=-lpthread \
|
||||
--enable-omx \
|
||||
--enable-omx-rpi \
|
||||
--enable-mmal \
|
||||
--enable-v4l2_m2m \
|
||||
--enable-neon \
|
||||
--extra-cflags="-I${PREFIX}/include" \
|
||||
--extra-ldflags="-L${PREFIX}/lib" && \
|
||||
make -j $(nproc) && \
|
||||
make -j $(nproc) install && \
|
||||
make tools/zmqsend && cp tools/zmqsend ${PREFIX}/bin/ && \
|
||||
make distclean && \
|
||||
hash -r && \
|
||||
cd tools && \
|
||||
make qt-faststart && cp qt-faststart ${PREFIX}/bin/
|
||||
|
||||
## cleanup
|
||||
RUN \
|
||||
ldd ${PREFIX}/bin/ffmpeg | grep opt/ffmpeg | cut -d ' ' -f 3 | xargs -i cp {} /usr/local/lib/ && \
|
||||
# copy userland lib too
|
||||
ldd ${PREFIX}/bin/ffmpeg | grep opt/vc | cut -d ' ' -f 3 | xargs -i cp {} /usr/local/lib/ && \
|
||||
for lib in /usr/local/lib/*.so.*; do ln -s "${lib##*/}" "${lib%%.so.*}".so; done && \
|
||||
cp ${PREFIX}/bin/* /usr/local/bin/ && \
|
||||
cp -r ${PREFIX}/share/ffmpeg /usr/local/share/ && \
|
||||
LD_LIBRARY_PATH=/usr/local/lib ffmpeg -buildconf && \
|
||||
cp -r ${PREFIX}/include/libav* ${PREFIX}/include/libpostproc ${PREFIX}/include/libsw* /usr/local/include && \
|
||||
mkdir -p /usr/local/lib/pkgconfig && \
|
||||
for pc in ${PREFIX}/lib/pkgconfig/libav*.pc ${PREFIX}/lib/pkgconfig/libpostproc.pc ${PREFIX}/lib/pkgconfig/libsw*.pc; do \
|
||||
sed "s:${PREFIX}:/usr/local:g" <"$pc" >/usr/local/lib/pkgconfig/"${pc##*/}"; \
|
||||
done
|
||||
|
||||
FROM base AS release
|
||||
|
||||
ENV LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64:/lib:/lib64
|
||||
|
||||
RUN \
|
||||
apt-get -yqq update && \
|
||||
apt-get install -yq --no-install-recommends libx265-dev libaom-dev && \
|
||||
apt-get autoremove -y && \
|
||||
apt-get clean -y
|
||||
|
||||
CMD ["--help"]
|
||||
ENTRYPOINT ["ffmpeg"]
|
||||
|
||||
COPY --from=build /usr/local /usr/local/
|
@@ -1,39 +0,0 @@
|
||||
FROM ubuntu:20.04 as build
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get -qq update \
|
||||
&& apt-get -qq install -y \
|
||||
python3 \
|
||||
python3-dev \
|
||||
wget \
|
||||
# opencv dependencies
|
||||
build-essential cmake git pkg-config libgtk-3-dev \
|
||||
libavcodec-dev libavformat-dev libswscale-dev libv4l-dev \
|
||||
libxvidcore-dev libx264-dev libjpeg-dev libpng-dev libtiff-dev \
|
||||
gfortran openexr libatlas-base-dev libssl-dev\
|
||||
libtbb2 libtbb-dev libdc1394-22-dev libopenexr-dev \
|
||||
libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev \
|
||||
# scipy dependencies
|
||||
gcc gfortran libopenblas-dev liblapack-dev cython
|
||||
|
||||
RUN wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
|
||||
&& python3 get-pip.py
|
||||
|
||||
RUN pip3 install scikit-build
|
||||
|
||||
RUN pip3 wheel --wheel-dir=/wheels \
|
||||
opencv-python-headless \
|
||||
numpy \
|
||||
imutils \
|
||||
scipy \
|
||||
psutil \
|
||||
Flask \
|
||||
paho-mqtt \
|
||||
PyYAML \
|
||||
matplotlib \
|
||||
click
|
||||
|
||||
FROM scratch
|
||||
|
||||
COPY --from=build /wheels /wheels
|
@@ -1,49 +0,0 @@
|
||||
FROM ubuntu:20.04 as build
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get -qq update \
|
||||
&& apt-get -qq install -y \
|
||||
python3 \
|
||||
python3-dev \
|
||||
wget \
|
||||
# opencv dependencies
|
||||
build-essential cmake git pkg-config libgtk-3-dev \
|
||||
libavcodec-dev libavformat-dev libswscale-dev libv4l-dev \
|
||||
libxvidcore-dev libx264-dev libjpeg-dev libpng-dev libtiff-dev \
|
||||
gfortran openexr libatlas-base-dev libssl-dev\
|
||||
libtbb2 libtbb-dev libdc1394-22-dev libopenexr-dev \
|
||||
libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev \
|
||||
# scipy dependencies
|
||||
gcc gfortran libopenblas-dev liblapack-dev cython
|
||||
|
||||
RUN wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
|
||||
&& python3 get-pip.py
|
||||
|
||||
# need to build cmake from source because binary distribution is broken for arm64
|
||||
# https://github.com/scikit-build/cmake-python-distributions/issues/115
|
||||
# https://github.com/skvark/opencv-python/issues/366
|
||||
# https://github.com/scikit-build/cmake-python-distributions/issues/96#issuecomment-663062358
|
||||
RUN pip3 install scikit-build
|
||||
|
||||
RUN git clone https://github.com/scikit-build/cmake-python-distributions.git \
|
||||
&& cd cmake-python-distributions/ \
|
||||
&& python3 setup.py bdist_wheel
|
||||
|
||||
RUN pip3 install cmake-python-distributions/dist/*.whl
|
||||
|
||||
RUN pip3 wheel --wheel-dir=/wheels \
|
||||
opencv-python-headless \
|
||||
numpy \
|
||||
imutils \
|
||||
scipy \
|
||||
psutil \
|
||||
Flask \
|
||||
paho-mqtt \
|
||||
PyYAML \
|
||||
matplotlib \
|
||||
click
|
||||
|
||||
FROM scratch
|
||||
|
||||
COPY --from=build /wheels /wheels
|
263
docker/main/Dockerfile
Normal file
263
docker/main/Dockerfile
Normal file
@@ -0,0 +1,263 @@
|
||||
# syntax=docker/dockerfile:1.6
|
||||
|
||||
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ARG BASE_IMAGE=debian:11
|
||||
ARG SLIM_BASE=debian:11-slim
|
||||
|
||||
FROM ${BASE_IMAGE} AS base
|
||||
|
||||
FROM --platform=${BUILDPLATFORM} debian:11 AS base_host
|
||||
|
||||
FROM ${SLIM_BASE} AS slim-base
|
||||
|
||||
FROM slim-base AS wget
|
||||
ARG DEBIAN_FRONTEND
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y wget xz-utils \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
WORKDIR /rootfs
|
||||
|
||||
FROM base AS nginx
|
||||
ARG DEBIAN_FRONTEND
|
||||
ENV CCACHE_DIR /root/.ccache
|
||||
ENV CCACHE_MAXSIZE 2G
|
||||
|
||||
# bind /var/cache/apt to tmpfs to speed up nginx build
|
||||
RUN --mount=type=tmpfs,target=/tmp --mount=type=tmpfs,target=/var/cache/apt \
|
||||
--mount=type=bind,source=docker/main/build_nginx.sh,target=/deps/build_nginx.sh \
|
||||
--mount=type=cache,target=/root/.ccache \
|
||||
/deps/build_nginx.sh
|
||||
|
||||
FROM scratch AS go2rtc
|
||||
ARG TARGETARCH
|
||||
WORKDIR /rootfs/usr/local/go2rtc/bin
|
||||
ADD --link --chmod=755 "https://github.com/AlexxIT/go2rtc/releases/download/v1.8.1/go2rtc_linux_${TARGETARCH}" go2rtc
|
||||
|
||||
|
||||
####
|
||||
#
|
||||
# OpenVino Support
|
||||
#
|
||||
# 1. Download and convert a model from Intel's Public Open Model Zoo
|
||||
# 2. Build libUSB without udev to handle NCS2 enumeration
|
||||
#
|
||||
####
|
||||
# Download and Convert OpenVino model
|
||||
FROM base_host AS ov-converter
|
||||
ARG DEBIAN_FRONTEND
|
||||
|
||||
# Install OpenVino Runtime and Dev library
|
||||
COPY docker/main/requirements-ov.txt /requirements-ov.txt
|
||||
RUN apt-get -qq update \
|
||||
&& apt-get -qq install -y wget python3 python3-distutils \
|
||||
&& wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
|
||||
&& python3 get-pip.py "pip" \
|
||||
&& pip install -r /requirements-ov.txt
|
||||
|
||||
# Get OpenVino Model
|
||||
RUN mkdir /models \
|
||||
&& cd /models && omz_downloader --name ssdlite_mobilenet_v2 \
|
||||
&& cd /models && omz_converter --name ssdlite_mobilenet_v2 --precision FP16
|
||||
|
||||
|
||||
# libUSB - No Udev
|
||||
FROM wget as libusb-build
|
||||
ARG TARGETARCH
|
||||
ARG DEBIAN_FRONTEND
|
||||
ENV CCACHE_DIR /root/.ccache
|
||||
ENV CCACHE_MAXSIZE 2G
|
||||
|
||||
# Build libUSB without udev. Needed for Openvino NCS2 support
|
||||
WORKDIR /opt
|
||||
RUN apt-get update && apt-get install -y unzip build-essential automake libtool ccache pkg-config
|
||||
RUN --mount=type=cache,target=/root/.ccache wget -q https://github.com/libusb/libusb/archive/v1.0.26.zip -O v1.0.26.zip && \
|
||||
unzip v1.0.26.zip && cd libusb-1.0.26 && \
|
||||
./bootstrap.sh && \
|
||||
./configure CC='ccache gcc' CCX='ccache g++' --disable-udev --enable-shared && \
|
||||
make -j $(nproc --all)
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends libusb-1.0-0-dev && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
WORKDIR /opt/libusb-1.0.26/libusb
|
||||
RUN /bin/mkdir -p '/usr/local/lib' && \
|
||||
/bin/bash ../libtool --mode=install /usr/bin/install -c libusb-1.0.la '/usr/local/lib' && \
|
||||
/bin/mkdir -p '/usr/local/include/libusb-1.0' && \
|
||||
/usr/bin/install -c -m 644 libusb.h '/usr/local/include/libusb-1.0' && \
|
||||
/bin/mkdir -p '/usr/local/lib/pkgconfig' && \
|
||||
cd /opt/libusb-1.0.26/ && \
|
||||
/usr/bin/install -c -m 644 libusb-1.0.pc '/usr/local/lib/pkgconfig' && \
|
||||
ldconfig
|
||||
|
||||
FROM wget AS models
|
||||
|
||||
# Get model and labels
|
||||
RUN wget -qO edgetpu_model.tflite https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess_edgetpu.tflite
|
||||
RUN wget -qO cpu_model.tflite https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess.tflite
|
||||
COPY labelmap.txt .
|
||||
# Copy OpenVino model
|
||||
COPY --from=ov-converter /models/public/ssdlite_mobilenet_v2/FP16 openvino-model
|
||||
RUN wget -q https://github.com/openvinotoolkit/open_model_zoo/raw/master/data/dataset_classes/coco_91cl_bkgr.txt -O openvino-model/coco_91cl_bkgr.txt && \
|
||||
sed -i 's/truck/car/g' openvino-model/coco_91cl_bkgr.txt
|
||||
# Get Audio Model and labels
|
||||
RUN wget -qO cpu_audio_model.tflite https://tfhub.dev/google/lite-model/yamnet/classification/tflite/1?lite-format=tflite
|
||||
COPY audio-labelmap.txt .
|
||||
|
||||
|
||||
FROM wget AS s6-overlay
|
||||
ARG TARGETARCH
|
||||
RUN --mount=type=bind,source=docker/main/install_s6_overlay.sh,target=/deps/install_s6_overlay.sh \
|
||||
/deps/install_s6_overlay.sh
|
||||
|
||||
|
||||
FROM base AS wheels
|
||||
ARG DEBIAN_FRONTEND
|
||||
ARG TARGETARCH
|
||||
|
||||
# Use a separate container to build wheels to prevent build dependencies in final image
|
||||
RUN apt-get -qq update \
|
||||
&& apt-get -qq install -y \
|
||||
apt-transport-https \
|
||||
gnupg \
|
||||
wget \
|
||||
# the key fingerprint can be obtained from https://ftp-master.debian.org/keys.html
|
||||
&& wget -qO- "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xA4285295FC7B1A81600062A9605C66F00D6C9793" | \
|
||||
gpg --dearmor > /usr/share/keyrings/debian-archive-bullseye-stable.gpg \
|
||||
&& echo "deb [signed-by=/usr/share/keyrings/debian-archive-bullseye-stable.gpg] http://deb.debian.org/debian bullseye main contrib non-free" | \
|
||||
tee /etc/apt/sources.list.d/debian-bullseye-nonfree.list \
|
||||
&& apt-get -qq update \
|
||||
&& apt-get -qq install -y \
|
||||
python3.9 \
|
||||
python3.9-dev \
|
||||
# opencv dependencies
|
||||
build-essential cmake git pkg-config libgtk-3-dev \
|
||||
libavcodec-dev libavformat-dev libswscale-dev libv4l-dev \
|
||||
libxvidcore-dev libx264-dev libjpeg-dev libpng-dev libtiff-dev \
|
||||
gfortran openexr libatlas-base-dev libssl-dev\
|
||||
libtbb2 libtbb-dev libdc1394-22-dev libopenexr-dev \
|
||||
libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev \
|
||||
# scipy dependencies
|
||||
gcc gfortran libopenblas-dev liblapack-dev && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Ensure python3 defaults to python3.9
|
||||
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1
|
||||
|
||||
RUN wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
|
||||
&& python3 get-pip.py "pip"
|
||||
|
||||
COPY docker/main/requirements.txt /requirements.txt
|
||||
RUN pip3 install -r /requirements.txt
|
||||
|
||||
COPY docker/main/requirements-wheels.txt /requirements-wheels.txt
|
||||
RUN pip3 wheel --wheel-dir=/wheels -r /requirements-wheels.txt
|
||||
|
||||
|
||||
# Collect deps in a single layer
|
||||
FROM scratch AS deps-rootfs
|
||||
COPY --from=nginx /usr/local/nginx/ /usr/local/nginx/
|
||||
COPY --from=go2rtc /rootfs/ /
|
||||
COPY --from=libusb-build /usr/local/lib /usr/local/lib
|
||||
COPY --from=s6-overlay /rootfs/ /
|
||||
COPY --from=models /rootfs/ /
|
||||
COPY docker/main/rootfs/ /
|
||||
|
||||
|
||||
# Frigate deps (ffmpeg, python, nginx, go2rtc, s6-overlay, etc)
|
||||
FROM slim-base AS deps
|
||||
ARG TARGETARCH
|
||||
|
||||
ARG DEBIAN_FRONTEND
|
||||
# http://stackoverflow.com/questions/48162574/ddg#49462622
|
||||
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
|
||||
|
||||
# https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(Native-GPU-Support)
|
||||
ENV NVIDIA_VISIBLE_DEVICES=all
|
||||
ENV NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
|
||||
|
||||
ENV PATH="/usr/lib/btbn-ffmpeg/bin:/usr/local/go2rtc/bin:/usr/local/nginx/sbin:${PATH}"
|
||||
|
||||
# Install dependencies
|
||||
RUN --mount=type=bind,source=docker/main/install_deps.sh,target=/deps/install_deps.sh \
|
||||
/deps/install_deps.sh
|
||||
|
||||
RUN --mount=type=bind,from=wheels,source=/wheels,target=/deps/wheels \
|
||||
python3 -m pip install --upgrade pip && \
|
||||
pip3 install -U /deps/wheels/*.whl
|
||||
|
||||
COPY --from=deps-rootfs / /
|
||||
|
||||
RUN ldconfig
|
||||
|
||||
EXPOSE 5000
|
||||
EXPOSE 1935
|
||||
EXPOSE 8554
|
||||
EXPOSE 8555/tcp 8555/udp
|
||||
|
||||
# Configure logging to prepend timestamps, log to stdout, keep 0 archives and rotate on 10MB
|
||||
ENV S6_LOGGING_SCRIPT="T 1 n0 s10000000 T"
|
||||
|
||||
ENTRYPOINT ["/init"]
|
||||
CMD []
|
||||
|
||||
HEALTHCHECK --start-period=120s --start-interval=5s --interval=15s --timeout=5s --retries=3 \
|
||||
CMD curl --fail --silent --show-error http://127.0.0.1:5000/api/version || exit 1
|
||||
|
||||
# Frigate deps with Node.js and NPM for devcontainer
|
||||
FROM deps AS devcontainer
|
||||
|
||||
# Do not start the actual Frigate service on devcontainer as it will be started by VSCode
|
||||
# But start a fake service for simulating the logs
|
||||
COPY docker/main/fake_frigate_run /etc/s6-overlay/s6-rc.d/frigate/run
|
||||
|
||||
# Create symbolic link to the frigate source code, as go2rtc's create_config.sh uses it
|
||||
RUN mkdir -p /opt/frigate \
|
||||
&& ln -svf /workspace/frigate/frigate /opt/frigate/frigate
|
||||
|
||||
# Install Node 16
|
||||
RUN apt-get update \
|
||||
&& apt-get install wget -y \
|
||||
&& wget -qO- https://deb.nodesource.com/setup_16.x | bash - \
|
||||
&& apt-get install -y nodejs \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& npm install -g npm@9
|
||||
|
||||
WORKDIR /workspace/frigate
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install make -y \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN --mount=type=bind,source=./docker/main/requirements-dev.txt,target=/workspace/frigate/requirements-dev.txt \
|
||||
pip3 install -r requirements-dev.txt
|
||||
|
||||
CMD ["sleep", "infinity"]
|
||||
|
||||
|
||||
# Frigate web build
|
||||
# This should be architecture agnostic, so speed up the build on multiarch by not using QEMU.
|
||||
FROM --platform=$BUILDPLATFORM node:16 AS web-build
|
||||
|
||||
WORKDIR /work
|
||||
COPY web/package.json web/package-lock.json ./
|
||||
RUN npm install
|
||||
|
||||
COPY web/ ./
|
||||
RUN npm run build \
|
||||
&& mv dist/BASE_PATH/monacoeditorwork/* dist/assets/ \
|
||||
&& rm -rf dist/BASE_PATH
|
||||
|
||||
# Collect final files in a single layer
|
||||
FROM scratch AS rootfs
|
||||
|
||||
WORKDIR /opt/frigate/
|
||||
COPY frigate frigate/
|
||||
COPY migrations migrations/
|
||||
COPY --from=web-build /work/dist/ web/
|
||||
|
||||
# Frigate final container
|
||||
FROM deps AS frigate
|
||||
|
||||
WORKDIR /opt/frigate/
|
||||
COPY --from=rootfs / /
|
70
docker/main/build_nginx.sh
Executable file
70
docker/main/build_nginx.sh
Executable file
@@ -0,0 +1,70 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
NGINX_VERSION="1.25.2"
|
||||
VOD_MODULE_VERSION="1.31"
|
||||
SECURE_TOKEN_MODULE_VERSION="1.5"
|
||||
RTMP_MODULE_VERSION="1.2.2"
|
||||
|
||||
cp /etc/apt/sources.list /etc/apt/sources.list.d/sources-src.list
|
||||
sed -i 's|deb http|deb-src http|g' /etc/apt/sources.list.d/sources-src.list
|
||||
apt-get update
|
||||
|
||||
apt-get -yqq build-dep nginx
|
||||
|
||||
apt-get -yqq install --no-install-recommends ca-certificates wget
|
||||
update-ca-certificates -f
|
||||
apt install -y ccache
|
||||
|
||||
export PATH="/usr/lib/ccache:$PATH"
|
||||
|
||||
mkdir /tmp/nginx
|
||||
wget -nv https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz
|
||||
tar -zxf nginx-${NGINX_VERSION}.tar.gz -C /tmp/nginx --strip-components=1
|
||||
rm nginx-${NGINX_VERSION}.tar.gz
|
||||
mkdir /tmp/nginx-vod-module
|
||||
wget -nv https://github.com/kaltura/nginx-vod-module/archive/refs/tags/${VOD_MODULE_VERSION}.tar.gz
|
||||
tar -zxf ${VOD_MODULE_VERSION}.tar.gz -C /tmp/nginx-vod-module --strip-components=1
|
||||
rm ${VOD_MODULE_VERSION}.tar.gz
|
||||
# Patch MAX_CLIPS to allow more clips to be added than the default 128
|
||||
sed -i 's/MAX_CLIPS (128)/MAX_CLIPS (1080)/g' /tmp/nginx-vod-module/vod/media_set.h
|
||||
patch -d /tmp/nginx-vod-module/ -p1 << 'EOF'
|
||||
--- a/vod/avc_hevc_parser.c 2022-06-27 11:38:10.000000000 +0000
|
||||
+++ b/vod/avc_hevc_parser.c 2023-01-16 11:25:10.900521298 +0000
|
||||
@@ -3,6 +3,9 @@
|
||||
bool_t
|
||||
avc_hevc_parser_rbsp_trailing_bits(bit_reader_state_t* reader)
|
||||
{
|
||||
+ // https://github.com/blakeblackshear/frigate/issues/4572
|
||||
+ return TRUE;
|
||||
+
|
||||
uint32_t one_bit;
|
||||
|
||||
if (reader->stream.eof_reached)
|
||||
EOF
|
||||
|
||||
|
||||
mkdir /tmp/nginx-secure-token-module
|
||||
wget https://github.com/kaltura/nginx-secure-token-module/archive/refs/tags/${SECURE_TOKEN_MODULE_VERSION}.tar.gz
|
||||
tar -zxf ${SECURE_TOKEN_MODULE_VERSION}.tar.gz -C /tmp/nginx-secure-token-module --strip-components=1
|
||||
rm ${SECURE_TOKEN_MODULE_VERSION}.tar.gz
|
||||
mkdir /tmp/nginx-rtmp-module
|
||||
wget -nv https://github.com/arut/nginx-rtmp-module/archive/refs/tags/v${RTMP_MODULE_VERSION}.tar.gz
|
||||
tar -zxf v${RTMP_MODULE_VERSION}.tar.gz -C /tmp/nginx-rtmp-module --strip-components=1
|
||||
rm v${RTMP_MODULE_VERSION}.tar.gz
|
||||
|
||||
cd /tmp/nginx
|
||||
|
||||
./configure --prefix=/usr/local/nginx \
|
||||
--with-file-aio \
|
||||
--with-http_sub_module \
|
||||
--with-http_ssl_module \
|
||||
--with-threads \
|
||||
--add-module=../nginx-vod-module \
|
||||
--add-module=../nginx-secure-token-module \
|
||||
--add-module=../nginx-rtmp-module \
|
||||
--with-cc-opt="-O3 -Wno-error=implicit-fallthrough"
|
||||
|
||||
make CC="ccache gcc" -j$(nproc) && make install
|
||||
rm -rf /usr/local/nginx/html /usr/local/nginx/conf/*.default
|
13
docker/main/fake_frigate_run
Executable file
13
docker/main/fake_frigate_run
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/command/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
# Start the fake Frigate service
|
||||
|
||||
set -o errexit -o nounset -o pipefail
|
||||
|
||||
# Tell S6-Overlay not to restart this service
|
||||
s6-svc -O .
|
||||
|
||||
while true; do
|
||||
echo "[INFO] The fake Frigate service is running..."
|
||||
sleep 5s
|
||||
done
|
84
docker/main/install_deps.sh
Executable file
84
docker/main/install_deps.sh
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
apt-get -qq update
|
||||
|
||||
apt-get -qq install --no-install-recommends -y \
|
||||
apt-transport-https \
|
||||
gnupg \
|
||||
wget \
|
||||
procps vainfo \
|
||||
unzip locales tzdata libxml2 xz-utils \
|
||||
python3.9 \
|
||||
python3-pip \
|
||||
curl \
|
||||
jq \
|
||||
nethogs
|
||||
|
||||
# ensure python3 defaults to python3.9
|
||||
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1
|
||||
|
||||
mkdir -p -m 600 /root/.gnupg
|
||||
|
||||
# add coral repo
|
||||
curl -fsSLo - https://packages.cloud.google.com/apt/doc/apt-key.gpg | \
|
||||
gpg --dearmor -o /etc/apt/trusted.gpg.d/google-cloud-packages-archive-keyring.gpg
|
||||
echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | tee /etc/apt/sources.list.d/coral-edgetpu.list
|
||||
echo "libedgetpu1-max libedgetpu/accepted-eula select true" | debconf-set-selections
|
||||
|
||||
# enable non-free repo in Debian
|
||||
if grep -q "Debian" /etc/issue; then
|
||||
sed -i -e's/ main/ main contrib non-free/g' /etc/apt/sources.list
|
||||
fi
|
||||
|
||||
# coral drivers
|
||||
apt-get -qq update
|
||||
apt-get -qq install --no-install-recommends --no-install-suggests -y \
|
||||
libedgetpu1-max python3-tflite-runtime python3-pycoral
|
||||
|
||||
# btbn-ffmpeg -> amd64
|
||||
if [[ "${TARGETARCH}" == "amd64" ]]; then
|
||||
mkdir -p /usr/lib/btbn-ffmpeg
|
||||
wget -qO btbn-ffmpeg.tar.xz "https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2022-07-31-12-37/ffmpeg-n5.1-2-g915ef932a3-linux64-gpl-5.1.tar.xz"
|
||||
tar -xf btbn-ffmpeg.tar.xz -C /usr/lib/btbn-ffmpeg --strip-components 1
|
||||
rm -rf btbn-ffmpeg.tar.xz /usr/lib/btbn-ffmpeg/doc /usr/lib/btbn-ffmpeg/bin/ffplay
|
||||
fi
|
||||
|
||||
# ffmpeg -> arm64
|
||||
if [[ "${TARGETARCH}" == "arm64" ]]; then
|
||||
mkdir -p /usr/lib/btbn-ffmpeg
|
||||
wget -qO btbn-ffmpeg.tar.xz "https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2022-07-31-12-37/ffmpeg-n5.1-2-g915ef932a3-linuxarm64-gpl-5.1.tar.xz"
|
||||
tar -xf btbn-ffmpeg.tar.xz -C /usr/lib/btbn-ffmpeg --strip-components 1
|
||||
rm -rf btbn-ffmpeg.tar.xz /usr/lib/btbn-ffmpeg/doc /usr/lib/btbn-ffmpeg/bin/ffplay
|
||||
fi
|
||||
|
||||
# arch specific packages
|
||||
if [[ "${TARGETARCH}" == "amd64" ]]; then
|
||||
# use debian bookworm for hwaccel packages
|
||||
echo 'deb https://deb.debian.org/debian bookworm main contrib non-free' >/etc/apt/sources.list.d/debian-bookworm.list
|
||||
apt-get -qq update
|
||||
apt-get -qq install --no-install-recommends --no-install-suggests -y \
|
||||
intel-opencl-icd \
|
||||
mesa-va-drivers radeontop libva-drm2 intel-media-va-driver-non-free i965-va-driver libmfx1 intel-gpu-tools
|
||||
# something about this dependency requires it to be installed in a separate call rather than in the line above
|
||||
apt-get -qq install --no-install-recommends --no-install-suggests -y \
|
||||
i965-va-driver-shaders
|
||||
rm -f /etc/apt/sources.list.d/debian-bookworm.list
|
||||
fi
|
||||
|
||||
if [[ "${TARGETARCH}" == "arm64" ]]; then
|
||||
apt-get -qq install --no-install-recommends --no-install-suggests -y \
|
||||
libva-drm2 mesa-va-drivers
|
||||
fi
|
||||
|
||||
apt-get purge gnupg apt-transport-https xz-utils -y
|
||||
apt-get clean autoclean -y
|
||||
apt-get autoremove --purge -y
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install yq, for frigate-prepare and go2rtc echo source
|
||||
curl -fsSL \
|
||||
"https://github.com/mikefarah/yq/releases/download/v4.33.3/yq_linux_$(dpkg --print-architecture)" \
|
||||
--output /usr/local/bin/yq
|
||||
chmod +x /usr/local/bin/yq
|
19
docker/main/install_s6_overlay.sh
Executable file
19
docker/main/install_s6_overlay.sh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
s6_version="3.1.5.0"
|
||||
|
||||
if [[ "${TARGETARCH}" == "amd64" ]]; then
|
||||
s6_arch="x86_64"
|
||||
elif [[ "${TARGETARCH}" == "arm64" ]]; then
|
||||
s6_arch="aarch64"
|
||||
fi
|
||||
|
||||
mkdir -p /rootfs/
|
||||
|
||||
wget -qO- "https://github.com/just-containers/s6-overlay/releases/download/v${s6_version}/s6-overlay-noarch.tar.xz" |
|
||||
tar -C /rootfs/ -Jxpf -
|
||||
|
||||
wget -qO- "https://github.com/just-containers/s6-overlay/releases/download/v${s6_version}/s6-overlay-${s6_arch}.tar.xz" |
|
||||
tar -C /rootfs/ -Jxpf -
|
3
docker/main/requirements-dev.txt
Normal file
3
docker/main/requirements-dev.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
black == 23.10.*
|
||||
isort
|
||||
ruff
|
5
docker/main/requirements-ov.txt
Normal file
5
docker/main/requirements-ov.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
numpy
|
||||
# Openvino Library - Custom built with MYRIAD support
|
||||
openvino @ https://github.com/NateMeyer/openvino-wheels/releases/download/multi-arch_2022.3.1/openvino-2022.3.1-1-cp39-cp39-manylinux_2_31_x86_64.whl; platform_machine == 'x86_64'
|
||||
openvino @ https://github.com/NateMeyer/openvino-wheels/releases/download/multi-arch_2022.3.1/openvino-2022.3.1-1-cp39-cp39-linux_aarch64.whl; platform_machine == 'aarch64'
|
||||
openvino-dev[tensorflow2] @ https://github.com/NateMeyer/openvino-wheels/releases/download/multi-arch_2022.3.1/openvino_dev-2022.3.1-1-py3-none-any.whl
|
28
docker/main/requirements-wheels.txt
Normal file
28
docker/main/requirements-wheels.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
click == 8.1.*
|
||||
Flask == 2.3.*
|
||||
imutils == 0.5.*
|
||||
matplotlib == 3.7.*
|
||||
mypy == 1.6.1
|
||||
numpy == 1.23.*
|
||||
onvif_zeep == 0.2.12
|
||||
opencv-python-headless == 4.7.0.*
|
||||
paho-mqtt == 1.6.*
|
||||
peewee == 3.17.*
|
||||
peewee_migrate == 1.12.*
|
||||
psutil == 5.9.*
|
||||
pydantic == 1.10.*
|
||||
git+https://github.com/fbcotter/py3nvml#egg=py3nvml
|
||||
PyYAML == 6.0.*
|
||||
pytz == 2023.3
|
||||
ruamel.yaml == 0.17.*
|
||||
tzlocal == 5.1
|
||||
types-PyYAML == 6.0.*
|
||||
requests == 2.31.*
|
||||
types-requests == 2.31.*
|
||||
scipy == 1.11.*
|
||||
norfair == 2.2.*
|
||||
setproctitle == 1.3.*
|
||||
ws4py == 0.5.*
|
||||
# Openvino Library - Custom built with MYRIAD support
|
||||
openvino @ https://github.com/NateMeyer/openvino-wheels/releases/download/multi-arch_2022.3.1/openvino-2022.3.1-1-cp39-cp39-manylinux_2_31_x86_64.whl; platform_machine == 'x86_64'
|
||||
openvino @ https://github.com/NateMeyer/openvino-wheels/releases/download/multi-arch_2022.3.1/openvino-2022.3.1-1-cp39-cp39-linux_aarch64.whl; platform_machine == 'aarch64'
|
2
docker/main/requirements.txt
Normal file
2
docker/main/requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
scikit-build == 0.17.*
|
||||
nvidia-pyindex
|
@@ -0,0 +1 @@
|
||||
frigate
|
@@ -0,0 +1 @@
|
||||
frigate-pipeline
|
4
docker/main/rootfs/etc/s6-overlay/s6-rc.d/frigate-log/run
Executable file
4
docker/main/rootfs/etc/s6-overlay/s6-rc.d/frigate-log/run
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/command/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
|
||||
exec logutil-service /dev/shm/logs/frigate
|
@@ -0,0 +1 @@
|
||||
longrun
|
28
docker/main/rootfs/etc/s6-overlay/s6-rc.d/frigate/finish
Executable file
28
docker/main/rootfs/etc/s6-overlay/s6-rc.d/frigate/finish
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/command/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
# Take down the S6 supervision tree when the service exits
|
||||
|
||||
set -o errexit -o nounset -o pipefail
|
||||
|
||||
# Logs should be sent to stdout so that s6 can collect them
|
||||
|
||||
declare exit_code_container
|
||||
exit_code_container=$(cat /run/s6-linux-init-container-results/exitcode)
|
||||
readonly exit_code_container
|
||||
readonly exit_code_service="${1}"
|
||||
readonly exit_code_signal="${2}"
|
||||
readonly service="Frigate"
|
||||
|
||||
echo "[INFO] Service ${service} exited with code ${exit_code_service} (by signal ${exit_code_signal})"
|
||||
|
||||
if [[ "${exit_code_service}" -eq 256 ]]; then
|
||||
if [[ "${exit_code_container}" -eq 0 ]]; then
|
||||
echo $((128 + exit_code_signal)) >/run/s6-linux-init-container-results/exitcode
|
||||
fi
|
||||
elif [[ "${exit_code_service}" -ne 0 ]]; then
|
||||
if [[ "${exit_code_container}" -eq 0 ]]; then
|
||||
echo "${exit_code_service}" >/run/s6-linux-init-container-results/exitcode
|
||||
fi
|
||||
fi
|
||||
|
||||
exec /run/s6/basedir/bin/halt
|
@@ -0,0 +1 @@
|
||||
frigate-log
|
55
docker/main/rootfs/etc/s6-overlay/s6-rc.d/frigate/run
Executable file
55
docker/main/rootfs/etc/s6-overlay/s6-rc.d/frigate/run
Executable file
@@ -0,0 +1,55 @@
|
||||
#!/command/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
# Start the Frigate service
|
||||
|
||||
set -o errexit -o nounset -o pipefail
|
||||
|
||||
# Logs should be sent to stdout so that s6 can collect them
|
||||
|
||||
# Tell S6-Overlay not to restart this service
|
||||
s6-svc -O .
|
||||
|
||||
function migrate_db_path() {
|
||||
# Find config file in yaml or yml, but prefer yaml
|
||||
local config_file="${CONFIG_FILE:-"/config/config.yml"}"
|
||||
local config_file_yaml="${config_file//.yml/.yaml}"
|
||||
if [[ -f "${config_file_yaml}" ]]; then
|
||||
config_file="${config_file_yaml}"
|
||||
elif [[ ! -f "${config_file}" ]]; then
|
||||
echo "[ERROR] Frigate config file not found"
|
||||
return 1
|
||||
fi
|
||||
unset config_file_yaml
|
||||
|
||||
# Use yq to check if database.path is set
|
||||
local user_db_path
|
||||
user_db_path=$(yq eval '.database.path' "${config_file}")
|
||||
|
||||
if [[ "${user_db_path}" == "null" ]]; then
|
||||
local previous_db_path="/media/frigate/frigate.db"
|
||||
local new_db_dir="/config"
|
||||
if [[ -f "${previous_db_path}" ]]; then
|
||||
if mountpoint --quiet "${new_db_dir}"; then
|
||||
# /config is a mount point, move the db
|
||||
echo "[INFO] Moving db from '${previous_db_path}' to the '${new_db_dir}' dir..."
|
||||
# Move all files that starts with frigate.db to the new directory
|
||||
mv -vf "${previous_db_path}"* "${new_db_dir}"
|
||||
else
|
||||
echo "[ERROR] Trying to migrate the db path from '${previous_db_path}' to the '${new_db_dir}' dir, but '${new_db_dir}' is not a mountpoint, please mount the '${new_db_dir}' dir"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
echo "[INFO] Preparing Frigate..."
|
||||
migrate_db_path
|
||||
export LIBAVFORMAT_VERSION_MAJOR=$(ffmpeg -version | grep -Po 'libavformat\W+\K\d+')
|
||||
|
||||
echo "[INFO] Starting Frigate..."
|
||||
|
||||
cd /opt/frigate || echo "[ERROR] Failed to change working directory to /opt/frigate"
|
||||
|
||||
# Replace the bash process with the Frigate process, redirecting stderr to stdout
|
||||
exec 2>&1
|
||||
exec python3 -u -m frigate
|
@@ -0,0 +1 @@
|
||||
120000
|
1
docker/main/rootfs/etc/s6-overlay/s6-rc.d/frigate/type
Normal file
1
docker/main/rootfs/etc/s6-overlay/s6-rc.d/frigate/type
Normal file
@@ -0,0 +1 @@
|
||||
longrun
|
12
docker/main/rootfs/etc/s6-overlay/s6-rc.d/go2rtc-healthcheck/finish
Executable file
12
docker/main/rootfs/etc/s6-overlay/s6-rc.d/go2rtc-healthcheck/finish
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/command/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
|
||||
set -o errexit -o nounset -o pipefail
|
||||
|
||||
# Logs should be sent to stdout so that s6 can collect them
|
||||
|
||||
readonly exit_code_service="${1}"
|
||||
readonly exit_code_signal="${2}"
|
||||
readonly service="go2rtc-healthcheck"
|
||||
|
||||
echo "[INFO] The ${service} service exited with code ${exit_code_service} (by signal ${exit_code_signal})"
|
@@ -0,0 +1 @@
|
||||
go2rtc-log
|
22
docker/main/rootfs/etc/s6-overlay/s6-rc.d/go2rtc-healthcheck/run
Executable file
22
docker/main/rootfs/etc/s6-overlay/s6-rc.d/go2rtc-healthcheck/run
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/command/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
# Start the go2rtc-healthcheck service
|
||||
|
||||
set -o errexit -o nounset -o pipefail
|
||||
|
||||
# Logs should be sent to stdout so that s6 can collect them
|
||||
|
||||
# Give some additional time for go2rtc to start before start pinging
|
||||
sleep 10s
|
||||
echo "[INFO] Starting go2rtc healthcheck service..."
|
||||
|
||||
while sleep 30s; do
|
||||
# Check if the service is running
|
||||
if ! curl --connect-timeout 10 --fail --silent --show-error --output /dev/null http://127.0.0.1:1984/api/streams 2>&1; then
|
||||
echo "[ERROR] The go2rtc service is not responding to ping, restarting..."
|
||||
# We can also use -r instead of -t to send kill signal rather than term
|
||||
s6-svc -t /var/run/service/go2rtc 2>&1
|
||||
# Give some additional time to go2rtc to restart before start pinging again
|
||||
sleep 10s
|
||||
fi
|
||||
done
|
@@ -0,0 +1 @@
|
||||
5000
|
@@ -0,0 +1 @@
|
||||
longrun
|
@@ -0,0 +1,2 @@
|
||||
go2rtc
|
||||
go2rtc-healthcheck
|
@@ -0,0 +1 @@
|
||||
go2rtc-pipeline
|
4
docker/main/rootfs/etc/s6-overlay/s6-rc.d/go2rtc-log/run
Executable file
4
docker/main/rootfs/etc/s6-overlay/s6-rc.d/go2rtc-log/run
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/command/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
|
||||
exec logutil-service /dev/shm/logs/go2rtc
|
@@ -0,0 +1 @@
|
||||
longrun
|
12
docker/main/rootfs/etc/s6-overlay/s6-rc.d/go2rtc/finish
Executable file
12
docker/main/rootfs/etc/s6-overlay/s6-rc.d/go2rtc/finish
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/command/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
|
||||
set -o errexit -o nounset -o pipefail
|
||||
|
||||
# Logs should be sent to stdout so that s6 can collect them
|
||||
|
||||
readonly exit_code_service="${1}"
|
||||
readonly exit_code_signal="${2}"
|
||||
readonly service="go2rtc"
|
||||
|
||||
echo "[INFO] The ${service} service exited with code ${exit_code_service} (by signal ${exit_code_signal})"
|
@@ -0,0 +1 @@
|
||||
go2rtc-log
|
72
docker/main/rootfs/etc/s6-overlay/s6-rc.d/go2rtc/run
Executable file
72
docker/main/rootfs/etc/s6-overlay/s6-rc.d/go2rtc/run
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/command/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
# Start the go2rtc service
|
||||
|
||||
set -o errexit -o nounset -o pipefail
|
||||
|
||||
# Logs should be sent to stdout so that s6 can collect them
|
||||
|
||||
function get_ip_and_port_from_supervisor() {
|
||||
local ip_address
|
||||
# Example: 192.168.1.10/24
|
||||
local ip_regex='^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})/[0-9]{1,2}$'
|
||||
if ip_address=$(
|
||||
curl -fsSL \
|
||||
-H "Authorization: Bearer ${SUPERVISOR_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
http://supervisor/network/interface/default/info |
|
||||
jq --exit-status --raw-output '.data.ipv4.address[0]'
|
||||
) && [[ "${ip_address}" =~ ${ip_regex} ]]; then
|
||||
ip_address="${BASH_REMATCH[1]}"
|
||||
echo "[INFO] Got IP address from supervisor: ${ip_address}"
|
||||
else
|
||||
echo "[WARN] Failed to get IP address from supervisor"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local webrtc_port
|
||||
local port_regex='^([0-9]{1,5})$'
|
||||
if webrtc_port=$(
|
||||
curl -fsSL \
|
||||
-H "Authorization: Bearer ${SUPERVISOR_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
http://supervisor/addons/self/info |
|
||||
jq --exit-status --raw-output '.data.network["8555/tcp"]'
|
||||
) && [[ "${webrtc_port}" =~ ${port_regex} ]]; then
|
||||
webrtc_port="${BASH_REMATCH[1]}"
|
||||
echo "[INFO] Got WebRTC port from supervisor: ${webrtc_port}"
|
||||
else
|
||||
echo "[WARN] Failed to get WebRTC port from supervisor"
|
||||
return 0
|
||||
fi
|
||||
|
||||
export FRIGATE_GO2RTC_WEBRTC_CANDIDATE_INTERNAL="${ip_address}:${webrtc_port}"
|
||||
}
|
||||
|
||||
export LIBAVFORMAT_VERSION_MAJOR=$(ffmpeg -version | grep -Po 'libavformat\W+\K\d+')
|
||||
|
||||
if [[ ! -f "/dev/shm/go2rtc.yaml" ]]; then
|
||||
echo "[INFO] Preparing go2rtc config..."
|
||||
|
||||
if [[ -n "${SUPERVISOR_TOKEN:-}" ]]; then
|
||||
# Running as a Home Assistant add-on, infer the IP address and port
|
||||
get_ip_and_port_from_supervisor
|
||||
fi
|
||||
|
||||
python3 /usr/local/go2rtc/create_config.py
|
||||
fi
|
||||
|
||||
readonly config_path="/config"
|
||||
|
||||
if [[ -x "${config_path}/go2rtc" ]]; then
|
||||
readonly binary_path="${config_path}/go2rtc"
|
||||
echo "[WARN] Using go2rtc binary from '${binary_path}' instead of the embedded one"
|
||||
else
|
||||
readonly binary_path="/usr/local/go2rtc/bin/go2rtc"
|
||||
fi
|
||||
|
||||
echo "[INFO] Starting go2rtc..."
|
||||
|
||||
# Replace the bash process with the go2rtc process, redirecting stderr to stdout
|
||||
exec 2>&1
|
||||
exec "${binary_path}" -config=/dev/shm/go2rtc.yaml
|
@@ -0,0 +1 @@
|
||||
30000
|
1
docker/main/rootfs/etc/s6-overlay/s6-rc.d/go2rtc/type
Normal file
1
docker/main/rootfs/etc/s6-overlay/s6-rc.d/go2rtc/type
Normal file
@@ -0,0 +1 @@
|
||||
longrun
|
11
docker/main/rootfs/etc/s6-overlay/s6-rc.d/log-prepare/run
Executable file
11
docker/main/rootfs/etc/s6-overlay/s6-rc.d/log-prepare/run
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/command/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
# Prepare the logs folder for s6-log
|
||||
|
||||
set -o errexit -o nounset -o pipefail
|
||||
|
||||
dirs=(/dev/shm/logs/frigate /dev/shm/logs/go2rtc /dev/shm/logs/nginx)
|
||||
|
||||
mkdir -p "${dirs[@]}"
|
||||
chown nobody:nogroup "${dirs[@]}"
|
||||
chmod 02755 "${dirs[@]}"
|
@@ -0,0 +1 @@
|
||||
oneshot
|
1
docker/main/rootfs/etc/s6-overlay/s6-rc.d/log-prepare/up
Normal file
1
docker/main/rootfs/etc/s6-overlay/s6-rc.d/log-prepare/up
Normal file
@@ -0,0 +1 @@
|
||||
/etc/s6-overlay/s6-rc.d/log-prepare/run
|
@@ -0,0 +1 @@
|
||||
nginx
|
@@ -0,0 +1 @@
|
||||
nginx-pipeline
|
4
docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx-log/run
Executable file
4
docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx-log/run
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/command/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
|
||||
exec logutil-service /dev/shm/logs/nginx
|
1
docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx-log/type
Normal file
1
docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx-log/type
Normal file
@@ -0,0 +1 @@
|
||||
longrun
|
30
docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish
Executable file
30
docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/command/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
# Take down the S6 supervision tree when the service fails
|
||||
|
||||
set -o errexit -o nounset -o pipefail
|
||||
|
||||
# Logs should be sent to stdout so that s6 can collect them
|
||||
|
||||
declare exit_code_container
|
||||
exit_code_container=$(cat /run/s6-linux-init-container-results/exitcode)
|
||||
readonly exit_code_container
|
||||
readonly exit_code_service="${1}"
|
||||
readonly exit_code_signal="${2}"
|
||||
readonly service="NGINX"
|
||||
|
||||
echo "[INFO] Service ${service} exited with code ${exit_code_service} (by signal ${exit_code_signal})"
|
||||
|
||||
if [[ "${exit_code_service}" -eq 256 ]]; then
|
||||
if [[ "${exit_code_container}" -eq 0 ]]; then
|
||||
echo $((128 + exit_code_signal)) >/run/s6-linux-init-container-results/exitcode
|
||||
fi
|
||||
if [[ "${exit_code_signal}" -eq 15 ]]; then
|
||||
exec /run/s6/basedir/bin/halt
|
||||
fi
|
||||
elif [[ "${exit_code_service}" -ne 0 ]]; then
|
||||
if [[ "${exit_code_container}" -eq 0 ]]; then
|
||||
echo "${exit_code_service}" >/run/s6-linux-init-container-results/exitcode
|
||||
fi
|
||||
exec /run/s6/basedir/bin/halt
|
||||
fi
|
@@ -0,0 +1 @@
|
||||
nginx-log
|
13
docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx/run
Executable file
13
docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx/run
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/command/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
# Start the NGINX service
|
||||
|
||||
set -o errexit -o nounset -o pipefail
|
||||
|
||||
# Logs should be sent to stdout so that s6 can collect them
|
||||
|
||||
echo "[INFO] Starting NGINX..."
|
||||
|
||||
# Replace the bash process with the NGINX process, redirecting stderr to stdout
|
||||
exec 2>&1
|
||||
exec nginx
|
@@ -0,0 +1 @@
|
||||
30000
|
1
docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx/type
Normal file
1
docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx/type
Normal file
@@ -0,0 +1 @@
|
||||
longrun
|
137
docker/main/rootfs/usr/local/go2rtc/create_config.py
Normal file
137
docker/main/rootfs/usr/local/go2rtc/create_config.py
Normal file
@@ -0,0 +1,137 @@
|
||||
"""Creates a go2rtc config file."""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
import yaml
|
||||
|
||||
sys.path.insert(0, "/opt/frigate")
|
||||
from frigate.const import BIRDSEYE_PIPE # noqa: E402
|
||||
from frigate.ffmpeg_presets import ( # noqa: E402
|
||||
parse_preset_hardware_acceleration_encode,
|
||||
)
|
||||
|
||||
sys.path.remove("/opt/frigate")
|
||||
|
||||
|
||||
FRIGATE_ENV_VARS = {k: v for k, v in os.environ.items() if k.startswith("FRIGATE_")}
|
||||
config_file = os.environ.get("CONFIG_FILE", "/config/config.yml")
|
||||
|
||||
# Check if we can use .yaml instead of .yml
|
||||
config_file_yaml = config_file.replace(".yml", ".yaml")
|
||||
if os.path.isfile(config_file_yaml):
|
||||
config_file = config_file_yaml
|
||||
|
||||
with open(config_file) as f:
|
||||
raw_config = f.read()
|
||||
|
||||
if config_file.endswith((".yaml", ".yml")):
|
||||
config: dict[str, any] = yaml.safe_load(raw_config)
|
||||
elif config_file.endswith(".json"):
|
||||
config: dict[str, any] = json.loads(raw_config)
|
||||
|
||||
go2rtc_config: dict[str, any] = config.get("go2rtc", {})
|
||||
|
||||
# Need to enable CORS for go2rtc so the frigate integration / card work automatically
|
||||
if go2rtc_config.get("api") is None:
|
||||
go2rtc_config["api"] = {"origin": "*"}
|
||||
elif go2rtc_config["api"].get("origin") is None:
|
||||
go2rtc_config["api"]["origin"] = "*"
|
||||
|
||||
# Need to set default location for HA config
|
||||
if go2rtc_config.get("hass") is None:
|
||||
go2rtc_config["hass"] = {"config": "/config"}
|
||||
|
||||
# we want to ensure that logs are easy to read
|
||||
if go2rtc_config.get("log") is None:
|
||||
go2rtc_config["log"] = {"format": "text"}
|
||||
elif go2rtc_config["log"].get("format") is None:
|
||||
go2rtc_config["log"]["format"] = "text"
|
||||
|
||||
if not go2rtc_config.get("webrtc", {}).get("candidates", []):
|
||||
default_candidates = []
|
||||
# use internal candidate if it was discovered when running through the add-on
|
||||
internal_candidate = os.environ.get(
|
||||
"FRIGATE_GO2RTC_WEBRTC_CANDIDATE_INTERNAL", None
|
||||
)
|
||||
if internal_candidate is not None:
|
||||
default_candidates.append(internal_candidate)
|
||||
# should set default stun server so webrtc can work
|
||||
default_candidates.append("stun:8555")
|
||||
|
||||
go2rtc_config["webrtc"] = {"candidates": default_candidates}
|
||||
else:
|
||||
print(
|
||||
"[INFO] Not injecting WebRTC candidates into go2rtc config as it has been set manually",
|
||||
)
|
||||
|
||||
# sets default RTSP response to be equivalent to ?video=h264,h265&audio=aac
|
||||
# this means user does not need to specify audio codec when using restream
|
||||
# as source for frigate and the integration supports HLS playback
|
||||
if go2rtc_config.get("rtsp") is None:
|
||||
go2rtc_config["rtsp"] = {"default_query": "mp4"}
|
||||
else:
|
||||
if go2rtc_config["rtsp"].get("default_query") is None:
|
||||
go2rtc_config["rtsp"]["default_query"] = "mp4"
|
||||
|
||||
if go2rtc_config["rtsp"].get("username") is not None:
|
||||
go2rtc_config["rtsp"]["username"] = go2rtc_config["rtsp"]["username"].format(
|
||||
**FRIGATE_ENV_VARS
|
||||
)
|
||||
|
||||
if go2rtc_config["rtsp"].get("password") is not None:
|
||||
go2rtc_config["rtsp"]["password"] = go2rtc_config["rtsp"]["password"].format(
|
||||
**FRIGATE_ENV_VARS
|
||||
)
|
||||
|
||||
# need to replace ffmpeg command when using ffmpeg4
|
||||
if int(os.environ["LIBAVFORMAT_VERSION_MAJOR"]) < 59:
|
||||
if go2rtc_config.get("ffmpeg") is None:
|
||||
go2rtc_config["ffmpeg"] = {
|
||||
"rtsp": "-fflags nobuffer -flags low_delay -stimeout 5000000 -user_agent go2rtc/ffmpeg -rtsp_transport tcp -i {input}"
|
||||
}
|
||||
elif go2rtc_config["ffmpeg"].get("rtsp") is None:
|
||||
go2rtc_config["ffmpeg"][
|
||||
"rtsp"
|
||||
] = "-fflags nobuffer -flags low_delay -stimeout 5000000 -user_agent go2rtc/ffmpeg -rtsp_transport tcp -i {input}"
|
||||
|
||||
for name in go2rtc_config.get("streams", {}):
|
||||
stream = go2rtc_config["streams"][name]
|
||||
|
||||
if isinstance(stream, str):
|
||||
try:
|
||||
go2rtc_config["streams"][name] = go2rtc_config["streams"][name].format(
|
||||
**FRIGATE_ENV_VARS
|
||||
)
|
||||
except KeyError as e:
|
||||
print(
|
||||
"[ERROR] Invalid substitution found, see https://docs.frigate.video/configuration/restream#advanced-restream-configurations for more info."
|
||||
)
|
||||
sys.exit(e)
|
||||
|
||||
elif isinstance(stream, list):
|
||||
for i, stream in enumerate(stream):
|
||||
try:
|
||||
go2rtc_config["streams"][name][i] = stream.format(**FRIGATE_ENV_VARS)
|
||||
except KeyError as e:
|
||||
print(
|
||||
"[ERROR] Invalid substitution found, see https://docs.frigate.video/configuration/restream#advanced-restream-configurations for more info."
|
||||
)
|
||||
sys.exit(e)
|
||||
|
||||
# add birdseye restream stream if enabled
|
||||
if config.get("birdseye", {}).get("restream", False):
|
||||
birdseye: dict[str, any] = config.get("birdseye")
|
||||
|
||||
input = f"-f rawvideo -pix_fmt yuv420p -video_size {birdseye.get('width', 1280)}x{birdseye.get('height', 720)} -r 10 -i {BIRDSEYE_PIPE}"
|
||||
ffmpeg_cmd = f"exec:{parse_preset_hardware_acceleration_encode(config.get('ffmpeg', {}).get('hwaccel_args'), input, '-rtsp_transport tcp -f rtsp {output}')}"
|
||||
|
||||
if go2rtc_config.get("streams"):
|
||||
go2rtc_config["streams"]["birdseye"] = ffmpeg_cmd
|
||||
else:
|
||||
go2rtc_config["streams"] = {"birdseye": ffmpeg_cmd}
|
||||
|
||||
# Write go2rtc_config to /dev/shm/go2rtc.yaml
|
||||
with open("/dev/shm/go2rtc.yaml", "w") as f:
|
||||
yaml.dump(go2rtc_config, f)
|
243
docker/main/rootfs/usr/local/nginx/conf/nginx.conf
Normal file
243
docker/main/rootfs/usr/local/nginx/conf/nginx.conf
Normal file
@@ -0,0 +1,243 @@
|
||||
daemon off;
|
||||
user root;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /dev/stdout warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /dev/stdout main;
|
||||
|
||||
# send headers in one piece, it is better than sending them one by one
|
||||
tcp_nopush on;
|
||||
|
||||
sendfile on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
gzip on;
|
||||
gzip_comp_level 6;
|
||||
gzip_types text/plain text/css application/json application/x-javascript application/javascript text/javascript image/svg+xml image/x-icon image/bmp image/png image/gif image/jpeg image/jpg;
|
||||
gzip_proxied no-cache no-store private expired auth;
|
||||
gzip_vary on;
|
||||
|
||||
upstream frigate_api {
|
||||
server 127.0.0.1:5001;
|
||||
keepalive 1024;
|
||||
}
|
||||
|
||||
upstream mqtt_ws {
|
||||
server 127.0.0.1:5002;
|
||||
keepalive 1024;
|
||||
}
|
||||
|
||||
upstream jsmpeg {
|
||||
server 127.0.0.1:8082;
|
||||
keepalive 1024;
|
||||
}
|
||||
|
||||
upstream go2rtc {
|
||||
server 127.0.0.1:1984;
|
||||
keepalive 1024;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 5000;
|
||||
|
||||
# vod settings
|
||||
vod_base_url '';
|
||||
vod_segments_base_url '';
|
||||
vod_mode mapped;
|
||||
vod_max_mapping_response_size 1m;
|
||||
vod_upstream_location /api;
|
||||
vod_align_segments_to_key_frames on;
|
||||
vod_manifest_segment_durations_mode accurate;
|
||||
vod_ignore_edit_list on;
|
||||
vod_segment_duration 10000;
|
||||
vod_hls_mpegts_align_frames off;
|
||||
vod_hls_mpegts_interleave_frames on;
|
||||
|
||||
# file handle caching / aio
|
||||
open_file_cache max=1000 inactive=5m;
|
||||
open_file_cache_valid 2m;
|
||||
open_file_cache_min_uses 1;
|
||||
open_file_cache_errors on;
|
||||
aio on;
|
||||
|
||||
# https://github.com/kaltura/nginx-vod-module#vod_open_file_thread_pool
|
||||
vod_open_file_thread_pool default;
|
||||
|
||||
# vod caches
|
||||
vod_metadata_cache metadata_cache 512m;
|
||||
vod_mapping_cache mapping_cache 5m 10m;
|
||||
|
||||
# gzip manifests
|
||||
gzip on;
|
||||
gzip_types application/vnd.apple.mpegurl;
|
||||
|
||||
location /vod/ {
|
||||
aio threads;
|
||||
vod hls;
|
||||
|
||||
secure_token $args;
|
||||
secure_token_types application/vnd.apple.mpegurl;
|
||||
|
||||
add_header Cache-Control "no-store";
|
||||
expires off;
|
||||
}
|
||||
|
||||
location /stream/ {
|
||||
add_header Cache-Control "no-store";
|
||||
expires off;
|
||||
|
||||
types {
|
||||
application/dash+xml mpd;
|
||||
application/vnd.apple.mpegurl m3u8;
|
||||
video/mp2t ts;
|
||||
image/jpeg jpg;
|
||||
}
|
||||
|
||||
root /tmp;
|
||||
}
|
||||
|
||||
location /clips/ {
|
||||
|
||||
types {
|
||||
video/mp4 mp4;
|
||||
image/jpeg jpg;
|
||||
}
|
||||
|
||||
autoindex on;
|
||||
root /media/frigate;
|
||||
}
|
||||
|
||||
location /cache/ {
|
||||
internal; # This tells nginx it's not accessible from the outside
|
||||
alias /tmp/cache/;
|
||||
}
|
||||
|
||||
location /recordings/ {
|
||||
types {
|
||||
video/mp4 mp4;
|
||||
}
|
||||
|
||||
autoindex on;
|
||||
autoindex_format json;
|
||||
root /media/frigate;
|
||||
}
|
||||
|
||||
location /exports/ {
|
||||
types {
|
||||
video/mp4 mp4;
|
||||
}
|
||||
|
||||
autoindex on;
|
||||
autoindex_format json;
|
||||
root /media/frigate;
|
||||
}
|
||||
|
||||
location /ws {
|
||||
proxy_pass http://mqtt_ws/;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /live/jsmpeg/ {
|
||||
proxy_pass http://jsmpeg/;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /live/mse/ {
|
||||
proxy_pass http://go2rtc/;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /live/webrtc/ {
|
||||
proxy_pass http://go2rtc/;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location ~* /api/go2rtc([/]?.*)$ {
|
||||
proxy_pass http://go2rtc;
|
||||
rewrite ^/api/go2rtc(.*)$ /api$1 break;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location ~* /api/.*\.(jpg|jpeg|png)$ {
|
||||
rewrite ^/api/(.*)$ $1 break;
|
||||
proxy_pass http://frigate_api;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
add_header Cache-Control "no-store";
|
||||
expires off;
|
||||
proxy_pass http://frigate_api/;
|
||||
include proxy.conf;
|
||||
|
||||
location /api/stats {
|
||||
access_log off;
|
||||
rewrite ^/api/(.*)$ $1 break;
|
||||
proxy_pass http://frigate_api;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /api/version {
|
||||
access_log off;
|
||||
rewrite ^/api/(.*)$ $1 break;
|
||||
proxy_pass http://frigate_api;
|
||||
include proxy.conf;
|
||||
}
|
||||
}
|
||||
|
||||
location / {
|
||||
add_header Cache-Control "no-store";
|
||||
expires off;
|
||||
|
||||
location /assets/ {
|
||||
access_log off;
|
||||
expires 1y;
|
||||
add_header Cache-Control "public";
|
||||
}
|
||||
|
||||
sub_filter 'href="/BASE_PATH/' 'href="$http_x_ingress_path/';
|
||||
sub_filter 'url(/BASE_PATH/' 'url($http_x_ingress_path/';
|
||||
sub_filter '"/BASE_PATH/dist/' '"$http_x_ingress_path/dist/';
|
||||
sub_filter '"/BASE_PATH/js/' '"$http_x_ingress_path/js/';
|
||||
sub_filter '"/BASE_PATH/assets/' '"$http_x_ingress_path/assets/';
|
||||
sub_filter '"/BASE_PATH/monacoeditorwork/' '"$http_x_ingress_path/assets/';
|
||||
sub_filter 'return"/BASE_PATH/"' 'return window.baseUrl';
|
||||
sub_filter '<body>' '<body><script>window.baseUrl="$http_x_ingress_path/";</script>';
|
||||
sub_filter_types text/css application/javascript;
|
||||
sub_filter_once off;
|
||||
|
||||
root /opt/frigate/web;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rtmp {
|
||||
server {
|
||||
listen 1935;
|
||||
chunk_size 4096;
|
||||
allow publish 127.0.0.1;
|
||||
deny publish all;
|
||||
allow play all;
|
||||
application live {
|
||||
live on;
|
||||
record off;
|
||||
meta copy;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user