From a0d292bb1981638c345d6084d26e17666ab94e3a Mon Sep 17 00:00:00 2001 From: MrDrache333 Date: Fri, 26 Apr 2024 13:55:27 +0200 Subject: [PATCH 1/5] Added Docker-Support --- .../ISSUE_TEMPLATE/-add--feature-request.md | 20 + .github/ISSUE_TEMPLATE/-bug--.md | 30 + .github/workflows/build.yml | 62 ++ .gitignore | 10 + Dockerfile | 32 + LICENSE | 674 ++++++++++++++++++ README.md | 89 +++ SourceCodePro-Regular.ttf | Bin 0 -> 210312 bytes docker-compose.yml | 21 + haproxy.cfg | 34 + webcam.py | 599 ++++++++++++++++ webcam@.service | 12 + 12 files changed, 1583 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/-add--feature-request.md create mode 100644 .github/ISSUE_TEMPLATE/-bug--.md create mode 100644 .github/workflows/build.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 LICENSE create mode 100644 README.md create mode 100644 SourceCodePro-Regular.ttf create mode 100644 docker-compose.yml create mode 100644 haproxy.cfg create mode 100755 webcam.py create mode 100644 webcam@.service diff --git a/.github/ISSUE_TEMPLATE/-add--feature-request.md b/.github/ISSUE_TEMPLATE/-add--feature-request.md new file mode 100644 index 0000000..ad18475 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/-add--feature-request.md @@ -0,0 +1,20 @@ +--- +name: "[ADD] Feature request" +about: Suggest an idea for this project +title: "[ADD] " +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**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. diff --git a/.github/ISSUE_TEMPLATE/-bug--.md b/.github/ISSUE_TEMPLATE/-bug--.md new file mode 100644 index 0000000..756f46f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/-bug--.md @@ -0,0 +1,30 @@ +--- +name: "[BUG] " +about: Create a report to help us improve +title: "[BUG] " +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: + +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Environment** + +**Additional context** +Add any other context about the problem here. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..cb58c74 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,62 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +# GitHub recommends pinning actions to a commit SHA. +# To get a newer version, you will need to update the SHA. +# You can also reference a tag or branch, but the action may change without warning. + +name: Create and publish Docker image + +on: + push: + branches: [ 'latest' ] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + environment: production + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Log in to the Container registry + uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@master + with: + platforms: all + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@master + + - name: Build and push Docker image + uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + with: + builder: ${{ steps.buildx.outputs.name }} + context: . + platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v8 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c9cdb8a --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.pyc +*.swp +.idea +*.iml +build +dist +*.egg* +.DS_Store +*.zip +._* diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6f073c4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +FROM python:3.9-slim + +WORKDIR /app + +# Klonen des neuesten Codes aus dem GitHub Repository +RUN apt-get update \ + && apt-get install -y git \ + && git clone -b bambu https://github.com/synman/webcamd.git /app \ + && apt-get purge -y --auto-remove git \ + && rm -rf /var/lib/apt/lists/* + +# Installieren der benötigten Python-Bibliothek +RUN pip install pillow + +# Expose the default port for the HTTP server +EXPOSE 8080 + +# Verwendung eines Inline-Shell-Skripts zur kontrollierten Übergabe von Umgebungsvariablen +CMD exec python webcam.py \ + --hostname "${HOSTNAME:-localhost}" \ + $( [ -n "${PASSWORD}" ] && echo "--password ${PASSWORD}" ) \ + $( [ -n "${WIDTH}" ] && echo "--width ${WIDTH}" ) \ + $( [ -n "${HEIGHT}" ] && echo "--height ${HEIGHT}" ) \ + $( [ -n "${IPV}" ] && echo "--ipv ${IPV}" ) \ + $( [ -n "${V4BINDADDRESS}" ] && echo "--v4bindaddress ${V4BINDADDRESS}" ) \ + $( [ -n "${V6BINDADDRESS}" ] && echo "--v6bindaddress ${V6BINDADDRESS}" ) \ + $( [ -n "${PORT}" ] && echo "--port ${PORT}" ) \ + $( [ -n "${ENCODEWAIT}" ] && echo "--encodewait ${ENCODEWAIT}" ) \ + $( [ -n "${STREAMWAIT}" ] && echo "--streamwait ${STREAMWAIT}" ) \ + $( [ -n "${ROTATE}" ] && echo "--rotate ${ROTATE}" ) \ + $( [ -n "${SHOWFPS}" ] && echo "--showfps" ) \ + $( [ -n "${LOGHTTP}" ] && echo "--loghttp" ) \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..932b6bf --- /dev/null +++ b/README.md @@ -0,0 +1,89 @@ +# webcamd - A High Performance (for python) MPJEG HTTP Server + +## Now supports Bambu printers + +The most notable component is webcam.py. It is a minimalist drop-in replacement +for mjpg-streamer, written in python. It can also be completely decoupled from OctoPrint and used in your own custom environment. + +webcam.py is based on Igor Maculan’s “Simple Python Motion Jpeg” daemon (https://gist.github.com/n3wtron/4624820). It has been reworked to run under python-3.x, accept command-line tunables, IPv6 support, and so forth. + +webcam@.service is a systemd unit file for webcam.py. + +haproxy.cfg is a configuration file for haproxy that actually works with non-ancient versions of haproxy, and enforces SSL connections to Octoprint. + +In addition to Christopher RYU's baseline additions, this version of webcamd has been significanly reworked to run as a multi-threaded MJPEG encoder (using pillow), and Python's multi-threaded HTTP server. + +Bambu Printer support is based on proof of concept work found in bambulab/BambuStudio#1536 (comment) that were later optimized in [pybambu](https://github.com/greghesp/pybambu). + +## Dependencies +``` +pip install pillow +``` +## Command Line Options +``` +webcam.py - A High Performance MJPEG HTTP Server + +options: + -h, --help show this help message and exit + --hostname HOSTNAME Bambu Printer IP address / hostname + --password PASSWORD Bambu Printer Access Code + --width WIDTH Web camera pixel width (default 1920) + --height HEIGHT Web camera pixel height (default 1080) + --ipv IPV IP version (default=4) + --v4bindaddress V4BINDADDRESS + IPv4 HTTP bind address (default '0.0.0.0') + --v6bindaddress V6BINDADDRESS + IPv6 HTTP bind address (default '::') + --port PORT HTTP bind port (default 8080) + --encodewait ENCODEWAIT + not used + --streamwait STREAMWAIT + not used - is set dynamically + --rotate ROTATE rotate captured image 1-359 in degrees - (default no rotation) + --showfps periodically show encoding / streaming frame rate (default false) + --loghttp enable http server logging (default false) +``` +## Useful Information +Specify `/?stream` to stream, `/?snapshot` for a picture, or `/?info` for statistics and configuration information. + +You can rotate the encoded image for all clients using the `--rotate` command line option (adds overhead at the encoder) and/or you can also specify on a per stream basis with the `&rotate=` querystring option (`/?stream&rotate=#` or `/?snapshot&rotate=#`) which offloads the rotation to the client session thread. + +`/?info` produces a json document that shows various information about the state of the encoder and active streams, as well as the active configuration. +``` +{ + stats: { + server: "qbp-webcam:8080", + encodeFps: 19, + sessionCount: 1, + avgStreamFps: 18.4, + sessions: { + 10.151.51.244:41578: 18.4 + }, + snapshots: 0 + }, + config: { + width: 1280, + height: 720, + index: 0, + ipv: 4, + v4bindaddress: "0.0.0.0", + v6bindaddress: "::", + port: 8080, + encodewait: 0.01, + streamwait: 0.01, + rotate: -1, + showfps: false, + loghttp: false + } +} +``` +Statistics and `--showfps` logging update every 5 seconds. + +### Note: +--showfps has been modified to embed a watermark on mjpeg streams and snapshots. This, along with rotation, greatly impacts encoding and stream performance, but it is nice addition if you're okay with a +/- 10 FPS framerate when running on a SoC such as the pi zero2. + +Screenshot 2022-12-28 at 1 35 02 PM + +Screenshot 2024-01-10 at 3 46 52 AM + + diff --git a/SourceCodePro-Regular.ttf b/SourceCodePro-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..10c73d7d901cf0dfa8ba03e45e3271d466291520 GIT binary patch literal 210312 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 f?M*tey>)(nozl;T#iwzOj$&_u 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 +# +# Fixes by Christopher RYU +# Major refactor and threading optimizations by Shell Shrader +# +# Bambu Printer Camera Streaming - SMS - Jan 2024 +# +import os +import sys +import io +import time +import datetime +# import signal +import threading +import traceback +import socket +import argparse +import json + +import struct +import ssl + +from http.server import BaseHTTPRequestHandler, HTTPServer +from socketserver import ThreadingMixIn +from urllib.parse import urlparse, parse_qs +from PIL import ImageFont, ImageDraw, Image +from io import BytesIO + +exitCode = os.EX_OK +myargs = None +webserver = None +lastImage = None +encoderLock = None +encodeFps = 0.0 +streamFps = {} +snapshots = 0 + +class WebRequestHandler(BaseHTTPRequestHandler): + def do_GET(self): + global exitCode + global myargs + global streamFps + global snapshots + + if self.path.lower().startswith("/?snapshot"): + snapshots = snapshots + 1 + qs = parse_qs(urlparse(self.path).query) + if "rotate" in qs: + self.sendSnapshot(rotate=int(qs["rotate"][0])) + return + if myargs.rotate != -1: + self.sendSnapshot(rotate=myargs.rotate) + return + self.sendSnapshot() + return + + if self.path.lower().startswith("/?stream"): + qs = parse_qs(urlparse(self.path).query) + if "encodewait" in qs: + myargs.encodewait = float(qs["encodewait"][0]) + showFps = myargs.showfps + if "showfps" in self.path.lower(): + showFps = True + if "hidefps" in self.path.lower(): + showFps = False + if "rotate" in qs: + self.streamVideo(rotate=int(qs["rotate"][0]), showFps=showFps) + return + if myargs.rotate != -1: + self.streamVideo(rotate=myargs.rotate, showFps=showFps) + return + self.streamVideo(showFps=showFps) + return + + if self.path.lower().startswith("/?info"): + self.send_response(200) + self.send_header("Content-type", "text/json") + self.end_headers() + host = self.headers.get('Host') + + fpssum = 0. + fpsavg = 0. + + for fps in streamFps: + fpssum = fpssum + streamFps[fps] + + if len(streamFps) > 0: + fpsavg = fpssum / len(streamFps) + else: + fpsavg = 0. + + jsonstr = ('{"stats":{"server": "%s", "encodeFps": %.2f, "sessionCount": %d, "avgStreamFps": %.2f, "sessions": %s, "snapshots": %d}, "config": %s}' % (host, self.server.getEncodeFps(), len(streamFps), fpsavg, json.dumps(streamFps) if len(streamFps) > 0 else "{}", snapshots, json.dumps(vars(myargs)))) + self.wfile.write(jsonstr.encode("utf-8")) + return + + if self.path.lower().startswith("/?frame"): + self.send_response(200) + self.send_header("Content-type", "text/html") + self.end_headers() + + self.wfile.write(("webcamd - A High Performance MJPEG HTTP Server
" + + "
").encode("utf-8")) + return + + if self.path.lower().startswith("/?shutdown"): + self.send_response(200) + self.send_header("Content-type", "text/html") + self.end_headers() + + self.wfile.write(("webcamd - A High Performance MJPEG HTTP Server" + + "webcamd is shutting down now!").encode("utf-8")) + + client = ("%s:%d" % (self.client_address[0], self.client_address[1])) + print(f"{datetime.datetime.now()}: shutdown requested by {client}", flush=True) + + exitCode = os.EX_TEMPFAIL + self.server.die() + self.server.unlockEncoder() + return + + self.send_response(404) + self.send_header("Content-type", "text/html") + self.end_headers() + host = self.headers.get('Host') + self.wfile.write(( + "webcamd - A High Performance MJPEG HTTP ServerSpecify /?frame to host a stream in an object, /?stream to stream, /?snapshot for a picture, or /?info for statistics and configuration information").encode("utf-8")) + + def log_message(self, format, *args): + global myargs + if not myargs.loghttp: return + print(f"{datetime.datetime.now()}: {self.client_address[0]} {format % args}", flush=True) + + + def streamVideo(self, rotate=-1, showFps = False): + global myargs + global streamFps + + try: + if self.server.getImage() is None: + self.send_response(200) + self.send_header("Content-type", "text/html") + self.end_headers() + self.wfile.write(( + "webcamd - A High Performance MJPEG HTTP Server" + + "Loading MJPEG Stream . . .").encode("utf-8")) + return + self.send_response(200) + self.send_header("Content-type", "multipart/x-mixed-replace; boundary=boundarydonotcross") + self.end_headers() + except Exception as e: + print("%s: error in stream header %s: [%s]" % (datetime.datetime.now(), streamKey, e), flush=True) + return + + frames = 0 + self.server.addSession() + streamKey = ("%s:%d" % (socket.getnameinfo((self.client_address[0], 0), 0)[0], self.client_address[1])) + + fpsFont = ImageFont.truetype("SourceCodePro-Regular.ttf", 14) + fmA, fmD = fpsFont.getmetrics() + fmD = fmD * -1 + + startTime = time.time() + primed = False + addBreaks = False + + showRed = False + + while not self is None and not self.server is None and self.server.isRunning(): + if time.time() > startTime + 5: + streamFps[streamKey] = frames / 5. + # if showfps: print("%s: streaming @ %.2f FPS to %s - wait time %.5f" % (datetime.datetime.now(), streamFps[streamKey], streamKey, myargs.streamwait), flush=True) + frames = 0 + startTime = time.time() + primed = True + + jpg = self.server.getImage() + + if rotate != -1: jpg = jpg.rotate(rotate) + + if showFps and primed: + draw = ImageDraw.Draw(jpg) + + message = f"{streamKey}\n{datetime.datetime.now()}\nEncode: {round(self.server.getEncodeFps(), 1)} FPS" + + if streamKey in streamFps: + fpssum = 0. + fpsavg = 0. + for fps in streamFps: + fpssum = fpssum + streamFps[fps] + fpsavg = fpssum / len(streamFps) + message = message + f"\nStreams: {len(streamFps)} @ {round(streamFps[streamKey], 1)} FPS" + + bbox = draw.textbbox((0, fmD), message, font=fpsFont) + draw.rectangle(bbox, fill="black") + draw.text((0, fmD), message, font=fpsFont) + + if myargs.flashred and showRed: + draw = ImageDraw.Draw(jpg) + bbox = (1910 - 48, 10, 1910, 48 + 10) + draw.ellipse(bbox, fill="#82221A", outline="#631710", width=3) + bbox = (1910 - 48 + 12, 10 + 12, 1910 - 12, 48 + 10 - 12) + draw.ellipse(bbox, fill="#E34234", outline="#AF3025", width=8) + + showRed = not showRed + + try: + tmpFile = BytesIO() + jpg.save(tmpFile, format="JPEG") + + if not addBreaks: + self.wfile.write(b"--boundarydonotcross\r\n") + addBreaks = True + else: + self.wfile.write(b"\r\n--boundarydonotcross\r\n") + + self.send_header("Content-type", "image/jpeg") + self.send_header("Content-length", str(tmpFile.getbuffer().nbytes)) + self.send_header("X-Timestamp", "0.000000") + self.end_headers() + + self.wfile.write(tmpFile.getvalue()) + + time.sleep(myargs.streamwait) + frames = frames + 1 + except Exception as e: + # ignore broken pipes & connection reset + if e.args[0] not in (32, 104): print(f"{datetime.datetime.now()}: error in stream {streamKey}:: [{e}]", flush=True) + break + + if streamKey in streamFps: streamFps.pop(streamKey) + self.server.dropSession() + + def sendSnapshot(self, rotate=-1): + try: + jpg = self.server.getImage() + + if jpg is None: + self.send_error(425, "Too Early", "The server is not yet ready to serve requests. Please try again momentarily.") + return + + self.server.addSession() + + if rotate != -1: jpg = jpg.rotate(rotate) + fpsFont = ImageFont.truetype("SourceCodePro-Regular.ttf", 14) + fmA, fmD = fpsFont.getmetrics() + fmD = fmD * -1 + + draw = ImageDraw.Draw(jpg) + + message = f"{socket.getnameinfo((self.client_address[0], 0), 0)[0]}\n{datetime.datetime.now()}" + + bbox = draw.textbbox((0, fmD), message, font=fpsFont) + draw.rectangle(bbox, fill="black") + draw.text((0, fmD), message, font=fpsFont) + + tmpFile = BytesIO() + jpg.save(tmpFile, "JPEG") + + self.send_response(200) + self.send_header("Content-type", "image/jpeg") + self.send_header("Content-length", str(len(tmpFile.getvalue()))) + self.end_headers() + + self.wfile.write(tmpFile.getvalue()) + except Exception as e: + print(f"{datetime.datetime.now()}: error in snapshot: [{e}]", flush=True) + + self.server.dropSession() + +def web_server_thread(): + global exitCode + global myargs + global webserver + global encoderLock + global encodeFps + + try: + if myargs.ipv == 4: + webserver = ThreadingHTTPServer((myargs.v4bindaddress, myargs.port), WebRequestHandler) + else: + webserver = ThreadingHTTPServerV6((myargs.v6bindaddress, myargs.port), WebRequestHandler) + + print(f"{datetime.datetime.now()}: web server started", flush=True) + webserver.serve_forever() + except Exception as e: + exitCode = os.EX_SOFTWARE + print(f"{datetime.datetime.now()}: web server error: [{e}]" , flush=True) + + print(f"{datetime.datetime.now()}: web server thread died", flush=True) + +class ThreadingHTTPServer(ThreadingMixIn, HTTPServer): + running = True + sessions = 0 + + def __init__(self, mixin, server): + global encoderLock + encoderLock.acquire() + super().__init__(mixin, server) + + def getImage(self): + global lastImage + if not lastImage is None: + return lastImage.copy() + else: + return None + + def die(self): + super().shutdown() + self.running = False + def isRunning(self): + return self.running + def addSession(self): + global encoderLock + if self.sessions == 0 and encoderLock.locked(): encoderLock.release() + self.sessions = self.sessions + 1 + def dropSession(self): + global encoderLock + global encodeFps + global streamFps + self.sessions = self.sessions - 1 + if self.sessions == 0 and not encoderLock.locked(): + encoderLock.acquire() + encodeFps = 0.0 + streamFps = {} + def unlockEncoder(self): + global encoderLock + if encoderLock.locked(): encoderLock.release() + def getSessions(self): + return self.sessions + def getEncodeFps(self): + global encodeFps + return encodeFps + +class ThreadingHTTPServerV6(ThreadingHTTPServer): + address_family = socket.AF_INET6 + +def main(): + global exitCode + global myargs + global webserver + global lastImage + global encoderLock + global encodeFps + + # signal.signal(signal.SIGTERM, exit_gracefully) + + # set_start_method('fork') + + parseArgs() + + encoderLock = threading.Lock() + threading.Thread(target=web_server_thread).start() + # Process(target=web_server_thread).start() + + # wait for our webserver to start + while webserver is None and exitCode == os.EX_OK: + time.sleep(.01) + + frames = 0 + startTime = time.time() + + username = 'bblp' + access_code = myargs.password + hostname = myargs.hostname + port = 6000 + + MAX_CONNECT_ATTEMPTS = 3 + MAX_READ_TIMEOUTS = 10 + + auth_data = bytearray() + connect_attempts = 0 + read_timeouts = 0 + + auth_data += struct.pack(" startTime + 5: + encodeFps = frames / 5. + if encodeFps <= 0: encodeFps = 1 + myargs.streamwait = 1 / encodeFps + # if myargs.showfps: print("%s: encoding @ %.2f FPS - wait time %.5f" % (datetime.datetime.now(), encodeFps, myargs.encodewait), flush=True) + frames = 0 + startTime = time.time() + # dr = 0 + + try: + dr = sslSock.recv(read_chunk_size) + except (TimeoutError, ssl.SSLWantReadError) as e: + time.sleep(1) + # print(f"{datetime.datetime.now()}: socket read timeout", flush=True) + read_timeouts = read_timeouts + 1 + continue + + if img is not None and len(dr) > 0: + img += dr + if len(img) > payload_size: + print(f"{datetime.datetime.now()}: We got more data than we expected", flush=True) + img = None + elif len(img) == payload_size: + # We should have the full image now. + if img[:4] != jpeg_start: + print(f"{datetime.datetime.now()}: JPEG start magic bytes missing", flush=True) + elif img[-2:] != jpeg_end: + print(f"{datetime.datetime.now()}: JPEG end magic bytes missing", flush=True) + else: + read_timeouts = 0 + lastImage = Image.open(io.BytesIO(img)).convert('RGB') + frames = frames + 1.0 + if encoderLock.locked(): + encoderLock.acquire() + encoderLock.release() + # Reset buffer + img = None + time.sleep(myargs.encodewait) + # else: + # Otherwise we need to continue looping without reseting the buffer to receive the remaining data + # and without delaying. + + elif len(dr) == 16: + # We got the header bytes. Get the expected payload size from it and create the image buffer bytearray. + # Reset connect_attempts now we know the connect was successful. + connect_attempts = 0 + img = bytearray() + payload_size = int.from_bytes(dr[0:3], byteorder='little') + + elif len(dr) == 0: + # This occurs if the wrong access code was provided. + # LOGGER.error(f"{self._client._device.info.device_type}: Chamber image connection rejected by the printer. Check provided access code and IP address.") + # Sleep for a short while and then re-attempt the connection. + time.sleep(1) + print(f"{datetime.datetime.now()}: no data received - possible invalid access code provided", flush=True) + read_timeouts = read_timeouts + 1 + continue + + else: + # print("unexpected error") + # time.sleep(1) + # raise Exception("unknown error occurred") + print(f"{datetime.datetime.now()}: unknown error occurred", flush=True) + + # except KeyboardInterrupt: + # print(f"{datetime.datetime.now()}: shutdown requested", flush=True) + # sslSock.shutdown(socket.SHUT_RDWR) + # break + + except ConnectionResetError: + print(f"{datetime.datetime.now()}: Connection Reset", flush=True) + + except Exception as e: + print(f"{datetime.datetime.now()}: {traceback.format_exc()}", flush=True) + exitCode = os.EX_TEMPFAIL + break + + if not webserver is None and webserver.isRunning(): + print(f"{datetime.datetime.now()}: web server shutting down", flush=True) + webserver.die() + + time.sleep(1) + + print(f"{datetime.datetime.now()}: ExitCode={exitCode} - Goodbye!", flush=True) + sys.exit(exitCode) + + +def parseArgs(): + global myargs + + parser = argparse.ArgumentParser( + description="webcam.py - A High Performance MJPEG HTTP Server" + ) + parser.add_argument( + "--hostname", + type=str, + required=True, + help="Bambu Printer IP address / hostname" + ) + parser.add_argument( + "--password", + type=str, + required=True, + help="Bambu Printer Access Code" + ) + parser.add_argument( + "--width", + type=int, + default=1920, + help="web camera pixel width (default 1920)" + ) + parser.add_argument( + "--height", + type=int, + default=1080, + help="web camera pixel height (default 1080)", + ) + + parser.add_argument("--ipv", type=int, default=4, help="IP version (default=4)") + + parser.add_argument( + "--v4bindaddress", + type=str, + default="0.0.0.0", + help="IPv4 HTTP bind address (default '0.0.0.0')", + ) + parser.add_argument( + "--v6bindaddress", + type=str, + default="::", + help="IPv6 HTTP bind address (default '::')", + ) + parser.add_argument( + "--port", type=int, default=8080, help="HTTP bind port (default 8080)" + ) + parser.add_argument( + "--encodewait", type=float, default=.5, help="seconds to pause between capturing encoded frames (default .5)" + ) + parser.add_argument( + "--streamwait", type=float, default=.01, help="not used - is set dynamically based on measured encoding fps" + ) + parser.add_argument( + "--rotate", type=int, default=-1, help="rotate captured image 1-359 in degrees - (default no rotation)" + ) + parser.add_argument('--flashred', action='store_true', help="show a red dot in the upper right corner of the stream every other frame (default false)") + parser.add_argument('--showfps', action='store_true', help="periodically show encoding / streaming frame rate (default false)") + parser.add_argument('--loghttp', action='store_true', help="enable http server logging (default false)") + + myargs = parser.parse_args() + +# def exit_gracefully(signum, frame): +# global webserver + +# if not webserver is None and webserver.isRunning(): +# print(f"{datetime.datetime.now()}: web server shutting down", flush=True) +# webserver.shutdown() + +# raise KeyboardInterrupt() + +if __name__ == "__main__": + main() diff --git a/webcam@.service b/webcam@.service new file mode 100644 index 0000000..f1db5fa --- /dev/null +++ b/webcam@.service @@ -0,0 +1,12 @@ +[Unit] +Description=Octoprint camera daemon +After=multi-user.target +Wants=multi-user.target + +[Service] +Type=simple +ExecStart=/usr/local/bin/webcam.py --index %I +User=octoprint + +[Install] +Alias=multi-user.target.wants/webcam@%i.service From 5a2ef443ca0adc7555dd64307bcc9faffe56dbcd Mon Sep 17 00:00:00 2001 From: MrDrache333 Date: Fri, 26 Apr 2024 18:46:04 +0200 Subject: [PATCH 2/5] Update dockerfile for building pillow --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6f073c4..5042698 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,12 +4,13 @@ WORKDIR /app # Klonen des neuesten Codes aus dem GitHub Repository RUN apt-get update \ - && apt-get install -y git \ + && apt-get install -y git libjpeg-dev zlib1g-dev gcc \ && git clone -b bambu https://github.com/synman/webcamd.git /app \ && apt-get purge -y --auto-remove git \ && rm -rf /var/lib/apt/lists/* # Installieren der benötigten Python-Bibliothek +RUN pip install --upgrade pip RUN pip install pillow # Expose the default port for the HTTP server From 184efd2968a3d3b225d683480ccde6e45fcb7338 Mon Sep 17 00:00:00 2001 From: MrDrache333 Date: Fri, 26 Apr 2024 18:49:50 +0200 Subject: [PATCH 3/5] Update dockerfile for building pillow --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index ce926df..e567088 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.8' +version: '3.5' services: webcam: From 817092507f7cdc003c89a6ac1bd235099824b8f6 Mon Sep 17 00:00:00 2001 From: Keno Date: Sun, 28 Apr 2024 13:10:59 +0200 Subject: [PATCH 4/5] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 932b6bf..b388fa9 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,12 @@ In addition to Christopher RYU's baseline additio Bambu Printer support is based on proof of concept work found in bambulab/BambuStudio#1536 (comment) that were later optimized in [pybambu](https://github.com/greghesp/pybambu). +## Docker installation +1. Clone this repository `git clone -b bambu https://github.com/MrDrache333/webcamd` +2. Change Environment Parameters in `docker-compose.yml` +3. Start up the Container with `docker-compose up -d` + + ## Dependencies ``` pip install pillow From 843c99ae4817ac51b951cd1e37c0a7df6f1748f2 Mon Sep 17 00:00:00 2001 From: Keno Date: Tue, 30 Apr 2024 11:29:35 +0200 Subject: [PATCH 5/5] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cb58c74..e044475 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,7 @@ name: Create and publish Docker image on: push: - branches: [ 'latest' ] + branches: [ 'bambu' ] env: REGISTRY: ghcr.io