diff --git a/Documents/Pictures/Google_Colab.svg b/Documents/Pictures/Google_Colab.svg new file mode 100644 index 0000000..bb55120 --- /dev/null +++ b/Documents/Pictures/Google_Colab.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/License.txt b/License.txt new file mode 100644 index 0000000..cea59bb --- /dev/null +++ b/License.txt @@ -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. + + Google Colaboratory Notebooks + Copyright (C) 2024 kubinka0505 + + 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: + + colab-notebooks Copyright (C) 2024 kubinka0505 + 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 +. \ No newline at end of file diff --git a/Notebooks/AI/Audio/Generate/AudioCraft.ipynb b/Notebooks/AI/Audio/Generate/AudioCraft.ipynb new file mode 100644 index 0000000..c5b2237 --- /dev/null +++ b/Notebooks/AI/Audio/Generate/AudioCraft.ipynb @@ -0,0 +1,178 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "Music Generation - AudioCraft", + "collapsed_sections": [ + "pcKlg7MAdaBl" + ], + "provenance": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + }, + "accelerator": "GPU", + "gpuClass": "standard" + }, + "cells": [ + { + "cell_type": "markdown", + "source": [ + " ๐ŸŽถ **Music Generation** โž• **- *AudioCraft***" + ], + "metadata": { + "id": "SV_zN6b_8UK9" + } + }, + { + "cell_type": "code", + "metadata": { + "cellView": "form", + "id": "WO1EH3sEbcdM" + }, + "source": [ + "#@title # **1.** Install requirements. ๐Ÿ“ฅ\n", + "#@markdown - Modules\n", + "#@markdown - [**`AudioCraft`**](https://github.com/facebookresearch/audiocraft) - Audio generation model ๐ŸŽถ\n", + "\n", + "from tensorflow import config\n", + "GPU = config.list_physical_devices(\"GPU\")\n", + "GPU = GPU[0].device_type == \"GPU\" if GPU else 0\n", + "\n", + "if not GPU:\n", + "\traise SystemExit(\"GPU unavailable!\\nThe continuation is pointless.\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "print('Installing dependencies for \"AudioCraft\"...')\n", + "!pip install -U git+https://github.com/facebookresearch/audiocraft#egg=audiocraft --quiet --exists-action i | grep -v \"already\"\n", + "\n", + "import torch, torchaudio\n", + "from audiocraft.models import musicgen\n", + "from audiocraft.utils.notebook import display_audio" + ] + }, + { + "cell_type": "code", + "source": [ + "#@title # **2.** Configure. โš™๏ธ\n", + "Model_Name = \"Medium\" #@param [\"Small\", \"Medium\", \"Melody\", \"Large\"]\n", + "Model_Name = Model_Name.lower()\n", + "\n", + "#@markdown Notices:\n", + "#@markdown - ### โ›” **Can't be less than `2` prompts. (RAM failure)**\n", + "#@markdown - ### ๐Ÿ™Š **Unable to generate realistic vocals**.\n", + "#@markdown - ### ๐Ÿ‡ฌ๐Ÿ‡ง Has been trained with **English descriptions and will not** perform as well in other languages.\n", + "#@markdown - ### ๐ŸŽถ Does not perform **equally well for all music styles and cultures**.\n", + "#@markdown - ๐Ÿ“‰ **Sometimes generates end of songs, collapsing to silence**.\n", + "#@markdown - ๐Ÿคทโ€โ™‚๏ธ It is sometimes difficult to assess what types of text descriptions provide the best generations.
Prompt engineering may be required to obtain satisfying results.\n", + "\n", + "if not \"musicgen\" in locals():\n", + "\traise SystemExit(\"Requirements were not installed!\\nPlease run the first cell.\")\n", + "\n", + "Model = musicgen.MusicGen.get_pretrained(Model_Name, device = \"cuda\")" + ], + "metadata": { + "cellView": "form", + "id": "jY8jPyEncCWs" + } + }, + { + "cell_type": "markdown", + "source": [ + "# **3.** Generate. ๐ŸŽถ\n", + "### โ„น๏ธ For good quality results, **provide as much details as possible.**" + ], + "metadata": { + "id": "pcKlg7MAdaBl" + } + }, + { + "cell_type": "markdown", + "source": [ + "## Text to audio ๐Ÿ“" + ], + "metadata": { + "id": "Qh52G6fBdlCz" + } + }, + { + "cell_type": "code", + "source": [ + "#@markdown ## Audio Prompts ๐Ÿ“\n", + "#@markdown Can be empty.\n", + "Description_1 = \"Crazy EDM, heavy bang\" #@param {\"type\": \"string\"}\n", + "Description_2 = \"Classic Reggae track with an electronic guitar solo\" #@param {\"type\": \"string\"}\n", + "Description_3 = \"LoFi electro chill with organic samples\" #@param {\"type\": \"string\"}\n", + "Description_4 = \"Rock with saturated guitars, a heavy bass line and crazy drum break and fills\" #@param {\"type\": \"string\"}\n", + "Description_5 = \"Earthy tones, environmentally conscious, ukulele-infused, harmonic, breezy, easygoing, organic instrumentation, gentle grooves\" #@param {\"type\": \"string\"}\n", + "Remove_Duplicated_Descriptions = False #@param {\"type\": \"boolean\"}\n", + "\n", + "#@markdown
\n", + "\n", + "#@markdown ## Generation parameters\n", + "#@markdown #### **For developers only!**\n", + "Use_ArgMax_Decoding = False #@param {type: \"boolean\"}\n", + "Top_P = 250 #@param {type: \"slider\", min: 100, max: 500.0, step: 1}\n", + "Top_K = 0.0 #@param {type: \"slider\", min: 0.0, max: 10.0, step: 0.1}\n", + "SoftMax_Temperature = 1.0 #@param {type: \"slider\", min: 1.0, max: 10.0, step: 0.1}\n", + "CFG_Coefficient = 3.0 #@param {type: \"slider\", min: 1.0, max: 10.0, step: 0.1}\n", + "Use_2_CFG = False #@param {type: \"boolean\"}\n", + "\n", + "#@markdown
\n", + "\n", + "#@markdown ## Music related settings\n", + "#@markdown Experimental, do not rely.\n", + "BPM = 135 #@param {type: \"slider\", min: 60, max: 170, step: 1}\n", + "BPM = f\"{BPM} BPM\", f\"{BPM} Beats Per Minute\"\n", + "Time_Signature = \"4/4\" #@param [\"3/4\", \"3/8\", \"4/4\", \"6/8\"]\n", + "Time_Signature = f\"{Time_Signature} Time Signature\"\n", + "Duration_Seconds = 25 #@param {type: \"slider\", min: 1.0, max: 60.0, step: 0.1}\n", + "Target_Key_Note = \"None\" #@param [\"C\", \"Cโ™ฏ (Dโ™ญ)\", \"D\", \"Dโ™ฏ (Eโ™ญ)\", \"E\", \"F\", \"Fโ™ฏ (Gโ™ญ)\", \"G\", \"Gโ™ฏ (Aโ™ญ)\", \"A\", \"Aโ™ฏ (Bโ™ญ)\", \"B\", \"None\"]\n", + "Target_Key_Mode = \"Major\" #@param [\"Major\", \"Minor\", \"Dorian\", \"Phyrgian\", \"Mixolydian\"]\n", + "if Target_Key_Note == \"None\": Target_Key_Note = \"\"\n", + "Target_Key = \"in {0} {1} key scale\".format(Target_Key_Note, Target_Key_Mode)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "if not \"Model\" in locals():\n", + "\traise SystemExit(\"Model was not downloaded!\\nPlease run the previous cell.\")\n", + "\n", + "Descriptions_ = Description_1, Description_2, Description_3, Description_4, Description_5\n", + "Descriptions = [\", \".join((Prompt.strip(), *BPM, Time_Signature, Target_Key)) for Prompt in Descriptions_ if Prompt]\n", + "\n", + "if Remove_Duplicated_Descriptions:\n", + "\tDescriptions = list(set(Descriptions))\n", + "if len(Descriptions) < 2:\n", + "\traise SystemExit(\"Amount of prompts have to be > 1.\")\n", + "\n", + "Model.set_generation_params(\n", + "\t0 if Use_ArgMax_Decoding else 1,\n", + "\tTop_K, Top_P, SoftMax_Temperature,\n", + "\tDuration_Seconds, CFG_Coefficient, Use_2_CFG\n", + ")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "print(\"Final prompts:\")\n", + "print(\"\\t\" + \"\\n\\t\".join(Descriptions))\n", + "print(\"\\n\" + \"โ”\" * 64 + \"\\n\")\n", + "\n", + "try:\n", + "\tResult = Model.generate(Descriptions, progress = 1)\n", + "\tdisplay_audio(Result, 32E3)\n", + "except KeyboardInterrupt:\n", + "\traise SystemExit(\"Cancelled.\")" + ], + "metadata": { + "cellView": "form", + "id": "r19GIsZNdmO0" + } + } + ] +} \ No newline at end of file diff --git a/Notebooks/AI/Audio/Separate/Drumsep.ipynb b/Notebooks/AI/Audio/Separate/Drumsep.ipynb new file mode 100644 index 0000000..87b09e1 --- /dev/null +++ b/Notebooks/AI/Audio/Separate/Drumsep.ipynb @@ -0,0 +1,1002 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "Drumsep", + "provenance": [], + "collapsed_sections": [ + "ev8do1kvRssq", + "XfDlrVA9Qc1x" + ] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# **Drumsep ๐Ÿฅโž—**\n", + "\n", + "> โ„น๏ธ Using `drums` stems separated with [AI models with $SDR \\ge 11$](https://mvsep.com/quality_checker/multisong_leaderboard?sort=drums) is strongly advised as their separation may result more *reliable* files.\n", + "\n", + "


\n", + "\n", + "### Features:\n", + "- URL support ๐Ÿ”—\n", + "- ***Fullband preservation*** ๐Ÿ”ฐ\n", + "- Appriopriate file naming ๐Ÿ‡ฌ๐Ÿ‡ง\n", + "- Configurable `shifts` and `overlap` parameters โš™๏ธ\n", + "- Configuration presets ๐Ÿ“\n", + "\n", + "


\n", + "\n", + "" + ], + "metadata": { + "id": "ClKsgqBbTAWs" + } + }, + { + "cell_type": "markdown", + "source": [ + "#
**1.** Re/install requirements ๐Ÿ“ฅ
" + ], + "metadata": { + "id": "ev8do1kvRssq" + } + }, + { + "cell_type": "code", + "source": [ + "#@markdown > โ„น๏ธ Runtime does not need to be restarted.\n", + "import os\n", + "import time\n", + "import torch\n", + "import locale\n", + "import warnings\n", + "from time import time\n", + "from pathlib import Path\n", + "from shutil import rmtree\n", + "from gdown import download\n", + "from zipfile import ZipFile\n", + "from datetime import timedelta\n", + "from rich import print as rprint\n", + "from mimetypes import guess_type\n", + "from requests import Session, utils\n", + "\n", + "try:\n", + "\tfrom google.colab import files, runtime\n", + "\tis_colab = True\n", + "except ImportError:\n", + "\tis_colab = False\n", + "\n", + "GPU = torch.cuda.device_count()\n", + "warnings.filterwarnings(\"ignore\")\n", + "locale.getpreferredencoding = lambda: \"UTF-8\"\n", + "\n", + "#-=-=-=-#\n", + "# Metadata\n", + "\n", + "__title__ = \"Drumsep\"\n", + "__author__ = \"kubinka0505\"\n", + "__date__ = \"17th November 2023\"\n", + "__title__ = __title__.replace(\" \", \"_\")\n", + "\n", + "#-=-=-=-#\n", + "# Modules & packages\n", + "\n", + "requirements = {\n", + "\t\"modules\": [\"mutagen\", \"demucs\"],\n", + "\t\"packages\": [\"sox\"]\n", + "}\n", + "\n", + "if GPU:\n", + "\tGPU_Name = torch.cuda.get_device_name(torch.cuda.current_device())\n", + "\trprint(\"[b #00CC00]GPU Available![/] [#A0A0A0]({0})[/]\".format(GPU_Name))\n", + "else:\n", + "\trprint(\"[#FFCC00][b]GPU Unavailable!\\n[/]Processing may be slower.[/]\")\n", + "\n", + "try:\n", + "\t__modules = requirements[\"modules\"]\n", + "\t__packages = requirements[\"packages\"]\n", + "\n", + "\tif __modules:\n", + "\t\tfor Name in __modules:\n", + "\t\t\t!pip uninstall {Name} -y -q | grep -v \"WARNING: Skip\"\n", + "\t\t\t!pip install -U {Name} --progress-bar off | grep -v \"already\"\n", + "\t\t\tif all((len(__modules) > 1, Name != __modules[-1])):\n", + "\t\t\t\tprint()\n", + "\n", + "\tif __packages:\n", + "\t\tfor Name in __packages:\n", + "\t\t\t!apt-get install --reinstall {Name} -qq > /dev/null 2 >&1\n", + "\t\t\tif all((len(__packages) > 1, Name != __packages[-1])):\n", + "\t\t\t\tprint()\n", + "\n", + "\tfrom mutagen import File as mFile\n", + "\n", + "\t#-=-=-=-#\n", + "\t# Requests\n", + "\n", + "\tsession = Session()\n", + "\tsession.headers.update(\n", + "\t\t{\n", + "\t\t\t\"User-Agent\":\n", + "\t\t\t\"Mozilla/5.0 (Windows NT 10.0; Win32; x32) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36\"\n", + "\t\t}\n", + "\t)\n", + "\n", + "\t#-=-=-=-#\n", + "\t# Functions\n", + "\n", + "\tdef fdb_size(obj: str, extended_units: bool = False, bits: bool = False, recursive: bool = False) -> str:\n", + "\t\t\"\"\"\n", + "\t\tArgs:\n", + "\t\t\tobj: Bytes integer or string path of existing file or directory.\n", + "\t\t\textended_units: Extends the unit of the result, i.e. \"Megabytes\" instead of \"MB\".\n", + "\t\t\tbits: Uses decimal divider (1000) instead of binary one. (1024)\n", + "\t\t\trecursive: Iterate subdirectories, applicable only if `obj` is directory. (slow!)\n", + "\n", + "\t\tReturns:\n", + "\t\t\tHuman-readable files size string.\n", + "\t\t\"\"\"\n", + "\t\t# Setup\n", + "\n", + "\t\tif bits:\n", + "\t\t\tBits = 1000\n", + "\t\t\tBits_Display_Single = \"bit\"\n", + "\t\t\tBits_Display_Multiple = \"bits\"\n", + "\t\telse:\n", + "\t\t\tBits = 1024\n", + "\t\t\tBits_Display_Single = \"byte\"\n", + "\t\t\tBits_Display_Multiple = \"bytes\"\n", + "\n", + "\t\tUnits = {\n", + "\t\t\t\"\":\t \"\",\n", + "\t\t\t\"K\": \"kilo\",\n", + "\t\t\t\"M\": \"mega\",\n", + "\t\t\t\"G\": \"giga\",\n", + "\t\t\t\"T\": \"tera\",\n", + "\t\t\t\"P\": \"peta\",\n", + "\t\t\t\"E\": \"exa\",\n", + "\t\t\t\"Z\": \"zetta\",\n", + "\t\t\t\"Y\": \"yotta\",\n", + "\t\t\t\"R\": \"ronna\",\n", + "\t\t\t\"Q\": \"quetta\"\n", + "\t\t}\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Search for files\n", + "\n", + "\t\tif isinstance(obj, str):\n", + "\t\t\tpath = str(Path(obj).resolve())\n", + "\n", + "\t\t\tif not os.path.exists(path):\n", + "\t\t\t\traise FileNotFoundError(path)\n", + "\n", + "\t\t\tif os.path.isfile(obj):\n", + "\t\t\t\tFiles = [obj]\n", + "\t\t\telse:\n", + "\t\t\t\tWildcard = \"*\"\n", + "\t\t\t\tif recursive:\n", + "\t\t\t\t\tWildcard += \"*/*\"\n", + "\t\t\t\tFiles = list(Path(obj).glob(Wildcard))\n", + "\t\t\t\tfor File in Files:\n", + "\t\t\t\t\tFiles[Files.index(File)] = str(File.resolve())\n", + "\n", + "\t\t\tFiles = map(os.path.getsize, Files)\n", + "\t\t\tBytes = sum(Files)\n", + "\t\telse:\n", + "\t\t\tBytes = obj\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Calculate integer\n", + "\n", + "\t\tfor Unit in Units:\n", + "\t\t\tif Bytes < Bits:\n", + "\t\t\t\tbreak\n", + "\t\t\tBytes /= Bits\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Ending conditions\n", + "\n", + "\t\tif extended_units:\n", + "\t\t\tif Bytes == 1:\n", + "\t\t\t\tBits_Display = Bits_Display_Single\n", + "\t\t\telse:\n", + "\t\t\t\tBits_Display = Bits_Display_Multiple\n", + "\t\t\tUnit = (Units[Unit] + Bits_Display).capitalize()\n", + "\t\telse:\n", + "\t\t\tUnit += \"B\"\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Add zero to integer\n", + "\n", + "\t\tif \".\" in str(Bytes):\n", + "\t\t\tBytes = round(Bytes, 2)\n", + "\t\t\tBytes = str(Bytes).split(\".\")\n", + "\t\t\tBytes[1] = Bytes[1][:2]\n", + "\t\t\tBytes[1] = Bytes[1].ljust(2, \"0\")\n", + "\t\t\tBytes = \".\".join(Bytes)\n", + "\n", + "\t\tBytes = str(Bytes)\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Return string\n", + "\n", + "\t\treturn \" \".join((Bytes, Unit))\n", + "\n", + "\t#-=-=-=-#\n", + "\t# Directories\n", + "\n", + "\tDirectory_Main = os.path.abspath(__title__)\n", + "\tDirectory_Primary = os.path.join(Directory_Main, \"Repository\")\n", + "\tDirectory_Inputs = os.path.join(Directory_Main, \"_Inputs\")\n", + "\tDirectory_Outputs = os.path.join(Directory_Main, \"_Outputs\")\n", + "except (KeyboardInterrupt, EOFError):\n", + "\tprint(\"\\n\" + \"โ”€\" * 32 + \"\\n\" + \"Operation cancelled by user.\")" + ], + "metadata": { + "cellView": "form", + "id": "KMDmKAQ8i7ji" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Repository & model ๐Ÿค–๐Ÿ—ƒ๏ธ
\n", + "Name = \"Base (1S79T3XlPFosbhXgVO8h3GeBJSu43Sk-O)\" #@param [\"Base (1S79T3XlPFosbhXgVO8h3GeBJSu43Sk-O)\"]\n", + "Model = Name.split()[-1].strip(\"(\").strip(\")\")\n", + "\n", + "#@markdown > โš ๏ธ **Running this cell will remove the existing cloned repository without warning!**\n", + "\n", + "if \"os\" not in locals():\n", + "\traise SystemExit(\"Requirements were not installed!\\nPlease run the first cell.\")\n", + "\n", + "#-=-=-=-#\n", + "# Download repository\n", + "\n", + "if os.path.exists(Directory_Primary):\n", + "\trmtree(Directory_Primary)\n", + "\n", + "!git clone https://github.com/inagoy/drumsep {Directory_Primary}\n", + "\n", + "# Download model\n", + "print(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "\n", + "for Directory_Models in [os.path.join(Directory_Primary, \"models\")]:\n", + "\tos.makedirs(Directory_Models, exist_ok = True)\n", + "\tdownload(id = Model, output = os.path.join(Directory_Models, \"drumsep.th\"))\n", + "\n", + "#-=-=-=-#\n", + "# Directories\n", + "\n", + "for Directory in Directory_Inputs, Directory_Outputs:\n", + "\tos.makedirs(Directory, exist_ok = True)" + ], + "metadata": { + "id": "N7PL79HlNQPa", + "cellView": "form" + } + }, + { + "cell_type": "markdown", + "source": [ + "#
**2.** Upload files ๐Ÿ“ค
" + ], + "metadata": { + "id": "hr4D77V3DUl_" + } + }, + { + "cell_type": "code", + "source": [ + "#@markdown > ๐Ÿ—ƒ๏ธ **URL of `ZIP` archive with files is supported.**\n", + "\n", + "Direct_URL = \"\" #@param {type: \"string\"}\n", + "Allow_non_WAV_URL = True #@param {type: \"boolean\"}\n", + "__URL_Fail = False if Direct_URL else True\n", + "\n", + "#@markdown ---\n", + "\n", + "#@markdown > โ„น๏ธ `Lazy Unpacking` determines whether **files from the archive should only be unpacked if their file name extension** is in the `Formats` variable.\n", + "\n", + "Lazy_Unpacking = True #@param {type: \"boolean\"}\n", + "Formats = \"AAC, AIFF, ALAC, APE, FLAC, M4A, MP3, OGG, OPUS, WAV, WV\" #@param {type: \"string\"}\n", + "Formats = [Format.lower().strip() for Format in Formats.split(\",\")]\n", + "\n", + "#@markdown ---\n", + "\n", + "Ask_to_upload_files_if_download_succeeds = True #@param {type: \"boolean\"}\n", + "Remove_previously_uploaded_files_and_subdirectories = True #@param {type: \"boolean\"}\n", + "\n", + "#-=-=-=-#\n", + "\n", + "if \"rmtree\" not in locals():\n", + "\traise SystemExit(\"Requirements were not installed!\\nPlease run the first cell.\")\n", + "\n", + "if \"Files\" not in locals():\n", + "\tFiles = []\n", + "\n", + "#-=-=-=-#\n", + "\n", + "__Directory_Base = os.getcwd()\n", + "\n", + "# `os.chdir` since `files.upload` does not have the target directory argument\n", + "os.chdir(Directory_Inputs)\n", + "\n", + "if Remove_previously_uploaded_files_and_subdirectories:\n", + "\tFiles_Inputs = []\n", + "\tfor File in Path(Directory_Inputs).rglob(\"*\"):\n", + "\t\tFile = str(File.resolve())\n", + "\t\tif is_colab:\n", + "\t\t\tif \".ipynb_checkpoints\" not in os.path.basename(File):\n", + "\t\t\t\tFiles_Inputs.append(File)\n", + "\t\telse:\n", + "\t\t\tFile_Inputs.append(File)\n", + "\n", + "\tfor File in Files_Inputs:\n", + "\t\tif os.path.isfile(File):\n", + "\t\t\tos.remove(File)\n", + "\t\t\trprint('Removed [b #44AAFF]\"{0}\"[/]'.format(\n", + "\t\t\t\tos.path.relpath(File, Directory_Inputs)\n", + "\t\t\t))\n", + "\n", + "\tfor File in Files_Inputs:\n", + "\t\tif os.path.isdir(File):\n", + "\t\t\trmtree(File)\n", + "\n", + "\tif Files_Inputs:\n", + "\t\tprint(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "\n", + "\tFiles = []\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Allowed_Specifiers = \"http\", \"https\", \"ftp\"\n", + "Allowed_Specifiers = [Specifier + \"://\" for Specifier in Allowed_Specifiers]\n", + "Allowed_Specifiers = tuple(Allowed_Specifiers)\n", + "\n", + "if Direct_URL.lower().startswith(Allowed_Specifiers):\n", + "\tfor Delimiter in ((\"?\", \"&\", \"#\")):\n", + "\t\tDownloaded_File_Location = Direct_URL.split(Delimiter)[0]\n", + "\n", + "\tDownloaded_File_Location = utils.unquote(Downloaded_File_Location.split(\"/\")[-1])\n", + "\n", + "\t__URL_Fail = False\n", + "\ttry:\n", + "\t\tSession_obj = session.get(Direct_URL, stream = 1)\n", + "\texcept Exception:\n", + "\t\t__URL_Fail = True\n", + "\n", + "\tif __URL_Fail:\n", + "\t\trprint(\"[b #FF0000]Provided URL is invalid![/]\")\n", + "\t\t__URL_Fail = True\n", + "\n", + "\tif not __URL_Fail:\n", + "\t\twith Session_obj as Site:\n", + "\t\t\tif Site.ok:\n", + "\t\t\t\tSite_MIME = Site.headers[\"content-type\"].lower().split()[0].split(\";\")[0].split(\"/\")\n", + "\t\t\t\tif Site_MIME[0] == \"audio\":\n", + "\t\t\t\t\tif any((Site_MIME[1].endswith(\"wav\"), Allow_non_WAV_URL)):\n", + "\t\t\t\t\t\twith open(Downloaded_File_Location, \"wb\") as File:\n", + "\t\t\t\t\t\t\trprint(f'Downloading [b #00CC00]\"{Downloaded_File_Location}\"[/]...')\n", + "\n", + "\t\t\t\t\t\t\tfor Chunk in Site.iter_content(chunk_size = 1024):\n", + "\t\t\t\t\t\t\t\tif Chunk:\n", + "\t\t\t\t\t\t\t\t\tFile.write(Chunk)\n", + "\t\t\t\t\t\t\tFiles.append(Downloaded_File_Location)\n", + "\t\t\t\t\telse:\n", + "\t\t\t\t\t\trprint(\"[b #FF0000]Permission to download non-WAV files was not granted.[/]\")\n", + "\t\t\t\t\t\t__URL_Fail = True\n", + "\t\t\t\telse:\n", + "\t\t\t\t\t# ZIP Archive Handling\n", + "\t\t\t\t\tif \"/\".join(Site_MIME) == \"application/zip\":\n", + "\t\t\t\t\t\twith open(Downloaded_File_Location, \"wb\") as File:\n", + "\t\t\t\t\t\t\trprint(f'Downloading [b #00CC00]\"{Downloaded_File_Location}\"[/]...')\n", + "\n", + "\t\t\t\t\t\t\tfor Chunk in Site.iter_content(chunk_size = 1024):\n", + "\t\t\t\t\t\t\t\tif Chunk:\n", + "\t\t\t\t\t\t\t\t\tFile.write(Chunk)\n", + "\n", + "\t\t\t\t\t\ttry:\n", + "\t\t\t\t\t\t\tArchive_Files_Amount = 0\n", + "\t\t\t\t\t\t\twith ZipFile(Downloaded_File_Location) as Archive:\n", + "\t\t\t\t\t\t\t\tfor Archive_File in Archive.infolist():\n", + "\t\t\t\t\t\t\t\t\tif Lazy_Unpacking:\n", + "\t\t\t\t\t\t\t\t\t\tif os.path.splitext(Archive_File.filename.lower())[1][1:] in Formats:\n", + "\t\t\t\t\t\t\t\t\t\t\tArchive_Files_Amount += 1\n", + "\t\t\t\t\t\t\t\t\t\t\tArchive.extract(Archive_File)\n", + "\t\t\t\t\t\t\t\t\telse:\n", + "\t\t\t\t\t\t\t\t\t\tArchive_Files_Amount += 1\n", + "\t\t\t\t\t\t\t\t\t\tArchive.extract(Archive_File)\n", + "\n", + "\t\t\t\t\t\t\tos.remove(Downloaded_File_Location)\n", + "\n", + "\t\t\t\t\t\t\t#-=-=-=-#\n", + "\n", + "\t\t\t\t\t\t\tfor File in Path().rglob(\"*.*\"):\n", + "\t\t\t\t\t\t\t\tFile = str(File.resolve())\n", + "\n", + "\t\t\t\t\t\t\t\tif os.path.isfile(File):\n", + "\t\t\t\t\t\t\t\t\tFiles.append(File)\n", + "\n", + "\t\t\t\t\t\t\trprint(f\"[b #00CC00]{Archive_Files_Amount} files from main directory were extracted successfully![/]\")\n", + "\t\t\t\t\t\texcept RuntimeError:\n", + "\t\t\t\t\t\t\trprint(\"[b #FF0000]Files extraction was not successful due to password requirement, file corruption or other internal error.[/]\")\n", + "\t\t\t\t\t\t\t__URL_Fail = True\n", + "\t\t\t\t\telse:\n", + "\t\t\t\t\t\trprint(\"[b #FF0000]Provided URL is not an audio file.[/] [i #A0A0A0](undetected MIME type in header)[/]\")\n", + "\t\t\t\t\t\t__URL_Fail = True\n", + "\t\t\telse:\n", + "\t\t\t\trprint(\"[b #FF0000]Failed to fetch the URL due to {0} status code. ({1})[/]\".format(\n", + "\t\t\t\t\tSite.status_code, Site.reason.title()\n", + "\t\t\t\t))\n", + "\t\t\t\t__URL_Fail = True\n", + "\n", + "#-=-=-=-#\n", + "# Upload files\n", + "\n", + "__Cancel_Permission = \"\" if __URL_Fail else \" [i #A0A0A0](can be cancelled)[/]\"\n", + "\n", + "if any((Ask_to_upload_files_if_download_succeeds, __URL_Fail)):\n", + "\tprint(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "\trprint(f\"Upload [b #44AAFF]AUDIO[/] files{__Cancel_Permission}\")\n", + "\n", + "\ttry:\n", + "\t\tfor File in files.upload():\n", + "\t\t\tFiles.append(File)\n", + "\texcept TypeError:\n", + "\t\tpass\n", + "\texcept (KeyboardInterrupt, EOFError):\n", + "\t\trprint(\"\\n\\n[b #FFCC00]File upload cancelled.[/]\")\n", + "\n", + "\tFiles = [str(Path(File).resolve()) for File in Files]\n", + "\tif is_colab:\n", + "\t\tFiles = [File for File in Files if os.path.basename(File) != \".ipynb_checkpoints\"]\n", + "\tFiles = list(set(Files))\n", + "\n", + "#-=-=-=-#\n", + "# Check for files\n", + "\n", + "Files = [os.path.abspath(File) for File in Files]\n", + "\n", + "err = 0\n", + "try:\n", + "\t# Use this later for string formatting\n", + "\tLongest_File_Name_Length = [File.split(Directory_Inputs)[1][1:] for File in Files]\n", + "\tLongest_File_Name_Length.sort(key = len)\n", + "\tLongest_File_Name_Length = len(Longest_File_Name_Length[-1])\n", + "except IndexError:\n", + "\terr = 1\n", + "\n", + "if err:\n", + "\traise SystemExit(\"No uploaded files has been found.\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "os.chdir(__Directory_Base)" + ], + "metadata": { + "id": "YfL9SPXWv9SJ", + "cellView": "form" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Verify files and convert them to `WAV` โš™๏ธ
\n", + "#@markdown > โš ๏ธ **Files whose [MIME type](https://wikipedia.org/wiki/Media_type)'s first segment will not be detected as `audio` will be removed without warning.**\n", + "if \"Files\" not in locals():\n", + "\traise SystemExit(\"Requirements were not installed!\\nPlease run the first cell.\")\n", + "\n", + "if not Files:\n", + "\traise SystemExit(\"No files has been found!\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Target = \"WAV\"\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Target = Target.split()[0].upper().strip(\".\")\n", + "\n", + "for Input in Files:\n", + "\tInput_Split = os.path.split(os.path.abspath(Input))\n", + "\tInput_Name = Input_Split[1]\n", + "\n", + "\ttry:\n", + "\t\tInput_MIME = mFile(Input).mime\n", + "\texcept AttributeError:\n", + "\t\tInput_MIME = guess_type(Input)\n", + "\tInput_MIME = Input_MIME[0].lower().split(\"/\")\n", + "\n", + "\tif Input_MIME[0] == \"audio\":\n", + "\t\tif Input_MIME[1] != Target.lower():\n", + "\t\t\tos.environ[\"FILE_INPUT\"] = Input\n", + "\t\t\tos.environ[\"FILE_OUTPUT\"] = os.path.splitext(Input)[0] + f\".{Target.lower()}\"\n", + "\n", + "\t\t\trprint(f'[b #00CC00]\"{Input_Name}\" is not a {Target} file, converting...[/]')\n", + "\t\t\t!ffmpeg -y -i \"$FILE_INPUT\" -hide_banner -loglevel 16 \\\n", + "\t\t\t\t-map_metadata 0 -map_metadata 0:s:0 \\\n", + "\t\t\t\t-fflags +bitexact -flags:v +bitexact -flags:a +bitexact \\\n", + "\t\t\t\t\"$FILE_OUTPUT\"\n", + "\n", + "\t\t\tFiles[Files.index(Input)] = os.environ[\"FILE_OUTPUT\"]\n", + "\t\t\tos.remove(Input)\n", + "\telse:\n", + "\t\trprint(f'[b #FF0000]\"{Input_Name}\" is not an audio file, removing[/]')\n", + "\t\tFiles.remove(Input)\n", + "\t\tos.remove(Input)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "if not Files:\n", + "\traise SystemExit(\"No files has been found!\")" + ], + "metadata": { + "cellView": "form", + "id": "k3XKgCi0EWyP" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Change audio files sample rate โš™๏ธ (optional)
\n", + "if \"Files\" not in locals():\n", + "\traise SystemExit(\"Requirements were not installed!\\nPlease run the first cell.\")\n", + "\n", + "if not Files:\n", + "\traise SystemExit(\"No files has been found!\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Value = \"44 100 Hz\" #@param [\"29 400 Hz\", \"32 000 Hz\", \"33 075 Hz\", \"44 100 Hz\"]\n", + "Samplerate = Value.lower().split(\"hz\")[0]\n", + "Samplerate = \"\".join((Character for Character in Samplerate if Character.isdigit()))\n", + "\n", + "#-=-=-=-#\n", + "\n", + "for Input in Files:\n", + "\tInput_Object = mFile(Input)\n", + "\tInput_Name = os.path.basename(Input)\n", + "\tInput_MIME = Input_Object.mime[0].lower().split(\"/\")\n", + "\n", + "\tif Input_Object.info.sample_rate == int(Samplerate):\n", + "\t\tif Input_MIME[1] == \"wav\":\n", + "\t\t\tos.environ[\"FILE_INPUT\"] = Input\n", + "\t\t\tos.environ[\"FILE_OUTPUT\"] = \"_\".join(os.path.splitext(Input))\n", + "\t\t\tos.environ[\"SAMPLE_RATE\"] = Samplerate\n", + "\n", + "\t\t\trprint('[b #00CC00]Changing sample rate of \"{0}\" from {1} to {2}...[/]'.format(\n", + "\t\t\t\tInput_Name, Input_Object.info.sample_rate, Samplerate\n", + "\t\t\t))\n", + "\t\t\t!ffmpeg -y -i \"$FILE_INPUT\" -hide_banner -loglevel 16 \\\n", + "\t\t\t\t-af asetrate=$SAMPLE_RATE -map_metadata 0 -map_metadata 0:s:0 \\\n", + "\t\t\t\t-fflags +bitexact -flags:v +bitexact -flags:a +bitexact \\\n", + "\t\t\t\t\"$FILE_OUTPUT\"\n", + "\n", + "\t\t\tos.remove(Input)\n", + "\t\t\tos.rename(os.environ[\"FILE_OUTPUT\"], Input)\n", + "\t\telse:\n", + "\t\t\trprint(f'[b #FF0000]\"{Input_Name}\" is not a WAV file, sample rate was not changed.[/]')" + ], + "metadata": { + "cellView": "form", + "id": "hh91uhqmPRA4" + } + }, + { + "cell_type": "markdown", + "source": [ + "#
**3.** Separate โž—
" + ], + "metadata": { + "id": "NyA8NMGtDoJn" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Configure ๐Ÿ“
\n", + "#@markdown > *Premade presets. If not `None`, settings below will be overwritten by the preset values.*\n", + "Preset = \"None\" #@param [\"None\", \"kubinka0505 Notebook (01st January 2024) [kubinka0505]\"]\n", + "\n", + "#@markdown ---\n", + "\n", + "Shifts = 10 # @param {type: \"slider\", min: 0, max: 20, step: 1}\n", + "Overlap = 0.75 # @param {type: \"slider\", min: 0.1, max: 0.99, step: 0.01}\n", + "Bit_Depth = \"32-bit\" #@param [\"24-bit\", \"32-bit\"]\n", + "Bit_Depth = int(Bit_Depth.split(\"-\")[0])\n", + "\n", + "#-=-=-=-#\n", + "\n", + "if \"os\" not in locals():\n", + "\traise SystemExit(\"Requirements were not installed!\\nPlease run the first cell.\")\n", + "\n", + "#-=-=-=-#\n", + "# Configure preset\n", + "\n", + "Preset_Display = Preset\n", + "Preset = Preset.lower()\n", + "\n", + "p = {\n", + "\t\"Shifts\": Shifts,\n", + "\t\"Overlap\": Overlap,\n", + "\t\"Bit Depth\": Bit_Depth\n", + "}\n", + "\n", + "if \"kubinka0505\" in Preset:\n", + "\tp[\"Shifts\"] = 10\n", + "\tp[\"Overlap\"] = 0.75\n", + "\tp[\"Bit Depth\"] = 32\n", + "\n", + "p[\"Bit Depth\"] = \"--int24\" if p[\"Bit Depth\"] == 24 else \"--float32\"\n", + "\n", + "#-=-=-=-#\n", + "# Output\n", + "\n", + "Longest_Key_Length = len(sorted(p, key = len)[-1])\n", + "\n", + "if Preset != \"none\":\n", + "\trprint(\"Preset:\", f\"[b i #44AAFF]{Preset_Display}[/]\\n\")\n", + "\n", + "print(\"Settings:\")\n", + "for Key, Value in p.items():\n", + "\tif Value is False:\n", + "\t\tValue = \"\"\n", + "\n", + "\tValue = str(Value)\n", + "\tos.environ[\"_\".join(Key.upper().strip().split())] = Value\n", + "\trprint(\" [i #FFCC00]{0}[/][b #00CC00]{1}[/]\".format(\n", + "\t\tKey.ljust(Longest_Key_Length + 5, \" \"), Value\n", + "\t))" + ], + "metadata": { + "cellView": "form", + "id": "RtyMpqReO5YM" + } + }, + { + "cell_type": "code", + "source": [ + "#@title # **Run** `(10 steps/file)`\n", + "#@markdown > ## โš ๏ธ **Previously processed files will be removed without warning!**\n", + "\n", + "#@markdown ---\n", + "\n", + "Sort_Files_by = \"Upload order ๐Ÿ”ข\" #@param [\"Upload order ๐Ÿ”ข\", \"Duration ๐Ÿ•’\", \"Size โš™๏ธ\"]\n", + "Sort_Files_by = Sort_Files_by.lower()\n", + "Descending = False #@param {type: \"boolean\"}\n", + "\n", + "#-=-=-=-#\n", + "\n", + "if \"demucs\" not in locals():\n", + "\timport demucs\n", + "\n", + "rprint(f\"[b]Demucs version: [#44AAFF]{demucs.__version__}[/][/]\")\n", + "print(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "\n", + "#-=-=-=-#\n", + "# Variables\n", + "\n", + "Directory_Final = os.path.join(Directory_Outputs, \"drumsep\")\n", + "os.environ[\"DIRECTORY_MODEL\"] = Directory_Models\n", + "os.environ[\"NAME_MODEL\"] = os.path.basename(Directory_Final)\n", + "os.environ[\"DIRECTORY_OUTPUTS\"] = Directory_Outputs\n", + "\n", + "#-=-=-=-#\n", + "# Files removal\n", + "\n", + "rmtree(Directory_Final, True)\n", + "\n", + "#-=-=-=-#\n", + "# Sorting files\n", + "\n", + "Files_Sorted = Files\n", + "if \"duration\" in Sort_Files_by:\n", + "\tFiles_Sorted = {File: mFile(File).info.length for File in Files}\n", + "\tFiles_Sorted = sorted(Files_Sorted.items(), key = lambda x: x[1])\n", + "\tFiles_Sorted = list(dict(Files_Sorted))\n", + "if \"size\" in Sort_Files_by:\n", + "\tFiles_Sorted = sorted(Files, key = os.path.getsize)\n", + "\n", + "if Descending:\n", + "\tFiles_Sorted = Files_Sorted[::-1]\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Runtime = time()\n", + "Counter = 1\n", + "\n", + "torch.cuda.empty_cache()\n", + "\n", + "for Input in Files_Sorted:\n", + "\tInput_Object = mFile(Input)\n", + "\tInput_Split = os.path.split(os.path.abspath(Input))\n", + "\n", + "\trprint(\"[b][#44AAFF]{0}.[/] [i]{1} [#A0A0A0]({2}s) ({3})[/][/][/]\".format(\n", + "\t\tstr(Counter).rjust(len(str(len(Files))) + 1, \"0\"),\n", + "\t\tos.path.basename(Input).ljust(Longest_File_Name_Length, \" \"),\n", + "\t\tround(Input_Object.info.length, 3),\n", + "\t\tfdb_size(Input)\n", + "\t))\n", + "\n", + "\tos.environ[\"FILE_INPUT\"] = Input\n", + "\n", + "\ttry:\n", + "\t\t!demucs --repo \"$DIRECTORY_MODEL\" -n \"$NAME_MODEL\" \\\n", + "\t\t\t--shifts=$SHIFTS --overlap=$OVERLAP $BIT_DEPTH \\\n", + "\t\t\t-o \"$DIRECTORY_OUTPUTS\" \"$FILE_INPUT\" | grep -v \"track\"\n", + "\texcept KeyboardInterrupt:\n", + "\t\trprint(\"[b #FFCC00]File processing aborted.[/]\")\n", + "\n", + "\ttorch.cuda.empty_cache()\n", + "\tCounter += 1\n", + "\n", + "\tif all((len(Files) > 1, Input != Files_Sorted[-1])):\n", + "\t\tprint()\n", + "\n", + "#-=-=-=-#\n", + "\n", + "torch.cuda.empty_cache()\n", + "\n", + "__Run_Time = time() - Runtime\n", + "print(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "rprint(\"[b #00CC00]Done![/]\")\n", + "rprint(\"Runtime: [b #44AAFF]{0}[/] [i #A0A0A0](avg. {1} per file)[/]\".format(\n", + "\tstr(timedelta(seconds = __Run_Time))[2:-3],\n", + "\tstr(timedelta(seconds = __Run_Time / len(Files)))[2:-3]\n", + "))" + ], + "metadata": { + "id": "pGJWlVU-C_SY", + "cellView": "form" + } + }, + { + "cell_type": "markdown", + "source": [ + "#
Utils โš™๏ธ
" + ], + "metadata": { + "id": "XfDlrVA9Qc1x" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Rename output files to English ๐Ÿ‡ฌ๐Ÿ‡ง ๐Ÿ”
\n", + "#@markdown - `bombo.wav` โ†’ **`kicks.wav`**\n", + "#@markdown - `redoblante.wav` โ†’ **`snares.wav`**\n", + "#@markdown - `platillos.wav` โ†’ **`hats.wav`**\n", + "#@markdown - `toms.wav` โ†’ **`toms.wav`**\n", + "\n", + "#@markdown ---\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Dictionary = {\n", + "\t\"bombo\": \"kicks\",\n", + "\t\"redoblante\": \"snares\",\n", + "\t\"platillos\": \"hats\",\n", + "\t\"toms\": \"toms\"\n", + "}\n", + "\n", + "if \"os\" not in locals():\n", + "\traise SystemExit(\"Requirements were not installed!\\nPlease run the first cell.\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Files_Outputs = [str(File.resolve()) for File in Path(Directory_Final).rglob(\"*.*\")]\n", + "\n", + "if not Files_Outputs:\n", + "\traise SystemExit(\"No processed files has been found!\")\n", + "\n", + "for File in Files_Outputs:\n", + "\tif os.path.isfile(File):\n", + "\t\tfor Key, Value in Dictionary.items():\n", + "\t\t\ttry:\n", + "\t\t\t\tos.rename(\n", + "\t\t\t\t\tFile,\n", + "\t\t\t\t\tos.path.join(\n", + "\t\t\t\t\t\tos.path.dirname(File),\n", + "\t\t\t\t\t\tos.path.basename(File).replace(Key, Value)\n", + "\t\t\t\t\t)\n", + "\t\t\t\t)\n", + "\t\t\texcept OSError:\n", + "\t\t\t\tpass" + ], + "metadata": { + "cellView": "form", + "id": "16fntZBYQVh8" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Change processed audio files sample rate โš™๏ธ
\n", + "\n", + "Value = \"48 000 Hz\" #@param [\"29 400 Hz\", \"32 000 Hz\", \"33 075 Hz\", \"44 100 Hz\", \"48 000 Hz\", \"96 000 Hz\", \"192 000 Hz\"]\n", + "Samplerate = Value.lower().split(\"hz\")[0]\n", + "Samplerate = \"\".join((Character for Character in Samplerate if Character.isdigit()))\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Files_Final = []\n", + "\n", + "for Input in Path(Directory_Outputs).rglob(\"*\"):\n", + "\tInput = str(Input.resolve())\n", + "\n", + "\tif os.path.isfile(Input):\n", + "\t\tInput_Name = os.path.relpath(Input, Directory_Final)\n", + "\n", + "\t\tos.environ[\"FILE_INPUT\"] = Input\n", + "\t\tos.environ[\"FILE_OUTPUT\"] = \"_\".join(os.path.splitext(Input))\n", + "\t\tos.environ[\"SAMPLERATE\"] = Samplerate\n", + "\n", + "\t\tif mFile(Input).info.sample_rate != int(Samplerate):\n", + "\t\t\trprint('[b #00CC00]Changing sample rate of \"{0}\" from {1} to {2}...[/]'.format(\n", + "\t\t\t\tInput_Name, Input_Object.info.sample_rate, Samplerate\n", + "\t\t\t))\n", + "\t\t\t!ffmpeg -y -i \"$FILE_INPUT\" -hide_banner -loglevel 16 \\\n", + "\t\t\t\t-af asetrate=$SAMPLERATE -map_metadata 0 -map_metadata 0:s:0 \\\n", + "\t\t\t\t-fflags +bitexact -flags:v +bitexact -flags:a +bitexact \\\n", + "\t\t\t\t\"$FILE_OUTPUT\"\n", + "\n", + "\t\t\tos.remove(Input)\n", + "\t\t\tos.rename(os.environ[\"FILE_OUTPUT\"], Input)" + ], + "metadata": { + "cellView": "form", + "id": "y1CyjzaHAdbf" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Convert output files to `FLAC` ๐ŸŽถ
\n", + "\n", + "Bit_Depth = \"24-bit\" #@param [\"16-bit\", \"24-bit\"]\n", + "Bit_Depth = Bit_Depth.split(\"-\")[0]\n", + "Normalize_dB = 1 # @param {type: \"slider\", min: -6, max: 1, step: 1}\n", + "#@markdown > โ„น๏ธ To **disable** normalization, set `Normalize_dB` to **`1`**.\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Target = \"FLAC\"\n", + "Target = Target.split()[0].lower().strip(\".\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "os.environ[\"BIT_DEPTH\"] = \"-b \" + Bit_Depth\n", + "os.environ[\"NORMALIZE\"] = (\"--norm \" + str(Normalize_dB)) if Normalize_dB < 1 else \"\"\n", + "\n", + "for File in Path(Directory_Final).rglob(\"*.*\"):\n", + "\tInput = str(File.resolve())\n", + "\n", + "\tif os.path.isfile(Input):\n", + "\t\tInput_MIME = mFile(Input).mime[0].lower().split(\"/\")\n", + "\t\tInput_Name = os.path.relpath(Input, Directory_Final)\n", + "\n", + "\t\tOutput_FLAC = os.path.splitext(Input)[0], f\".{Target.lower()}\"\n", + "\t\tOutput = \"_\".join(Output_FLAC)\n", + "\n", + "\t\tos.environ[\"FILE_INPUT\"] = Input\n", + "\t\tos.environ[\"FILE_OUTPUT\"] = Output\n", + "\n", + "\t\trprint('[b i]{1}onverting [#44AAFF]\"{0}\"[/] to FLAC...[/]'.format(\n", + "\t\t\tInput_Name,\n", + "\t\t\t(\"rec\" if Input_MIME[1] == \"flac\" else \"c\").capitalize()\n", + "\t\t))\n", + "\n", + "\t\t!sox \"$FILE_INPUT\" -D $BIT_DEPTH -C 8 $NORMALIZE --comment \"\" -G \"$FILE_OUTPUT\" -V0\n", + "\n", + "\t\tos.remove(Input)\n", + "\t\tos.rename(Output, \"\".join(Output_FLAC))" + ], + "metadata": { + "cellView": "form", + "id": "nxkupjCJpf5R" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Download archive with output files ๐Ÿ—ƒ๏ธ
\n", + "Emphasize_Archive_File_Name = True #@param {type: \"boolean\"}\n", + "Beggining = \"!_\" if Emphasize_Archive_File_Name else \"\"\n", + "\n", + "#@markdown > โ„น๏ธ Pushes the archive file to top of the explorer's file list (**if** it's sorted by name) by putting `!_` to its file name beggining.\n", + "\n", + "#-=-=-=-#\n", + "\n", + "__Padding = 7\n", + "Archive_File = Beggining + \"_\".join((__title__, str(time()).split(\".\")[1][:__Padding].rjust(__Padding, \"0\")))\n", + "Archive_File += \".zip\"\n", + "Archive_File = os.path.abspath(Archive_File)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "# Archive Creation\n", + "print(\"Making Archive...\")\n", + "with ZipFile(Archive_File, \"w\", 14, 1, 9) as Archive:\n", + "\tfor File in Path(Directory_Final).rglob(\"*.*\"):\n", + "\t\tFile = str(File.resolve())\n", + "\n", + "\t\tif os.path.isfile(File):\n", + "\t\t\tArcName = os.path.relpath(File, Directory_Final)\n", + "\n", + "\t\t\trprint(f'\\t[b i]Writing [#44AACC]\"{ArcName}\"[/]...')\n", + "\t\t\tArchive.write(File, ArcName)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "files.download(Archive_File)" + ], + "metadata": { + "cellView": "form", + "id": "rpPfi2g7gnTi" + } + }, + { + "cell_type": "code", + "source": [ + "#@title Terminate runtime after specified time ๐Ÿ”Œ\n", + "#@markdown In case if you don't want to waste this account's resources while performing other tasks.\n", + "#@markdown > ### **This cancellable action is irreversible and will result in loss of ALL session data!**\n", + "\n", + "#@markdown
\n", + "#@markdown
\n", + "#@markdown Time sheet\n", + "#@markdown\n", + "#@markdown
\n", + "#@markdown\n", + "#@markdown | Seconds | Minutes |\n", + "#@markdown |:-|:-|\n", + "#@markdown | `60` | `1` |\n", + "#@markdown | `300` | `5` |\n", + "#@markdown | `600` | `10` |\n", + "#@markdown | `1800` | `30` |\n", + "#@markdown | `3600` | `60` |\n", + "#@markdown
\n", + "\n", + "#@markdown ---\n", + "\n", + "Seconds_Default = 30\n", + "Seconds = 300 # @param {type: \"integer\"}\n", + "\n", + "if Seconds < 0:\n", + "\trprint(f\"[b][#FFCC00]Seconds are[/] [#FF0000]< 0[/][#FFCC00], defaulting to[/] [#FF0000]{Seconds_Default}[/][#FFCC00].[/][/]\")\n", + "\n", + "__Spaces = \" \" * 8\n", + "\n", + "\n", + "\n", + "if is_colab:\n", + "\ttry:\n", + "\t\tfor i in range(Seconds, -1, -1):\n", + "\t\t\tprint(\"\\r\", end = f\"Runtime will be terminated in {i} seconds...\" + __Spaces)\n", + "\n", + "\t\trprint(\"\\n\\n[b #FF0000]Runtime has been terminated.[/]\")\n", + "\t\truntime.unassign()\n", + "\texcept (KeyboardInterrupt, EOFError):\n", + "\t\tprint()\n", + "\t\trprint(\"[b #FF0000]Operation cancelled by user.[/]\")\n", + "else:\n", + "\trprint(\"[b #FFCC00]Not in Colab, unsupported.[/]\")" + ], + "metadata": { + "id": "rhKs_AmESZew", + "cellView": "form" + } + } + ] +} \ No newline at end of file diff --git a/Notebooks/AI/Audio/Separate/MDX23C.ipynb b/Notebooks/AI/Audio/Separate/MDX23C.ipynb new file mode 100644 index 0000000..1e598da --- /dev/null +++ b/Notebooks/AI/Audio/Separate/MDX23C.ipynb @@ -0,0 +1,1015 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "MDX23C", + "provenance": [], + "collapsed_sections": [ + "ev8do1kvRssq", + "XfDlrVA9Qc1x" + ], + "gpuType": "T4" + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + }, + "accelerator": "GPU" + }, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# **MDX23C ๐ŸŽถโž—**\n", + "\n", + "> *Adaptation of MVSep-MDX23 algorithm for Colab.*\n", + "\n", + "


\n", + "\n", + "### Features:\n", + "- URL support ๐Ÿ”—\n", + "- ***Fullband preservation*** ๐Ÿ”ฐ\n", + "- Configuration presets ๐Ÿ“\n", + "\n", + "


\n", + "\n", + "" + ], + "metadata": { + "id": "ClKsgqBbTAWs" + } + }, + { + "cell_type": "markdown", + "source": [ + "#
**1.** Re/install requirements ๐Ÿ“ฅ
" + ], + "metadata": { + "id": "ev8do1kvRssq" + } + }, + { + "cell_type": "code", + "source": [ + "#@markdown > โ„น๏ธ Runtime does not need to be restarted.\n", + "import os\n", + "import time\n", + "import torch\n", + "import locale\n", + "import warnings\n", + "from time import time\n", + "from pathlib import Path\n", + "from shutil import rmtree\n", + "from zipfile import ZipFile\n", + "from datetime import timedelta\n", + "from rich import print as rprint\n", + "from mimetypes import guess_type\n", + "from requests import Session, utils\n", + "\n", + "try:\n", + "\tfrom google.colab import files, runtime\n", + "\tis_colab = True\n", + "except ImportError:\n", + "\tis_colab = False\n", + "\n", + "GPU = torch.cuda.device_count()\n", + "warnings.filterwarnings(\"ignore\")\n", + "locale.getpreferredencoding = lambda: \"UTF-8\"\n", + "\n", + "#-=-=-=-#\n", + "# Metadata\n", + "\n", + "__title__ = \"MDX23C\"\n", + "__author__ = \"kubinka0505\"\n", + "__credits__ = \"jarredou\"\n", + "__date__ = \"15th December 2023\"\n", + "__title__ = __title__.replace(\" \", \"_\")\n", + "\n", + "#-=-=-=-#\n", + "# Modules & packages\n", + "\n", + "requirements = {\n", + "\t\"modules\": [\"mutagen\", \"onnxruntime-gpu\"],\n", + "\t\"packages\": [\"sox\"]\n", + "}\n", + "\n", + "if GPU:\n", + "\tGPU_Name = torch.cuda.get_device_name(torch.cuda.current_device())\n", + "\trprint(\"[b #00CC00]GPU Available![/] [#A0A0A0]({0})[/]\".format(GPU_Name))\n", + "else:\n", + "\trprint(\"[#FF0000][b]GPU Unavailable!\\n[/]Processing will be impossible - requirements will not be installed.[/]\")\n", + "\traise SystemExit()\n", + "\n", + "print(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "\n", + "try:\n", + "\t__modules = requirements[\"modules\"]\n", + "\t__packages = requirements[\"packages\"]\n", + "\n", + "\tif __modules:\n", + "\t\tfor Name in __modules:\n", + "\t\t\t!pip uninstall {Name} -y -q | grep -v \"WARNING: Skip\"\n", + "\t\t\t!pip install -U {Name} --progress-bar off | grep -v \"already\"\n", + "\t\t\tif all((len(__modules) > 1, Name != __modules[-1])):\n", + "\t\t\t\tprint()\n", + "\n", + "\tif __packages:\n", + "\t\tfor Name in __packages:\n", + "\t\t\t!apt-get install --reinstall {Name} -qq > /dev/null 2 >&1\n", + "\t\t\tif all((len(__packages) > 1, Name != __packages[-1])):\n", + "\t\t\t\tprint()\n", + "\n", + "\tfrom mutagen import File as mFile\n", + "\n", + "\t#-=-=-=-#\n", + "\t# Requests\n", + "\n", + "\tsession = Session()\n", + "\tsession.headers.update(\n", + "\t\t{\n", + "\t\t\t\"User-Agent\":\n", + "\t\t\t\"Mozilla/5.0 (Windows NT 10.0; Win32; x32) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36\"\n", + "\t\t}\n", + "\t)\n", + "\n", + "\t#-=-=-=-#\n", + "\t# Functions\n", + "\n", + "\tdef fdb_size(obj: str, extended_units: bool = False, bits: bool = False, recursive: bool = False) -> str:\n", + "\t\t\"\"\"\n", + "\t\tArgs:\n", + "\t\t\tobj: Bytes integer or string path of existing file or directory.\n", + "\t\t\textended_units: Extends the unit of the result, i.e. \"Megabytes\" instead of \"MB\".\n", + "\t\t\tbits: Uses decimal divider (1000) instead of binary one. (1024)\n", + "\t\t\trecursive: Iterate subdirectories, applicable only if `obj` is directory. (slow!)\n", + "\n", + "\t\tReturns:\n", + "\t\t\tHuman-readable files size string.\n", + "\t\t\"\"\"\n", + "\t\t# Setup\n", + "\n", + "\t\tif bits:\n", + "\t\t\tBits = 1000\n", + "\t\t\tBits_Display_Single = \"bit\"\n", + "\t\t\tBits_Display_Multiple = \"bits\"\n", + "\t\telse:\n", + "\t\t\tBits = 1024\n", + "\t\t\tBits_Display_Single = \"byte\"\n", + "\t\t\tBits_Display_Multiple = \"bytes\"\n", + "\n", + "\t\tUnits = {\n", + "\t\t\t\"\":\t \"\",\n", + "\t\t\t\"K\": \"kilo\",\n", + "\t\t\t\"M\": \"mega\",\n", + "\t\t\t\"G\": \"giga\",\n", + "\t\t\t\"T\": \"tera\",\n", + "\t\t\t\"P\": \"peta\",\n", + "\t\t\t\"E\": \"exa\",\n", + "\t\t\t\"Z\": \"zetta\",\n", + "\t\t\t\"Y\": \"yotta\",\n", + "\t\t\t\"R\": \"ronna\",\n", + "\t\t\t\"Q\": \"quetta\"\n", + "\t\t}\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Search for files\n", + "\n", + "\t\tif isinstance(obj, str):\n", + "\t\t\tpath = str(Path(obj).resolve())\n", + "\n", + "\t\t\tif not os.path.exists(path):\n", + "\t\t\t\traise FileNotFoundError(path)\n", + "\n", + "\t\t\tif os.path.isfile(obj):\n", + "\t\t\t\tFiles = [obj]\n", + "\t\t\telse:\n", + "\t\t\t\tWildcard = \"*\"\n", + "\t\t\t\tif recursive:\n", + "\t\t\t\t\tWildcard += \"*/*\"\n", + "\t\t\t\tFiles = list(Path(obj).glob(Wildcard))\n", + "\t\t\t\tfor File in Files:\n", + "\t\t\t\t\tFiles[Files.index(File)] = str(File.resolve())\n", + "\n", + "\t\t\tFiles = map(os.path.getsize, Files)\n", + "\t\t\tBytes = sum(Files)\n", + "\t\telse:\n", + "\t\t\tBytes = obj\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Calculate integer\n", + "\n", + "\t\tfor Unit in Units:\n", + "\t\t\tif Bytes < Bits:\n", + "\t\t\t\tbreak\n", + "\t\t\tBytes /= Bits\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Ending conditions\n", + "\n", + "\t\tif extended_units:\n", + "\t\t\tif Bytes == 1:\n", + "\t\t\t\tBits_Display = Bits_Display_Single\n", + "\t\t\telse:\n", + "\t\t\t\tBits_Display = Bits_Display_Multiple\n", + "\t\t\tUnit = (Units[Unit] + Bits_Display).capitalize()\n", + "\t\telse:\n", + "\t\t\tUnit += \"B\"\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Add zero to integer\n", + "\n", + "\t\tif \".\" in str(Bytes):\n", + "\t\t\tBytes = round(Bytes, 2)\n", + "\t\t\tBytes = str(Bytes).split(\".\")\n", + "\t\t\tBytes[1] = Bytes[1][:2]\n", + "\t\t\tBytes[1] = Bytes[1].ljust(2, \"0\")\n", + "\t\t\tBytes = \".\".join(Bytes)\n", + "\n", + "\t\tBytes = str(Bytes)\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Return string\n", + "\n", + "\t\treturn \" \".join((Bytes, Unit))\n", + "\n", + "\t#-=-=-=-#\n", + "\t# Directories\n", + "\n", + "\tDirectory_Main = os.path.abspath(__title__)\n", + "\tDirectory_Primary = os.path.join(Directory_Main, \"Repository\")\n", + "\tDirectory_Inputs = os.path.join(Directory_Main, \"_Inputs\")\n", + "\tDirectory_Outputs = os.path.join(Directory_Main, \"_Output\")\n", + "except (KeyboardInterrupt, EOFError):\n", + "\tprint(\"\\n\" + \"โ”€\" * 32 + \"\\n\" + \"Operation cancelled by user.\")" + ], + "metadata": { + "id": "KMDmKAQ8i7ji", + "cellView": "form" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Repository ๐Ÿ—ƒ๏ธ
\n", + "#@markdown > โš ๏ธ **Running this cell will remove the existing cloned repository without warning!**\n", + "\n", + "if \"os\" not in locals():\n", + "\traise SystemExit(\"Requirements were not installed!\\nPlease run the first cell.\")\n", + "\n", + "#-=-=-=-#\n", + "# Download repository\n", + "\n", + "if os.path.exists(Directory_Primary):\n", + "\trmtree(Directory_Primary)\n", + "\n", + "!git clone https://github.com/kubinka0505/MVSEP-MDX23-Colab_v2 {__title__}\n", + "\n", + "print(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "\n", + "!pip install -r {Directory_Primary}/requirements.txt --progress-bar off | grep -v \"already\"\n", + "\n", + "#-=-=-=-#\n", + "# Directories\n", + "\n", + "for Directory in Directory_Inputs, Directory_Outputs:\n", + "\tos.makedirs(Directory, exist_ok = True)" + ], + "metadata": { + "id": "N7PL79HlNQPa", + "cellView": "form" + } + }, + { + "cell_type": "markdown", + "source": [ + "#
**2.** Upload files ๐Ÿ“ค
" + ], + "metadata": { + "id": "hr4D77V3DUl_" + } + }, + { + "cell_type": "code", + "source": [ + "#@markdown > ๐Ÿ—ƒ๏ธ **URL of `ZIP` archive with files is supported.**\n", + "\n", + "Direct_URL = \"\" #@param {type: \"string\"}\n", + "Allow_non_WAV_URL = True #@param {type: \"boolean\"}\n", + "__URL_Fail = False if Direct_URL else True\n", + "\n", + "#@markdown ---\n", + "\n", + "#@markdown > โ„น๏ธ `Lazy Unpacking` determines whether **files from the archive should only be unpacked if their file name extension** is in the `Formats` variable.\n", + "\n", + "Lazy_Unpacking = True #@param {type: \"boolean\"}\n", + "Formats = \"AAC, AIFF, ALAC, APE, FLAC, M4A, MP3, OGG, OPUS, WAV, WV\" #@param {type: \"string\"}\n", + "Formats = [Format.lower().strip() for Format in Formats.split(\",\")]\n", + "\n", + "#@markdown ---\n", + "\n", + "Ask_to_upload_files_if_download_succeeds = True #@param {type: \"boolean\"}\n", + "Remove_previously_uploaded_files_and_subdirectories = True #@param {type: \"boolean\"}\n", + "\n", + "#-=-=-=-#\n", + "\n", + "if \"rmtree\" not in locals():\n", + "\traise SystemExit(\"Requirements were not installed!\\nPlease run the first cell.\")\n", + "\n", + "if \"Files\" not in locals():\n", + "\tFiles = []\n", + "\n", + "#-=-=-=-#\n", + "\n", + "__Directory_Base = os.getcwd()\n", + "\n", + "# `os.chdir` since `files.upload` does not have the target directory argument\n", + "os.chdir(Directory_Inputs)\n", + "\n", + "if Remove_previously_uploaded_files_and_subdirectories:\n", + "\tFiles_Inputs = []\n", + "\tfor File in Path(Directory_Inputs).rglob(\"*\"):\n", + "\t\tFile = str(File.resolve())\n", + "\t\tif is_colab:\n", + "\t\t\tif \".ipynb_checkpoints\" not in os.path.basename(File):\n", + "\t\t\t\tFiles_Inputs.append(File)\n", + "\t\telse:\n", + "\t\t\tFile_Inputs.append(File)\n", + "\n", + "\tfor File in Files_Inputs:\n", + "\t\tif os.path.isfile(File):\n", + "\t\t\tos.remove(File)\n", + "\t\t\trprint('Removed [b #44AAFF]\"{0}\"[/]'.format(\n", + "\t\t\t\tos.path.relpath(File, Directory_Inputs)\n", + "\t\t\t))\n", + "\n", + "\tfor File in Files_Inputs:\n", + "\t\tif os.path.isdir(File):\n", + "\t\t\trmtree(File)\n", + "\n", + "\tif Files_Inputs:\n", + "\t\tprint(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "\n", + "\tFiles = []\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Allowed_Specifiers = \"http\", \"https\", \"ftp\"\n", + "Allowed_Specifiers = [Specifier + \"://\" for Specifier in Allowed_Specifiers]\n", + "Allowed_Specifiers = tuple(Allowed_Specifiers)\n", + "\n", + "if Direct_URL.lower().startswith(Allowed_Specifiers):\n", + "\tfor Delimiter in ((\"?\", \"&\", \"#\")):\n", + "\t\tDownloaded_File_Location = Direct_URL.split(Delimiter)[0]\n", + "\n", + "\tDownloaded_File_Location = utils.unquote(Downloaded_File_Location.split(\"/\")[-1])\n", + "\n", + "\t__URL_Fail = False\n", + "\ttry:\n", + "\t\tSession_obj = session.get(Direct_URL, stream = 1)\n", + "\texcept Exception:\n", + "\t\t__URL_Fail = True\n", + "\n", + "\tif __URL_Fail:\n", + "\t\trprint(\"[b #FF0000]Provided URL is invalid![/]\")\n", + "\t\t__URL_Fail = True\n", + "\n", + "\tif not __URL_Fail:\n", + "\t\twith Session_obj as Site:\n", + "\t\t\tif Site.ok:\n", + "\t\t\t\tSite_MIME = Site.headers[\"content-type\"].lower().split()[0].split(\";\")[0].split(\"/\")\n", + "\t\t\t\tif Site_MIME[0] == \"audio\":\n", + "\t\t\t\t\tif any((Site_MIME[1].endswith(\"wav\"), Allow_non_WAV_URL)):\n", + "\t\t\t\t\t\twith open(Downloaded_File_Location, \"wb\") as File:\n", + "\t\t\t\t\t\t\trprint(f'Downloading [b #00CC00]\"{Downloaded_File_Location}\"[/]...')\n", + "\n", + "\t\t\t\t\t\t\tfor Chunk in Site.iter_content(chunk_size = 1024):\n", + "\t\t\t\t\t\t\t\tif Chunk:\n", + "\t\t\t\t\t\t\t\t\tFile.write(Chunk)\n", + "\t\t\t\t\t\t\tFiles.append(Downloaded_File_Location)\n", + "\t\t\t\t\telse:\n", + "\t\t\t\t\t\trprint(\"[b #FF0000]Permission to download non-WAV files was not granted.[/]\")\n", + "\t\t\t\t\t\t__URL_Fail = True\n", + "\t\t\t\telse:\n", + "\t\t\t\t\t# ZIP Archive Handling\n", + "\t\t\t\t\tif \"/\".join(Site_MIME) == \"application/zip\":\n", + "\t\t\t\t\t\twith open(Downloaded_File_Location, \"wb\") as File:\n", + "\t\t\t\t\t\t\trprint(f'Downloading [b #00CC00]\"{Downloaded_File_Location}\"[/]...')\n", + "\n", + "\t\t\t\t\t\t\tfor Chunk in Site.iter_content(chunk_size = 1024):\n", + "\t\t\t\t\t\t\t\tif Chunk:\n", + "\t\t\t\t\t\t\t\t\tFile.write(Chunk)\n", + "\n", + "\t\t\t\t\t\ttry:\n", + "\t\t\t\t\t\t\tArchive_Files_Amount = 0\n", + "\t\t\t\t\t\t\twith ZipFile(Downloaded_File_Location) as Archive:\n", + "\t\t\t\t\t\t\t\tfor Archive_File in Archive.infolist():\n", + "\t\t\t\t\t\t\t\t\tif Lazy_Unpacking:\n", + "\t\t\t\t\t\t\t\t\t\tif os.path.splitext(Archive_File.filename.lower())[1][1:] in Formats:\n", + "\t\t\t\t\t\t\t\t\t\t\tArchive_Files_Amount += 1\n", + "\t\t\t\t\t\t\t\t\t\t\tArchive.extract(Archive_File)\n", + "\t\t\t\t\t\t\t\t\telse:\n", + "\t\t\t\t\t\t\t\t\t\tArchive_Files_Amount += 1\n", + "\t\t\t\t\t\t\t\t\t\tArchive.extract(Archive_File)\n", + "\n", + "\t\t\t\t\t\t\tos.remove(Downloaded_File_Location)\n", + "\n", + "\t\t\t\t\t\t\t#-=-=-=-#\n", + "\n", + "\t\t\t\t\t\t\tfor File in Path().rglob(\"*.*\"):\n", + "\t\t\t\t\t\t\t\tFile = str(File.resolve())\n", + "\n", + "\t\t\t\t\t\t\t\tif os.path.isfile(File):\n", + "\t\t\t\t\t\t\t\t\tFiles.append(File)\n", + "\n", + "\t\t\t\t\t\t\trprint(f\"[b #00CC00]{Archive_Files_Amount} files from main directory were extracted successfully![/]\")\n", + "\t\t\t\t\t\texcept RuntimeError:\n", + "\t\t\t\t\t\t\trprint(\"[b #FF0000]Files extraction was not successful due to password requirement, file corruption or other internal error.[/]\")\n", + "\t\t\t\t\t\t\t__URL_Fail = True\n", + "\t\t\t\t\telse:\n", + "\t\t\t\t\t\trprint(\"[b #FF0000]Provided URL is not an audio file.[/] [i #A0A0A0](undetected MIME type in header)[/]\")\n", + "\t\t\t\t\t\t__URL_Fail = True\n", + "\t\t\telse:\n", + "\t\t\t\trprint(\"[b #FF0000]Failed to fetch the URL due to {0} status code. ({1})[/]\".format(\n", + "\t\t\t\t\tSite.status_code, Site.reason.title()\n", + "\t\t\t\t))\n", + "\t\t\t\t__URL_Fail = True\n", + "\n", + "#-=-=-=-#\n", + "# Upload files\n", + "\n", + "__Cancel_Permission = \"\" if __URL_Fail else \" [i #A0A0A0](can be cancelled)[/]\"\n", + "\n", + "if any((Ask_to_upload_files_if_download_succeeds, __URL_Fail)):\n", + "\tprint(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "\trprint(f\"Upload [b #44AAFF]AUDIO[/] files{__Cancel_Permission}\")\n", + "\n", + "\ttry:\n", + "\t\tfor File in files.upload():\n", + "\t\t\tFiles.append(File)\n", + "\texcept TypeError:\n", + "\t\tpass\n", + "\texcept (KeyboardInterrupt, EOFError):\n", + "\t\trprint(\"\\n\\n[b #FFCC00]File upload cancelled.[/]\")\n", + "\n", + "\tFiles = [str(Path(File).resolve()) for File in Files]\n", + "\tif is_colab:\n", + "\t\tFiles = [File for File in Files if os.path.basename(File) != \".ipynb_checkpoints\"]\n", + "\tFiles = list(set(Files))\n", + "\n", + "#-=-=-=-#\n", + "# Check for files\n", + "\n", + "Files = [os.path.abspath(File) for File in Files]\n", + "\n", + "err = 0\n", + "try:\n", + "\t# Use this later for string formatting\n", + "\tLongest_File_Name_Length = [File.split(Directory_Inputs)[1][1:] for File in Files]\n", + "\tLongest_File_Name_Length.sort(key = len)\n", + "\tLongest_File_Name_Length = len(Longest_File_Name_Length[-1])\n", + "except IndexError:\n", + "\terr = 1\n", + "\n", + "if err:\n", + "\traise SystemExit(\"No uploaded files has been found.\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "os.chdir(__Directory_Base)" + ], + "metadata": { + "id": "YfL9SPXWv9SJ", + "cellView": "form" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Verify files and convert them to `WAV` โš™๏ธ
\n", + "#@markdown > โš ๏ธ **Files whose [MIME type](https://wikipedia.org/wiki/Media_type)'s first segment will not be detected as `audio` will be removed without warning.**\n", + "if \"Files\" not in locals():\n", + "\traise SystemExit(\"Requirements were not installed!\\nPlease run the first cell.\")\n", + "\n", + "if not Files:\n", + "\traise SystemExit(\"No files has been found!\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Target = \"WAV\"\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Target = Target.split()[0].upper().strip(\".\")\n", + "\n", + "for Input in Files:\n", + "\tInput_Split = os.path.split(os.path.abspath(Input))\n", + "\tInput_Name = Input_Split[1]\n", + "\n", + "\ttry:\n", + "\t\tInput_MIME = mFile(Input).mime\n", + "\texcept AttributeError:\n", + "\t\tInput_MIME = guess_type(Input)\n", + "\tInput_MIME = Input_MIME[0].lower().split(\"/\")\n", + "\n", + "\tif Input_MIME[0] == \"audio\":\n", + "\t\tif Input_MIME[1] != Target.lower():\n", + "\t\t\tos.environ[\"FILE_INPUT\"] = Input\n", + "\t\t\tos.environ[\"FILE_OUTPUT\"] = os.path.splitext(Input)[0] + f\".{Target.lower()}\"\n", + "\n", + "\t\t\trprint(f'[b #00CC00]\"{Input_Name}\" is not a {Target} file, converting...[/]')\n", + "\t\t\t!ffmpeg -i \"$FILE_INPUT\" -hide_banner -loglevel 16 \\\n", + "\t\t\t\t-map_metadata 0 -map_metadata 0:s:0 \\\n", + "\t\t\t\t-fflags +bitexact -flags:v +bitexact -flags:a +bitexact \\\n", + "\t\t\t\t\"$FILE_OUTPUT\"\n", + "\n", + "\t\t\tFiles[Files.index(Input)] = os.environ[\"FILE_OUTPUT\"]\n", + "\t\t\tos.remove(Input)\n", + "\telse:\n", + "\t\trprint(f'[b #FF0000]\"{Input_Name}\" is not an audio file, removing[/]')\n", + "\t\tFiles.remove(Input)\n", + "\t\tos.remove(Input)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "if not Files:\n", + "\traise SystemExit(\"No files has been found!\")" + ], + "metadata": { + "cellView": "form", + "id": "k3XKgCi0EWyP" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Change audio files sample rate โš™๏ธ (optional)
\n", + "\n", + "if \"Files\" not in locals():\n", + "\traise SystemExit(\"Requirements were not installed!\\nPlease run the first cell.\")\n", + "\n", + "if not Files:\n", + "\traise SystemExit(\"No files has been found!\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Value = \"44 100 Hz\" #@param [\"29 400 Hz\", \"32 000 Hz\", \"33 075 Hz\", \"44 100 Hz\"]\n", + "Samplerate = Value.lower().split(\"hz\")[0]\n", + "Samplerate = \"\".join((Character for Character in Samplerate if Character.isdigit()))\n", + "\n", + "#-=-=-=-#\n", + "\n", + "for Input in Files:\n", + "\tInput_Object = mFile(Input)\n", + "\tInput_Name = os.path.basename(Input)\n", + "\tInput_MIME = Input_Object.mime[0].lower().split(\"/\")\n", + "\n", + "\tif Input_Object.info.sample_rate > int(Samplerate):\n", + "\t\tif Input_MIME[1] == \"wav\":\n", + "\t\t\tos.environ[\"FILE_INPUT\"] = Input\n", + "\t\t\tos.environ[\"FILE_OUTPUT\"] = \"_\".join(os.path.splitext(Input))\n", + "\t\t\tos.environ[\"SAMPLERATE\"] = Samplerate\n", + "\n", + "\t\t\trprint('[b #00CC00]Changing sample rate of \"{0}\" from {1} to {2}...[/]'.format(\n", + "\t\t\t\tInput_Name, Input_Object.info.sample_rate, Samplerate\n", + "\t\t\t))\n", + "\t\t\t!ffmpeg -i \"$FILE_INPUT\" -hide_banner -loglevel 16 \\\n", + "\t\t\t\t-af asetrate=$SAMPLERATE -map_metadata 0 -map_metadata 0:s:0 \\\n", + "\t\t\t\t-fflags +bitexact -flags:v +bitexact -flags:a +bitexact \\\n", + "\t\t\t\t\"$FILE_OUTPUT\"\n", + "\n", + "\t\t\tos.remove(Input)\n", + "\t\t\tos.rename(os.environ[\"FILE_OUTPUT\"], Input)\n", + "\t\telse:\n", + "\t\t\trprint(f'[b #FF0000]\"{Input_Name}\" is not a WAV file, sample rate was not changed.[/]')" + ], + "metadata": { + "cellView": "form", + "id": "hh91uhqmPRA4" + } + }, + { + "cell_type": "markdown", + "source": [ + "#
**3.** Separate โž—
" + ], + "metadata": { + "id": "NyA8NMGtDoJn" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Configure ๐Ÿ“
\n", + "#@markdown > *Premade presets. If not `None`, settings below will be overwritten by the preset values.*\n", + "Preset = \"None\" #@param [\"None\", \"jarredou Notebook (01st January 2024) [jarredou] [Original]\"]\n", + "\n", + "#@markdown ---\n", + "\n", + "BigShifts = 7 # @param {type: \"slider\", min: 3, max: 11, step: 1}\n", + "Demucs_Overlap = 0.6 #@param {type: \"slider\", min: 0, max: 0.95, step: 0.05}\n", + "Bit_Depth = \"32-bit\" #@param [\"16-bit\", \"32-bit\"]\n", + "Bit_Depth = Bit_Depth.split(\"-\")[0]\n", + "\n", + "#@markdown ---\n", + "\n", + "#@markdown ## `InstVoc` Settings\n", + "\n", + "InstVoc_Overlap = 1 #@param {type: \"slider\", min: 1, max: 40, step: 1}\n", + "InstVoc_Weight = 8 #@param {type: \"slider\", min: 0, max: 10, step: 1}\n", + "\n", + "#@markdown ---\n", + "\n", + "#@markdown ## `VitLarge` Settings\n", + "\n", + "VitLarge_Overlap = 1 #@param {type: \"slider\", min: 1, max: 40, step:1}\n", + "VitLarge_Weight = 5 #@param {type: \"slider\", min: 0, max: 10, step: 1}\n", + "\n", + "#@markdown ---\n", + "\n", + "#@markdown ## `VocFT` Settings\n", + "\n", + "VocFT_Enabled = True #@param {type: \"boolean\"}\n", + "VocFT_Overlap = 0.1 #@param {type: \"slider\", min: 0, max: 0.99, step: 0.01}\n", + "VocFT_Weight = 2 #@param {type: \"slider\", min: 0, max: 10, step: 1}\n", + "\n", + "#-=-=-=-#\n", + "\n", + "if \"os\" not in locals():\n", + "\traise SystemExit(\"Requirements were not installed!\\nPlease run the first cell.\")\\\n", + "\n", + "#-=-=-=-#\n", + "# Configure preset\n", + "\n", + "Preset_Display = Preset\n", + "Preset = Preset.lower()\n", + "\n", + "p = {\n", + "\t\"BigShifts\": BigShifts,\n", + "\t\"Demucs Overlap\": Demucs_Overlap,\n", + "\t\"Bit Depth\": Bit_Depth,\n", + "\t\"InstVoc Overlap\": InstVoc_Overlap,\n", + "\t\"InstVoc Weight\": InstVoc_Weight,\n", + "\t\"VitLarge Overlap\": VitLarge_Overlap,\n", + "\t\"VitLarge Weight\": VitLarge_Weight,\n", + "\t\"VocFT Enabled\": VocFT_Enabled,\n", + "\t\"VocFT Overlap\": VocFT_Overlap,\n", + "\t\"VocFT Weight\": VocFT_Weight\n", + "}\n", + "\n", + "if Preset.endswith(\"[original]\"):\n", + "\tp[\"BigShifts\"] = 7\n", + "\tp[\"Demucs Overlap\"] = 0.6\n", + "\tp[\"Bit Depth\"] = 16\n", + "\tp[\"InstVoc Overlap\"] = 1\n", + "\tp[\"InstVoc Weight\"] = 8\n", + "\tp[\"VitLarge Overlap\"] = 1\n", + "\tp[\"VitLarge Weight\"] = 5\n", + "\tp[\"VocFT Enabled\"] = False\n", + "\tp[\"VocFT Overlap\"] = 0.1\n", + "\tp[\"VocFT Weight\"] = 2\n", + "\n", + "p[\"Bit Depth\"] = \"PCM_16\" if p[\"Bit Depth\"] == 16 else \"FLOAT\"\n", + "p[\"VocFT Enabled\"] = str(p[\"VocFT Enabled\"]).lower()\n", + "\n", + "#-=-=-=-#\n", + "# Output\n", + "\n", + "Longest_Key_Length = len(sorted(p, key = len)[-1])\n", + "\n", + "if Preset != \"none\":\n", + "\trprint(\"Preset:\", f\"[b i #44AAFF]{Preset_Display}[/]\\n\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "print(\"Settings:\")\n", + "for Key, Value in p.items():\n", + "\tif Value is False:\n", + "\t\tValue = \"\"\n", + "\n", + "\tValue = str(Value)\n", + "\tos.environ[\"_\".join(Key.upper().strip().split())] = Value\n", + "\n", + "\trprint(\" [i #FFCC00]{0}[/][b #00CC00]{1}[/]\".format(\n", + "\t\tKey.ljust(Longest_Key_Length + 5, \" \"), Value\n", + "\t))" + ], + "metadata": { + "id": "RtyMpqReO5YM", + "cellView": "form" + } + }, + { + "cell_type": "code", + "source": [ + "#@title #
**Run**
\n", + "#@markdown > ## โš ๏ธ **Previously processed files will be removed without warning!**\n", + "\n", + "#@markdown ---\n", + "\n", + "Sort_Files_by = \"Upload order ๐Ÿ”ข\" #@param [\"Upload order ๐Ÿ”ข\", \"Duration ๐Ÿ•’\", \"Size โš™๏ธ\"]\n", + "Sort_Files_by = Sort_Files_by.lower()\n", + "Descending = False #@param {type: \"boolean\"}\n", + "\n", + "#-=-=-=-#\n", + "\n", + "os.environ[\"DIRECTORY_PRIMARY\"] = Directory_Primary\n", + "\n", + "#-=-=-=-#\n", + "# Files removal\n", + "\n", + "Files_Outputs = []\n", + "\n", + "for File in Path(Directory_Outputs).rglob(\"*\"):\n", + "\tFile = str(File.resolve())\n", + "\tif is_colab:\n", + "\t\tif \".ipynb_checkpoints\" not in os.path.basename(File):\n", + "\t\t\tFiles_Outputs.append(File)\n", + "\telse:\n", + "\t\tFiles_Outputs.append(File)\n", + "\n", + "for File in Files_Outputs:\n", + "\tif os.path.isfile(File):\n", + "\t\tos.remove(File)\n", + "\n", + "for File in Files_Outputs:\n", + "\tif os.path.isdir(File):\n", + "\t\trmtree(File)\n", + "\n", + "#-=-=-=-#\n", + "# Sorting files\n", + "\n", + "Files_Sorted = Files\n", + "if \"duration\" in Sort_Files_by:\n", + "\tFiles_Sorted = {File: mFile(File).info.length for File in Files}\n", + "\tFiles_Sorted = sorted(Files_Sorted.items(), key = lambda x: x[1])\n", + "\tFiles_Sorted = list(dict(Files_Sorted))\n", + "if \"size\" in Sort_Files_by:\n", + "\tFiles_Sorted = sorted(Files, key = os.path.getsize)\n", + "\n", + "if Descending:\n", + "\tFiles_Sorted = Files_Sorted[::-1]\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Runtime = time()\n", + "Counter = 1\n", + "\n", + "torch.cuda.empty_cache()\n", + "\n", + "for Input in Files_Sorted:\n", + "\tInput_Object = mFile(Input)\n", + "\tInput_Split = os.path.split(os.path.abspath(Input))\n", + "\n", + "\trprint(\"[b][#44AAFF]{0}.[/] [i]{1} [#A0A0A0]({2}s) ({3})[/][/][/]\".format(\n", + "\t\tstr(Counter).rjust(len(str(len(Files))) + 1, \"0\"),\n", + "\t\tos.path.basename(Input).ljust(Longest_File_Name_Length, \" \"),\n", + "\t\tround(Input_Object.info.length, 3),\n", + "\t\tfdb_size(Input)\n", + "\t))\n", + "\n", + "\tos.environ[\"FILE_INPUT\"] = Input\n", + "\tos.environ[\"DIRECTORY_OUTPUTS\"] = os.path.join(Directory_Outputs, os.path.basename(Input))\n", + "\n", + "\t!python $DIRECTORY_PRIMARY/inference.py -q \\\n", + "\t\t--input_audio \"$FILE_INPUT\" \\\n", + "\t\t--output_folder \"$DIRECTORY_OUTPUTS\" \\\n", + "\t\t--weight_InstVoc $INSTVOC_WEIGHT \\\n", + "\t\t--weight_VOCFT $VOCFT_WEIGHT \\\n", + "\t\t--weight_VitLarge $VITLARGE_WEIGHT \\\n", + "\t\t--overlap_VOCFT $VOCFT_OVERLAP \\\n", + "\t\t--overlap_InstVoc $INSTVOC_OVERLAP \\\n", + "\t\t--overlap_VitLarge $VITLARGE_OVERLAP \\\n", + "\t\t--overlap_demucs $DEMUCS_OVERLAP \\\n", + "\t\t--BigShifts $BIGSHIFTS \\\n", + "\t\t--output_format $BIT_DEPTH \\\n", + "\t\t--large_gpu --use_VOCFT $VOCFT_ENABLED | grep -v \"created\"\n", + "\n", + "\t# Cleanup\n", + "\tfor File in Path(os.environ[\"DIRECTORY_OUTPUTS\"]).rglob(\"*\"):\n", + "\t\tFile = str(File.resolve())\n", + "\n", + "\t\tos.rename(\n", + "\t\t\tFile,\n", + "\t\t\tos.path.join(\n", + "\t\t\t\tos.path.split(File)[0],\n", + "\t\t\t\tos.path.split(File)[1].split(\"_\")[-1]\n", + "\t\t\t)\n", + "\t\t)\n", + "\n", + "\ttorch.cuda.empty_cache()\n", + "\tCounter += 1\n", + "\n", + "\tif all((len(Files) > 1, Input != Files_Sorted[-1])):\n", + "\t\tprint()\n", + "\n", + "#-=-=-=-#\n", + "\n", + "torch.cuda.empty_cache()\n", + "\n", + "__Run_Time = time() - Runtime\n", + "print(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "rprint(\"[b #00CC00]Done![/]\")\n", + "rprint(\"Runtime: [b #44AAFF]{0}[/] [i #A0A0A0](avg. {1} per file)[/]\".format(\n", + "\tstr(timedelta(seconds = __Run_Time))[2:-3],\n", + "\tstr(timedelta(seconds = __Run_Time / len(Files)))[2:-3]\n", + "))" + ], + "metadata": { + "id": "pGJWlVU-C_SY", + "cellView": "form" + } + }, + { + "cell_type": "markdown", + "source": [ + "#
Utils โš™๏ธ
" + ], + "metadata": { + "id": "XfDlrVA9Qc1x" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Change processed audio files sample rate โš™๏ธ
\n", + "\n", + "Value = \"48 000 Hz\" #@param [\"29 400 Hz\", \"32 000 Hz\", \"33 075 Hz\", \"44 100 Hz\", \"48 000 Hz\", \"96 000 Hz\", \"192 000 Hz\"]\n", + "Samplerate = Value.lower().split(\"hz\")[0]\n", + "Samplerate = \"\".join((Character for Character in Samplerate if Character.isdigit()))\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Files_Final = []\n", + "\n", + "for Input in Path(Directory_Outputs).rglob(\"*\"):\n", + "\tInput = str(Input.resolve())\n", + "\n", + "\tif os.path.isfile(Input):\n", + "\t\tInput_Name = os.path.relpath(Input, Directory_Outputs)\n", + "\n", + "\t\tos.environ[\"FILE_INPUT\"] = Input\n", + "\t\tos.environ[\"FILE_OUTPUT\"] = \"_\".join(os.path.splitext(Input))\n", + "\t\tos.environ[\"SAMPLERATE\"] = Samplerate\n", + "\n", + "\t\tif mFile(Input).info.sample_rate != int(Samplerate):\n", + "\t\t\trprint('[b #00CC00]Changing sample rate of \"{0}\" from {1} to {2}...[/]'.format(\n", + "\t\t\t\tInput_Name, Input_Object.info.sample_rate, Samplerate\n", + "\t\t\t))\n", + "\t\t\t!ffmpeg -y -i \"$FILE_INPUT\" -hide_banner -loglevel 16 \\\n", + "\t\t\t\t-af asetrate=$SAMPLERATE -map_metadata 0 -map_metadata 0:s:0 \\\n", + "\t\t\t\t-fflags +bitexact -flags:v +bitexact -flags:a +bitexact \\\n", + "\t\t\t\t\"$FILE_OUTPUT\"\n", + "\n", + "\t\t\tos.remove(Input)\n", + "\t\t\tos.rename(os.environ[\"FILE_OUTPUT\"], Input)" + ], + "metadata": { + "cellView": "form", + "id": "y1CyjzaHAdbf" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Convert output files to `FLAC` ๐ŸŽถ
\n", + "\n", + "Bit_Depth = \"24-bit\" #@param [\"16-bit\", \"24-bit\"]\n", + "Bit_Depth = Bit_Depth.split(\"-\")[0]\n", + "Normalize_dB = 1 # @param {type: \"slider\", min: -6, max: 1, step: 1}\n", + "#@markdown > โ„น๏ธ To **disable** normalization, set `Normalize_dB` to **`1`**.\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Target = \"FLAC\"\n", + "Target = Target.split()[0].lower().strip(\".\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "os.environ[\"BIT_DEPTH\"] = \"-b \" + Bit_Depth\n", + "os.environ[\"NORMALIZE\"] = (\"--norm \" + str(Normalize_dB)) if Normalize_dB < 1 else \"\"\n", + "\n", + "for File in Path(Directory_Outputs).rglob(\"*.*\"):\n", + "\tInput = str(File.resolve())\n", + "\n", + "\tif os.path.isfile(Input):\n", + "\t\tInput_MIME = mFile(Input).mime[0].lower().split(\"/\")\n", + "\t\tInput_Name = os.path.relpath(Input, Directory_Outputs)\n", + "\n", + "\t\tOutput_FLAC = os.path.splitext(Input)[0], f\".{Target.lower()}\"\n", + "\t\tOutput = \"_\".join(Output_FLAC)\n", + "\n", + "\t\tos.environ[\"INPUT\"] = Input\n", + "\t\tos.environ[\"OUTPUT\"] = Output\n", + "\n", + "\t\trprint('[b i]{1}onverting [#44AAFF]\"{0}\"[/] to FLAC...[/]'.format(\n", + "\t\t\tInput_Name,\n", + "\t\t\t(\"rec\" if Input_MIME[1] == \"flac\" else \"c\").capitalize()\n", + "\t\t))\n", + "\n", + "\t\t!sox \"$INPUT\" -D $BIT_DEPTH -C 8 $NORMALIZE --comment \"\" -G \"$OUTPUT\" -V0\n", + "\n", + "\t\tos.remove(Input)\n", + "\t\tos.rename(Output, \"\".join(Output_FLAC))" + ], + "metadata": { + "cellView": "form", + "id": "nxkupjCJpf5R" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Download archive with output files ๐Ÿ—ƒ๏ธ
\n", + "Emphasize_archive_file_name = True #@param {type: \"boolean\"}\n", + "Beggining = \"!_\" if Emphasize_archive_file_name else \"\"\n", + "\n", + "#@markdown > โ„น๏ธ Pushes the archive file to top of the explorer's file list (**if** it's sorted by name) by putting `!_` to its file name beggining.\n", + "\n", + "#-=-=-=-#\n", + "\n", + "__Padding = 7\n", + "Archive_File = Beggining + \"_\".join((__title__, str(time()).split(\".\")[1][:__Padding].rjust(__Padding, \"0\")))\n", + "Archive_File += \".zip\"\n", + "Archive_File = os.path.abspath(Archive_File)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "# Archive Creation\n", + "print(\"Making Archive...\")\n", + "with ZipFile(Archive_File, \"w\", 14, 1, 9) as Archive:\n", + "\tfor File in Path(Directory_Outputs).rglob(\"*.*\"):\n", + "\t\tFile = str(File.resolve())\n", + "\n", + "\t\tif os.path.isfile(File):\n", + "\t\t\tArcName = os.path.relpath(File, Directory_Outputs)\n", + "\n", + "\t\t\trprint(f'\\t[b i]Writing [#44AACC]\"{ArcName}\"[/]...')\n", + "\t\t\tArchive.write(File, ArcName)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "files.download(Archive_File)" + ], + "metadata": { + "cellView": "form", + "id": "rpPfi2g7gnTi" + } + }, + { + "cell_type": "code", + "source": [ + "#@title Terminate runtime after specified time ๐Ÿ”Œ\n", + "#@markdown In case if you don't want to waste this account's resources while performing other tasks.\n", + "#@markdown > ### **This cancellable action is irreversible and will result in loss of ALL session data!**\n", + "\n", + "#@markdown
\n", + "#@markdown
\n", + "#@markdown Time sheet\n", + "#@markdown\n", + "#@markdown
\n", + "#@markdown\n", + "#@markdown | Seconds | Minutes |\n", + "#@markdown |:-|:-|\n", + "#@markdown | `60` | `1` |\n", + "#@markdown | `300` | `5` |\n", + "#@markdown | `600` | `10` |\n", + "#@markdown | `1800` | `30` |\n", + "#@markdown | `3600` | `60` |\n", + "#@markdown
\n", + "\n", + "#@markdown ---\n", + "\n", + "Seconds_Default = 30\n", + "Seconds = 300 # @param {type: \"integer\"}\n", + "\n", + "if Seconds < 0:\n", + "\trprint(f\"[b][#FFCC00]Seconds are[/] [#FF0000]< 0[/][#FFCC00], defaulting to[/] [#FF0000]{Seconds_Default}[/][#FFCC00].[/][/]\")\n", + "\n", + "__Spaces = \" \" * 8\n", + "\n", + "\n", + "\n", + "if is_colab:\n", + "\ttry:\n", + "\t\tfor i in range(Seconds, -1, -1):\n", + "\t\t\tprint(\"\\r\", end = f\"Runtime will be terminated in {i} seconds...\" + __Spaces)\n", + "\n", + "\t\trprint(\"\\n\\n[b #FF0000]Runtime has been terminated.[/]\")\n", + "\t\truntime.unassign()\n", + "\texcept (KeyboardInterrupt, EOFError):\n", + "\t\tprint()\n", + "\t\trprint(\"[b #FF0000]Operation cancelled by user.[/]\")\n", + "else:\n", + "\trprint(\"[b #FFCC00]Not in Colab, unsupported.[/]\")" + ], + "metadata": { + "id": "rhKs_AmESZew", + "cellView": "form" + } + } + ] +} \ No newline at end of file diff --git a/Notebooks/AI/Audio/Upscale/HiFi_GAN_BWE.ipynb b/Notebooks/AI/Audio/Upscale/HiFi_GAN_BWE.ipynb new file mode 100644 index 0000000..8ed15e7 --- /dev/null +++ b/Notebooks/AI/Audio/Upscale/HiFi_GAN_BWE.ipynb @@ -0,0 +1,929 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "HiFi GAN BWE", + "provenance": [], + "collapsed_sections": [ + "pPR2kVUB1r_1", + "wWMN_sT-ugof", + "XfDlrVA9Qc1x" + ] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# **HiFi GAN BWE ๐Ÿ“ˆโš™๏ธ๐ŸŽถ**\n", + "\n", + "> โš™๏ธ [...] unoffical implementation of the **HiFi-GAN+ model for audio bandwidth extension**, from the paper [โ€œ**B**and**w**idth **E**xtension is All You Needโ€](https://doi.org/10.1109/ICASSP39728.2021.9413575) by Jiaqi Su, Yunyun Wang, Adam Finkelstein, and Zeyu Jin.\n", + "\n", + "> ๐Ÿ“ˆ The model **takes a band-limited audio signal** (usually `8`/`16`/`24`kHz) and **attempts to reconstruct the high frequency components needed to restore a full-band signal at** 48kHz1.\n", + "\n", + "> ๐ŸŽถ This is useful for **upsampling low-rate outputs from upstream tasks like text-to-speech, voice conversion**, etc. or enhancing audio that was filtered to remove high frequency noise.\n", + "\n", + "


\n", + "\n", + "### Features:\n", + "- URL support ๐Ÿ”—\n", + "- **Multiple output target samplerates**1 ๐Ÿ“ˆ\n", + "\n", + "


\n", + "\n", + "" + ], + "metadata": { + "id": "6d9RBy68rV7-" + } + }, + { + "cell_type": "markdown", + "source": [ + "#
**1.** Re/install requirements ๐Ÿ“ฅ
" + ], + "metadata": { + "id": "pPR2kVUB1r_1" + } + }, + { + "cell_type": "code", + "source": [ + "#@markdown > โ„น๏ธ Runtime does not need to be restarted.\n", + "import os\n", + "import time\n", + "import torch\n", + "import locale\n", + "import warnings\n", + "import numpy as np\n", + "from time import time\n", + "from pathlib import Path\n", + "from shutil import rmtree\n", + "from zipfile import ZipFile\n", + "from datetime import timedelta\n", + "from rich import print as rprint\n", + "from mimetypes import guess_type\n", + "from scipy.io.wavfile import write\n", + "from requests import Session, utils\n", + "\n", + "try:\n", + "\tfrom google.colab import files, runtime\n", + "\tis_colab = True\n", + "except ImportError:\n", + "\tis_colab = False\n", + "\n", + "GPU = torch.cuda.device_count()\n", + "warnings.filterwarnings(\"ignore\")\n", + "locale.getpreferredencoding = lambda: \"UTF-8\"\n", + "\n", + "#-=-=-=-#\n", + "# Metadata\n", + "\n", + "__title__ = \"HiFi GAN BWE\"\n", + "__author__ = \"kubinka0505\"\n", + "__date__ = \"04th December 2023\"\n", + "__title__ = __title__.replace(\" \", \"_\")\n", + "\n", + "#-=-=-=-#\n", + "# Modules & packages\n", + "\n", + "requirements = {\n", + "\t\"modules\": [\"mutagen\", \"hifi_gan_bwe\"],\n", + "\t\"packages\": [\"sox\"]\n", + "}\n", + "\n", + "if GPU:\n", + "\tGPU_Name = torch.cuda.get_device_name(torch.cuda.current_device())\n", + "\trprint(\"[b #00CC00]GPU Available![/] [#A0A0A0]({0})[/]\".format(GPU_Name))\n", + "else:\n", + "\trprint(\"[#FFCC00][b]GPU Unavailable!\\n[/]Processing may be slower.[/]\")\n", + "\n", + "print(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "\n", + "try:\n", + "\t__modules = requirements[\"modules\"]\n", + "\t__packages = requirements[\"packages\"]\n", + "\n", + "\tif __modules:\n", + "\t\tfor Name in __modules:\n", + "\t\t\t!pip uninstall {Name} -y -q | grep -v \"WARNING: Skip\"\n", + "\t\t\t!pip install -U {Name} --progress-bar off | grep -v \"already\"\n", + "\t\t\tif all((len(__modules) > 1, Name != __modules[-1])):\n", + "\t\t\t\tprint()\n", + "\n", + "\tif __packages:\n", + "\t\tfor Name in __packages:\n", + "\t\t\t!apt-get install --reinstall {Name} -qq > /dev/null 2 >&1\n", + "\t\t\tif all((len(__packages) > 1, Name != __packages[-1])):\n", + "\t\t\t\tprint()\n", + "\n", + "\timport audioread\n", + "\tfrom mutagen import File as mFile\n", + "\tfrom hifi_gan_bwe import BandwidthExtender\n", + "\n", + "\t#-=-=-=-#\n", + "\t# Requests\n", + "\n", + "\tsession = Session()\n", + "\tsession.headers.update(\n", + "\t\t{\n", + "\t\t\t\"User-Agent\":\n", + "\t\t\t\"Mozilla/5.0 (Windows NT 10.0; Win32; x32) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36\"\n", + "\t\t}\n", + "\t)\n", + "\n", + "\t#-=-=-=-#\n", + "\t# Models\n", + "\n", + "\tprint(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "\tModels = {\n", + "\t\t\"hifi-gan-bwe-10-42890e3-vctk-48kHz\": \"\"\"\n", + "\t\t\tSame as [i]bwe-05[/], but [b]uses bandlimited interpolation for upsampling, [u]for reduced noise and aliasing[/][/].\n", + "\t\t\t[u]Uses the same parameters as resampy's \"kaiser_best\" mode[/]\n", + "\t\t\t\"\"\",\n", + "\t\t\"hifi-gan-bwe-11-d5f542d-vctk-8kHz-48kHz\": \"Same as [i]bwe-10[/], but [b]trained only on [i]8 000 Hz[/i][/] sources, [b u]for specialized upsampling[/]\",\n", + "\t\t\"hifi-gan-bwe-12-b086d8b-vctk-16kHz-48kHz\": \"Same as [i]bwe-10[/], but [b]trained only on [i]16 000 Hz[/][/] sources, [b u]for specialized upsampling[/]\",\n", + "\t\t\"hifi-gan-bwe-13-59f00ca-vctk-24kHz-48kHz\": \"Same as [i]bwe-10[/], but [b]trained only on [i]24 000 Hz[/][/] sources, [b u]for specialized upsampling[/]\",\n", + "\t\t\"hifi-gan-bwe-05-cd9f4ca-vctk-48kHz\": \"Trained for 200K iterations on the VCTK [b u]speech dataset with noise agumentation[/] from the DNS Challenge dataset\"\n", + "\t}\n", + "\n", + "\trmtree(os.path.expanduser(\"~/.local/hifi-gan-bwe\"), True)\n", + "\tfor Key, Value in Models.items():\n", + "\t\tModels[Key] = Value.replace(\"\\t\", \"\").strip(\"\\n\\t\")\n", + "\t\tBandwidthExtender.from_pretrained(Key)\n", + "\n", + "\t#-=-=-=-#\n", + "\t# Functions\n", + "\n", + "\tdef fdb_size(obj: str, extended_units: bool = False, bits: bool = False, recursive: bool = False) -> str:\n", + "\t\t\"\"\"\n", + "\t\tArgs:\n", + "\t\t\tobj: Bytes integer or string path of existing file or directory.\n", + "\t\t\textended_units: Extends the unit of the result, i.e. \"Megabytes\" instead of \"MB\".\n", + "\t\t\tbits: Uses decimal divider (1000) instead of binary one. (1024)\n", + "\t\t\trecursive: Iterate subdirectories, applicable only if `obj` is directory. (slow!)\n", + "\n", + "\t\tReturns:\n", + "\t\t\tHuman-readable files size string.\n", + "\t\t\"\"\"\n", + "\t\t# Setup\n", + "\n", + "\t\tif bits:\n", + "\t\t\tBits = 1000\n", + "\t\t\tBits_Display_Single = \"bit\"\n", + "\t\t\tBits_Display_Multiple = \"bits\"\n", + "\t\telse:\n", + "\t\t\tBits = 1024\n", + "\t\t\tBits_Display_Single = \"byte\"\n", + "\t\t\tBits_Display_Multiple = \"bytes\"\n", + "\n", + "\t\tUnits = {\n", + "\t\t\t\"\":\t \"\",\n", + "\t\t\t\"K\": \"kilo\",\n", + "\t\t\t\"M\": \"mega\",\n", + "\t\t\t\"G\": \"giga\",\n", + "\t\t\t\"T\": \"tera\",\n", + "\t\t\t\"P\": \"peta\",\n", + "\t\t\t\"E\": \"exa\",\n", + "\t\t\t\"Z\": \"zetta\",\n", + "\t\t\t\"Y\": \"yotta\",\n", + "\t\t\t\"R\": \"ronna\",\n", + "\t\t\t\"Q\": \"quetta\"\n", + "\t\t}\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Search for files\n", + "\n", + "\t\tif isinstance(obj, str):\n", + "\t\t\tpath = str(Path(obj).resolve())\n", + "\n", + "\t\t\tif not os.path.exists(path):\n", + "\t\t\t\traise FileNotFoundError(path)\n", + "\n", + "\t\t\tif os.path.isfile(obj):\n", + "\t\t\t\tFiles = [obj]\n", + "\t\t\telse:\n", + "\t\t\t\tWildcard = \"*\"\n", + "\t\t\t\tif recursive:\n", + "\t\t\t\t\tWildcard += \"*/*\"\n", + "\t\t\t\tFiles = list(Path(obj).glob(Wildcard))\n", + "\t\t\t\tfor File in Files:\n", + "\t\t\t\t\tFiles[Files.index(File)] = str(File.resolve())\n", + "\n", + "\t\t\tFiles = map(os.path.getsize, Files)\n", + "\t\t\tBytes = sum(Files)\n", + "\t\telse:\n", + "\t\t\tBytes = obj\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Calculate integer\n", + "\n", + "\t\tfor Unit in Units:\n", + "\t\t\tif Bytes < Bits:\n", + "\t\t\t\tbreak\n", + "\t\t\tBytes /= Bits\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Ending conditions\n", + "\n", + "\t\tif extended_units:\n", + "\t\t\tif Bytes == 1:\n", + "\t\t\t\tBits_Display = Bits_Display_Single\n", + "\t\t\telse:\n", + "\t\t\t\tBits_Display = Bits_Display_Multiple\n", + "\t\t\tUnit = (Units[Unit] + Bits_Display).capitalize()\n", + "\t\telse:\n", + "\t\t\tUnit += \"B\"\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Add zero to integer\n", + "\n", + "\t\tif \".\" in str(Bytes):\n", + "\t\t\tBytes = round(Bytes, 2)\n", + "\t\t\tBytes = str(Bytes).split(\".\")\n", + "\t\t\tBytes[1] = Bytes[1][:2]\n", + "\t\t\tBytes[1] = Bytes[1].ljust(2, \"0\")\n", + "\t\t\tBytes = \".\".join(Bytes)\n", + "\n", + "\t\tBytes = str(Bytes)\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Return string\n", + "\n", + "\t\treturn \" \".join((Bytes, Unit))\n", + "\n", + "\t#-=-=-=-#\n", + "\t# Directories\n", + "\n", + "\tDirectory_Main = os.path.abspath(__title__)\n", + "\tDirectory_Primary = os.path.join(Directory_Main, \"Repository\")\n", + "\tDirectory_Inputs = os.path.join(Directory_Main, \"_inputs\")\n", + "\tDirectory_Outputs = os.path.join(Directory_Main, \"_outputs\")\n", + "\n", + "\tif os.path.exists(Directory_Primary):\n", + "\t\trmtree(Directory_Primary)\n", + "\n", + "\tfor Directory in Directory_Inputs, Directory_Outputs:\n", + "\t\tos.makedirs(Directory, exist_ok = True)\n", + "except (KeyboardInterrupt, EOFError):\n", + "\tprint(\"\\n\" + \"โ”€\" * 32 + \"\\n\" + \"Operation cancelled by user.\")" + ], + "metadata": { + "id": "9ezDwM6lbQ9s", + "cellView": "form" + } + }, + { + "cell_type": "markdown", + "source": [ + "#
**2.** Upload files ๐Ÿ“ค
" + ], + "metadata": { + "id": "cOXSJNbzrDmk" + } + }, + { + "cell_type": "code", + "metadata": { + "id": "dNrOJkouZFlx", + "cellView": "form" + }, + "source": [ + "#@markdown > ๐Ÿ—ƒ๏ธ **URL of `ZIP` archive with files is supported.**\n", + "\n", + "Direct_URL = \"\" #@param {type: \"string\"}\n", + "Allow_non_WAV_URL = True #@param {type: \"boolean\"}\n", + "__URL_Fail = False if Direct_URL else True\n", + "\n", + "#@markdown ---\n", + "\n", + "#@markdown > โ„น๏ธ `Lazy Unpacking` determines whether **files from the archive should only be unpacked if their file name extension** is in the `Formats` variable.\n", + "\n", + "Lazy_Unpacking = True #@param {type: \"boolean\"}\n", + "Formats = \"AAC, AIFF, ALAC, APE, FLAC, M4A, MP3, OGG, OPUS, WAV, WV\" #@param {type: \"string\"}\n", + "Formats = [Format.lower().strip() for Format in Formats.split(\",\")]\n", + "\n", + "#@markdown ---\n", + "\n", + "Ask_to_upload_files_if_download_succeeds = True #@param {type: \"boolean\"}\n", + "Remove_previously_uploaded_files_and_subdirectories = True #@param {type: \"boolean\"}\n", + "\n", + "#-=-=-=-#\n", + "\n", + "if \"rmtree\" not in locals():\n", + "\traise SystemExit(\"Requirements were not installed!\\nPlease run the first cell.\")\n", + "\n", + "if \"Files\" not in locals():\n", + "\tFiles = []\n", + "\n", + "#-=-=-=-#\n", + "\n", + "__Directory_Base = os.getcwd()\n", + "\n", + "# `os.chdir` since `files.upload` does not have the target directory argument\n", + "os.chdir(Directory_Inputs)\n", + "\n", + "if Remove_previously_uploaded_files_and_subdirectories:\n", + "\tFiles_Inputs = []\n", + "\tfor File in Path(Directory_Inputs).rglob(\"*\"):\n", + "\t\tFile = str(File.resolve())\n", + "\t\tif is_colab:\n", + "\t\t\tif \".ipynb_checkpoints\" not in os.path.basename(File):\n", + "\t\t\t\tFiles_Inputs.append(File)\n", + "\t\telse:\n", + "\t\t\tFile_Inputs.append(File)\n", + "\n", + "\tfor File in Files_Inputs:\n", + "\t\tif os.path.isfile(File):\n", + "\t\t\tos.remove(File)\n", + "\t\t\trprint('Removed [b #44AAFF]\"{0}\"[/]'.format(\n", + "\t\t\t\tos.path.relpath(File, Directory_Inputs)\n", + "\t\t\t))\n", + "\n", + "\tfor File in Files_Inputs:\n", + "\t\tif os.path.isdir(File):\n", + "\t\t\trmtree(File)\n", + "\n", + "\tif Files_Inputs:\n", + "\t\tprint(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "\n", + "\tFiles = []\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Allowed_Specifiers = \"http\", \"https\", \"ftp\"\n", + "Allowed_Specifiers = [Specifier + \"://\" for Specifier in Allowed_Specifiers]\n", + "Allowed_Specifiers = tuple(Allowed_Specifiers)\n", + "\n", + "if Direct_URL.lower().startswith(Allowed_Specifiers):\n", + "\tfor Delimiter in ((\"?\", \"&\", \"#\")):\n", + "\t\tDownloaded_File_Location = Direct_URL.split(Delimiter)[0]\n", + "\n", + "\tDownloaded_File_Location = utils.unquote(Downloaded_File_Location.split(\"/\")[-1])\n", + "\n", + "\t__URL_Fail = False\n", + "\ttry:\n", + "\t\tSession_obj = session.get(Direct_URL, stream = 1)\n", + "\texcept Exception:\n", + "\t\t__URL_Fail = True\n", + "\n", + "\tif __URL_Fail:\n", + "\t\trprint(\"[b #FF0000]Provided URL is invalid![/]\")\n", + "\t\t__URL_Fail = True\n", + "\n", + "\tif not __URL_Fail:\n", + "\t\twith Session_obj as Site:\n", + "\t\t\tif Site.ok:\n", + "\t\t\t\tSite_MIME = Site.headers[\"content-type\"].lower().split()[0].split(\";\")[0].split(\"/\")\n", + "\t\t\t\tif Site_MIME[0] == \"audio\":\n", + "\t\t\t\t\tif any((Site_MIME[1].endswith(\"wav\"), Allow_non_WAV_URL)):\n", + "\t\t\t\t\t\twith open(Downloaded_File_Location, \"wb\") as File:\n", + "\t\t\t\t\t\t\trprint(f'Downloading [b #00CC00]\"{Downloaded_File_Location}\"[/]...')\n", + "\n", + "\t\t\t\t\t\t\tfor Chunk in Site.iter_content(chunk_size = 1024):\n", + "\t\t\t\t\t\t\t\tif Chunk:\n", + "\t\t\t\t\t\t\t\t\tFile.write(Chunk)\n", + "\t\t\t\t\t\t\tFiles.append(Downloaded_File_Location)\n", + "\t\t\t\t\telse:\n", + "\t\t\t\t\t\trprint(\"[b #FF0000]Permission to download non-WAV files was not granted.[/]\")\n", + "\t\t\t\t\t\t__URL_Fail = True\n", + "\t\t\t\telse:\n", + "\t\t\t\t\t# ZIP Archive Handling\n", + "\t\t\t\t\tif \"/\".join(Site_MIME) == \"application/zip\":\n", + "\t\t\t\t\t\twith open(Downloaded_File_Location, \"wb\") as File:\n", + "\t\t\t\t\t\t\trprint(f'Downloading [b #00CC00]\"{Downloaded_File_Location}\"[/]...')\n", + "\n", + "\t\t\t\t\t\t\tfor Chunk in Site.iter_content(chunk_size = 1024):\n", + "\t\t\t\t\t\t\t\tif Chunk:\n", + "\t\t\t\t\t\t\t\t\tFile.write(Chunk)\n", + "\n", + "\t\t\t\t\t\ttry:\n", + "\t\t\t\t\t\t\tArchive_Files_Amount = 0\n", + "\t\t\t\t\t\t\twith ZipFile(Downloaded_File_Location) as Archive:\n", + "\t\t\t\t\t\t\t\tfor Archive_File in Archive.infolist():\n", + "\t\t\t\t\t\t\t\t\tif Lazy_Unpacking:\n", + "\t\t\t\t\t\t\t\t\t\tif os.path.splitext(Archive_File.filename.lower())[1][1:] in Formats:\n", + "\t\t\t\t\t\t\t\t\t\t\tArchive_Files_Amount += 1\n", + "\t\t\t\t\t\t\t\t\t\t\tArchive.extract(Archive_File)\n", + "\t\t\t\t\t\t\t\t\telse:\n", + "\t\t\t\t\t\t\t\t\t\tArchive_Files_Amount += 1\n", + "\t\t\t\t\t\t\t\t\t\tArchive.extract(Archive_File)\n", + "\n", + "\t\t\t\t\t\t\tos.remove(Downloaded_File_Location)\n", + "\n", + "\t\t\t\t\t\t\t#-=-=-=-#\n", + "\n", + "\t\t\t\t\t\t\tfor File in Path().rglob(\"*.*\"):\n", + "\t\t\t\t\t\t\t\tFile = str(File.resolve())\n", + "\n", + "\t\t\t\t\t\t\t\tif os.path.isfile(File):\n", + "\t\t\t\t\t\t\t\t\tFiles.append(File)\n", + "\n", + "\t\t\t\t\t\t\trprint(f\"[b #00CC00]{Archive_Files_Amount} files from main directory were extracted successfully![/]\")\n", + "\t\t\t\t\t\texcept RuntimeError:\n", + "\t\t\t\t\t\t\trprint(\"[b #FF0000]Files extraction was not successful due to password requirement, file corruption or other internal error.[/]\")\n", + "\t\t\t\t\t\t\t__URL_Fail = True\n", + "\t\t\t\t\telse:\n", + "\t\t\t\t\t\trprint(\"[b #FF0000]Provided URL is not an audio file.[/] [i #A0A0A0](undetected MIME type in header)[/]\")\n", + "\t\t\t\t\t\t__URL_Fail = True\n", + "\t\t\telse:\n", + "\t\t\t\trprint(\"[b #FF0000]Failed to fetch the URL due to {0} status code. ({1})[/]\".format(\n", + "\t\t\t\t\tSite.status_code, Site.reason.title()\n", + "\t\t\t\t))\n", + "\t\t\t\t__URL_Fail = True\n", + "\n", + "#-=-=-=-#\n", + "# Upload files\n", + "\n", + "__Cancel_Permission = \"\" if __URL_Fail else \" [i #A0A0A0](can be cancelled)[/]\"\n", + "\n", + "if any((Ask_to_upload_files_if_download_succeeds, __URL_Fail)):\n", + "\tprint(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "\trprint(f\"Upload [b #44AAFF]AUDIO[/] files{__Cancel_Permission}\")\n", + "\n", + "\ttry:\n", + "\t\tfor File in files.upload():\n", + "\t\t\tFiles.append(File)\n", + "\texcept TypeError:\n", + "\t\tpass\n", + "\texcept (KeyboardInterrupt, EOFError):\n", + "\t\trprint(\"\\n\\n[b #FFCC00]File upload cancelled.[/]\")\n", + "\n", + "\tFiles = [str(Path(File).resolve()) for File in Files]\n", + "\tif is_colab:\n", + "\t\tFiles = [File for File in Files if os.path.basename(File) != \".ipynb_checkpoints\"]\n", + "\tFiles = list(set(Files))\n", + "\n", + "#-=-=-=-#\n", + "# Check for files\n", + "\n", + "Files = [os.path.abspath(File) for File in Files]\n", + "\n", + "err = 0\n", + "try:\n", + "\t# Use this later for string formatting\n", + "\tLongest_File_Name_Length = [File.split(Directory_Inputs)[1][1:] for File in Files]\n", + "\tLongest_File_Name_Length.sort(key = len)\n", + "\tLongest_File_Name_Length = len(Longest_File_Name_Length[-1])\n", + "except IndexError:\n", + "\terr = 1\n", + "\n", + "if err:\n", + "\traise SystemExit(\"No uploaded files has been found.\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "os.chdir(__Directory_Base)" + ] + }, + { + "cell_type": "code", + "source": [ + "#@title
Verify files and convert them to `WAV` โš™๏ธ
\n", + "#@markdown > โš ๏ธ **Files whose [MIME type](https://wikipedia.org/wiki/Media_type)'s first segment will not be detected as `audio` will be removed without warning.**\n", + "if \"Files\" not in locals():\n", + "\traise SystemExit(\"Requirements were not installed!\\nPlease run the first cell.\")\n", + "\n", + "if not Files:\n", + "\traise SystemExit(\"No files has been found!\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Target = \"WAV\"\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Target = Target.split()[0].upper().strip(\".\")\n", + "\n", + "for Input in Files:\n", + "\tInput_Split = os.path.split(os.path.abspath(Input))\n", + "\tInput_Name = Input_Split[1]\n", + "\n", + "\ttry:\n", + "\t\tInput_MIME = mFile(Input).mime\n", + "\texcept AttributeError:\n", + "\t\tInput_MIME = guess_type(Input)\n", + "\tInput_MIME = Input_MIME[0].lower().split(\"/\")\n", + "\n", + "\tif Input_MIME[0] == \"audio\":\n", + "\t\tif Input_MIME[1] != Target.lower():\n", + "\t\t\tos.environ[\"FILE_INPUT\"] = Input\n", + "\t\t\tos.environ[\"FILE_OUTPUT\"] = os.path.splitext(Input)[0] + f\".{Target.lower()}\"\n", + "\n", + "\t\t\trprint(f'[b #00CC00]\"{Input_Name}\" is not a {Target} file, converting...[/]')\n", + "\t\t\t!ffmpeg -y -i \"$FILE_INPUT\" -hide_banner -loglevel 16 \\\n", + "\t\t\t\t-map_metadata 0 -map_metadata 0:s:0 \\\n", + "\t\t\t\t-fflags +bitexact -flags:v +bitexact -flags:a +bitexact \\\n", + "\t\t\t\t\"$FILE_OUTPUT\"\n", + "\n", + "\t\t\tFiles[Files.index(Input)] = os.environ[\"FILE_OUTPUT\"]\n", + "\t\t\tos.remove(Input)\n", + "\telse:\n", + "\t\trprint(f'[b #FF0000]\"{Input_Name}\" is not an audio file, removing[/]')\n", + "\t\tFiles.remove(Input)\n", + "\t\tos.remove(Input)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "if not Files:\n", + "\traise SystemExit(\"No files has been found!\")" + ], + "metadata": { + "id": "k3XKgCi0EWyP", + "cellView": "form" + } + }, + { + "cell_type": "markdown", + "source": [ + "#
**3.** Process ๐Ÿ“ˆ
" + ], + "metadata": { + "id": "wWMN_sT-ugof" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Load Model โš™๏ธ
\n", + "#@markdown | Name | Quality (speech) | Quality (music) | Details |\n", + "#@markdown |:-|:-|:-|:-|\n", + "#@markdown | `hifi-gan-bwe-10-42890e3-vctk-48kHz` | โญ | โญ | Same as bwe-05, but uses bandlimited interpolation for upsampling, for reduced noise and aliasing.
Uses the same parameters as resampy's [`kaiser_best`](https://github.com/bmcfee/resampy/blob/5f46888e8b52402f2c62f374b39b93e0743543ad/resampy/filters.py#L9) mode. |\n", + "#@markdown | `hifi-gan-bwe-11-d5f542d-vctk-8kHz-48kHz` | โญโญ | โญ | Same as bwe-10, but trained only on 8kHz sources, for specialized upsampling. |\n", + "#@markdown | `hifi-gan-bwe-12-b086d8b-vctk-16kHz-48kHz` | โญโญโญ | โญ | Same as bwe-10, but trained only on 16kHz sources, for specialized upsampling. |\n", + "#@markdown | `hifi-gan-bwe-13-59f00ca-vctk-24kHz-48kHz` | โญโญโญโญ | โญโญ | Same as bwe-10, but trained only on 24kHz sources, for specialized upsampling. |\n", + "#@markdown | `hifi-gan-bwe-05-cd9f4ca-vctk-48kHz` | โญโญโญโญโญ | โญโญโญโญ | Trained for 200K iterations on the VCTK speech dataset with noise agumentation from the DNS Challenge dataset. |\n", + "\n", + "#@markdown ---\n", + "\n", + "if \"Models\" not in locals():\n", + "\trprint(\"[b #FF0000]Requirements were not installed!\\nPlease run the first cell.[/]\")\n", + "\n", + "Model_Name = \"hifi-gan-bwe-05-cd9f4ca-vctk-48kHz\" #@param [\"hifi-gan-bwe-10-42890e3-vctk-48kHz\", \"hifi-gan-bwe-11-d5f542d-vctk-8kHz-48kHz\", \"hifi-gan-bwe-12-b086d8b-vctk-16kHz-48kHz\", \"hifi-gan-bwe-13-59f00ca-vctk-24kHz-48kHz\", \"hifi-gan-bwe-05-cd9f4ca-vctk-48kHz\"]\n", + "Model = BandwidthExtender.from_pretrained(Model_Name)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "rprint('[b][#00CC00]Successfully loaded \"{0}\" model.[/]'.format(Model_Name))\n", + "print()\n", + "rprint(\"\\nDetails: {0}.\".format(Models[Model_Name]))" + ], + "metadata": { + "id": "quPFIMVHZYZz", + "cellView": "form" + } + }, + { + "cell_type": "code", + "source": [ + "#@title #
**Run**
\n", + "#@markdown Select $\\ge1$ output target samplerates.\n", + "SR_44100 = False #@param {type: \"boolean\"}\n", + "SR_48000 = True #@param {type: \"boolean\"}\n", + "SR_96000 = False #@param {type: \"boolean\"}\n", + "SR_192000 = False #@param {type: \"boolean\"}\n", + "\n", + "SR_BASE = int(48_000)\n", + "Target_Samplerates = {\n", + "\t44_100: SR_44100,\n", + "\tSR_BASE: SR_48000,\n", + "\t96_000: SR_96000,\n", + "\t192_000: SR_192000\n", + "}\n", + "\n", + "Sampling_Factors = {}\n", + "for Key in Target_Samplerates:\n", + "\tif Key != SR_BASE:\n", + "\t\tSampling_Factors.update({Key: Key / SR_BASE})\n", + "Sampling_Factors.update({SR_BASE: 1})\n", + "\n", + "Target_Samplerates = [int(Key) for Key, Value in Target_Samplerates.items() if Value]\n", + "\n", + "if not Target_Samplerates:\n", + "\traise SystemExit(\"No target samplerates were selected!\")\n", + "\n", + "#@markdown > โš ๏ธ **Output target samplerates above `48 000 Hz`:**\n", + "#@markdown > - **Takes longer to process**\n", + "#@markdown > - **Uses MUCH more RAM and may lead to the notebook failure!**\n", + "#@markdown > - **Changes frequency balance**\n", + "#@markdown > - **Was tested only on the `hifi-gan-bwe-05-cd9f4ca-vctk-48kHz` model**\n", + "#@markdown\n", + "\n", + "#@markdown > ## โš ๏ธ **Previously processed files will be removed without warning!**\n", + "\n", + "#@markdown > โ„น๏ธ **Files that duration exceeds $10$ seconds are not recommended!**\n", + "\n", + "#@markdown ---\n", + "\n", + "Sort_Files_by = \"Upload order ๐Ÿ”ข\" #@param [\"Upload order ๐Ÿ”ข\", \"Duration ๐Ÿ•’\", \"Size โš™๏ธ\"]\n", + "Sort_Files_by = Sort_Files_by.lower()\n", + "Descending = False #@param {type: \"boolean\"}\n", + "\n", + "#@markdown ---\n", + "\n", + "Upscale_Internal_Gain = 0 # @param {type: \"slider\", min: 0, max: 6, step: 1}\n", + "\n", + "#-=-=-=-#\n", + "# Files removal\n", + "\n", + "Files_Outputs = []\n", + "\n", + "for File in Path(Directory_Outputs).rglob(\"*\"):\n", + "\tFile = str(File.resolve())\n", + "\tif is_colab:\n", + "\t\tif \".ipynb_checkpoints\" not in os.path.basename(File):\n", + "\t\t\tFiles_Outputs.append(File)\n", + "\telse:\n", + "\t\tFiles_Outputs.append(File)\n", + "\n", + "for File in Files_Outputs:\n", + "\tif os.path.isfile(File):\n", + "\t\tos.remove(File)\n", + "\n", + "for File in Files_Outputs:\n", + "\tif os.path.isdir(File):\n", + "\t\trmtree(File)\n", + "\n", + "#-=-=-=-#\n", + "# Sorting files\n", + "\n", + "Files_Sorted = Files\n", + "if \"duration\" in Sort_Files_by:\n", + "\tFiles_Sorted = {File: mFile(File).info.length for File in Files}\n", + "\tFiles_Sorted = sorted(Files_Sorted.items(), key = lambda x: x[1])\n", + "\tFiles_Sorted = list(dict(Files_Sorted))\n", + "if \"size\" in Sort_Files_by:\n", + "\tFiles_Sorted = sorted(Files, key = os.path.getsize)\n", + "\n", + "if Descending:\n", + "\tFiles_Sorted = Files_Sorted[::-1]\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Runtime = time()\n", + "Counter_Samplerates = 1\n", + "\n", + "torch.cuda.empty_cache()\n", + "\n", + "try:\n", + "\twith torch.no_grad():\n", + "\t\tfor Output_Target_Samplerate in Target_Samplerates:\n", + "\t\t\tOutput_Target_Samplerate_Display = f\"{Output_Target_Samplerate:,}\".split(\",\")\n", + "\t\t\tOutput_Target_Samplerate_Display = \" \".join(Output_Target_Samplerate_Display) + \" Hz\"\n", + "\t\t\tCounter_Samplerates_Display = str(Counter_Samplerates).rjust(len(str(len(Target_Samplerates))) + 1, \"0\")\n", + "\n", + "\t\t\trprint(\"[b][#44AAFF]{0}.[/] Processing ([#44AAFF]{1}[/])[/]\".format(\n", + "\t\t\t\tCounter_Samplerates_Display,\n", + "\t\t\t\tOutput_Target_Samplerate_Display\n", + "\t\t\t))\n", + "\n", + "\t\t\tCounter = 1\n", + "\t\t\tfor Input in Files_Sorted:\n", + "\t\t\t\tCounter_Display = str(Counter).rjust(len(str(len(Files_Sorted))) + 1, \"0\")\n", + "\t\t\t\t# Output file\n", + "\t\t\t\tInput_Split = os.path.split(os.path.abspath(Input))\n", + "\n", + "\t\t\t\tOutput = os.path.join(\n", + "\t\t\t\t\tDirectory_Outputs,\n", + "\t\t\t\t\tos.path.relpath(Input_Split[0], Directory_Inputs),\n", + "\t\t\t\t\t\"_\".join((\n", + "\t\t\t\t\t\tos.path.splitext(Input_Split[1])[0],\n", + "\t\t\t\t\t\t\"scaled\",\n", + "\t\t\t\t\t\tstr(Output_Target_Samplerate)\n", + "\t\t\t\t\t)) + os.path.splitext(Input_Split[1])[1]\n", + "\t\t\t\t)\n", + "\n", + "\t\t\t\tif not os.path.exists(os.path.dirname(Output)):\n", + "\t\t\t\t\tos.makedirs(os.path.dirname(Output), exist_ok = True)\n", + "\n", + "\t\t\t\t#-=-=-=-#\n", + "\t\t\t\t# Data\n", + "\n", + "\t\t\t\twith audioread.audio_open(Input) as File_Object:\n", + "\t\t\t\t\tSamplerate = File_Object.samplerate\n", + "\t\t\t\t\tAudio_Data = (\n", + "\t\t\t\t\t\tnp.hstack([np.frombuffer(b, dtype = np.int16) for b in File_Object])\n", + "\t\t\t\t\t\t.reshape([-1, File_Object.channels])\n", + "\t\t\t\t\t\t.astype(np.float32)\n", + "\t\t\t\t\t) / (32767 - (Upscale_Internal_Gain * 1024))\n", + "\n", + "\t\t\t\t#-=-=-=-#\n", + "\t\t\t\t# Scale\n", + "\n", + "\t\t\t\tFile_Object = mFile(Input)\n", + "\t\t\t\tMSR = Model.sample_rate\n", + "\n", + "\t\t\t\trprint(\" [b][#FFCC00]{0}.[/] [i]{1} [#A0A0A0]({2}s) ({3})[/][/][/]\".format(\n", + "\t\t\t\t\tCounter_Display,\n", + "\n", + "\t\t\t\t\tos.path.join(\n", + "\t\t\t\t\t\tos.path.relpath(Input_Split[0], Directory_Inputs)[2:],\n", + "\t\t\t\t\t\tInput_Split[1]\n", + "\t\t\t\t\t).ljust(Longest_File_Name_Length, \" \"),\n", + "\n", + "\t\t\t\t\tround(File_Object.info.length, 3),\n", + "\t\t\t\t\tfdb_size(Input)\n", + "\t\t\t\t))\n", + "\n", + "\t\t\t\t# Main\n", + "\t\t\t\ttorch.cuda.empty_cache()\n", + "\t\t\t\tAudio_Data = np.stack([\n", + "\t\t\t\t\tModel(torch.from_numpy(x),\n", + "\t\t\t\t\tint(Samplerate / Sampling_Factors[Output_Target_Samplerate])\n", + "\t\t\t\t\t) for x in Audio_Data.T]).T\n", + "\t\t\t\twrite(\n", + "\t\t\t\t\tOutput,\n", + "\t\t\t\t\tint(MSR * Sampling_Factors[Output_Target_Samplerate]),\n", + "\t\t\t\t\tAudio_Data\n", + "\t\t\t\t)\n", + "\n", + "\t\t\t\tCounter += 1\n", + "\n", + "\t\t\t#-=-=-=-#\n", + "\n", + "\t\t\tif all((len(Target_Samplerates) > 1, Output_Target_Samplerate != Target_Samplerates[-1])):\n", + "\t\t\t\tprint()\n", + "\n", + "\t\t\tCounter_Samplerates += 1\n", + "except (KeyboardInterrupt, EOFError):\n", + "\trprint(\"[#FF0000]Operation cancelled by user.[/]\")\n", + "\n", + "torch.cuda.empty_cache()\n", + "\n", + "#-=-=-=-#\n", + "\n", + "__Run_Time = time() - Runtime\n", + "print(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "rprint(\"[b #00CC00]Done![/]\")\n", + "rprint(\"Runtime: [b #44AAFF]{0}[/]\".format(\n", + "\tstr(timedelta(seconds = __Run_Time))[2:-3]\n", + "))\n", + "rprint(\"\\t[i #A0A0A0]avg. {0} per file[/]\".format(\n", + "\tstr(timedelta(seconds = __Run_Time / len(Files)))[2:-3]\n", + "))\n", + "rprint(\"\\t[i #A0A0A0]avg. {0} per samplerate[/]\".format(\n", + "\tstr(timedelta(seconds = (__Run_Time / len(Files)) / len(Target_Samplerates)))[2:-3]\n", + "))" + ], + "metadata": { + "id": "4ni9ii4SeEPe", + "cellView": "form" + } + }, + { + "cell_type": "markdown", + "source": [ + "#
Utils โš™๏ธ
" + ], + "metadata": { + "id": "XfDlrVA9Qc1x" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Convert output files to `FLAC` ๐ŸŽถ
\n", + "\n", + "Bit_Depth = \"24-bit\" #@param [\"16-bit\", \"24-bit\"]\n", + "Bit_Depth = Bit_Depth.split(\"-\")[0]\n", + "Normalize_dB = 1 # @param {type: \"slider\", min: -6, max: 1, step: 1}\n", + "#@markdown > โ„น๏ธ To **disable** normalization, set `Normalize_dB` to **`1`**.\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Target = \"FLAC\"\n", + "Target = Target.split()[0].lower().strip(\".\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "os.environ[\"BIT_DEPTH\"] = \"-b \" + Bit_Depth\n", + "os.environ[\"NORMALIZE\"] = (\"--norm \" + str(Normalize_dB)) if Normalize_dB < 1 else \"\"\n", + "\n", + "for File in Path(Directory_Outputs).rglob(\"*.*\"):\n", + "\tInput = str(File.resolve())\n", + "\n", + "\tif os.path.isfile(Input):\n", + "\t\tInput_MIME = mFile(Input).mime[0].lower().split(\"/\")\n", + "\t\tInput_Name = os.path.relpath(Input, Directory_Main)\n", + "\n", + "\t\tOutput_FLAC = os.path.splitext(Input)[0], f\".{Target.lower()}\"\n", + "\t\tOutput = \"_\".join(Output_FLAC)\n", + "\n", + "\t\tos.environ[\"FILE_INPUT\"] = Input\n", + "\t\tos.environ[\"FILE_OUTPUT\"] = Output\n", + "\n", + "\t\trprint('[b i]{1}onverting [#44AAFF]\"{0}\"[/] to FLAC...[/]'.format(\n", + "\t\t\tInput_Name,\n", + "\t\t\t(\"rec\" if Input_MIME[1] == \"flac\" else \"c\").capitalize()\n", + "\t\t))\n", + "\t\t!sox \"$FILE_INPUT\" -D $BIT_DEPTH -C 8 $NORMALIZE --comment \"\" -G \"$FILE_OUTPUT\" -V0\n", + "\n", + "\t\tos.remove(Input)\n", + "\t\tos.rename(Output, \"\".join(Output_FLAC))" + ], + "metadata": { + "cellView": "form", + "id": "nxkupjCJpf5R" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Download archive with output files ๐Ÿ—ƒ๏ธ
\n", + "Emphasize_Archive_File_Name = True #@param {type: \"boolean\"}\n", + "Beggining = \"!_\" if Emphasize_Archive_File_Name else \"\"\n", + "\n", + "#@markdown > โ„น๏ธ Pushes the archive file to top of the explorer's file list (**if** it's sorted by name) by putting `!_` to its file name beggining.\n", + "\n", + "#-=-=-=-#\n", + "\n", + "__Padding = 7\n", + "Archive_File = Beggining + \"_\".join((__title__, str(time()).split(\".\")[1][:__Padding].rjust(__Padding, \"0\")))\n", + "Archive_File += \".zip\"\n", + "Archive_File = os.path.abspath(Archive_File)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "# Archive Creation\n", + "print(\"Making Archive...\")\n", + "with ZipFile(Archive_File, \"w\", 14, 1, 9) as Archive:\n", + "\tfor File in Path(Directory_Outputs).rglob(\"*.*\"):\n", + "\t\tFile = str(File.resolve())\n", + "\n", + "\t\tif os.path.isfile(File):\n", + "\t\t\tArcName = os.path.relpath(File, Directory_Outputs)\n", + "\n", + "\t\t\trprint(f'\\t[b i]Writing [#44AACC]\"{ArcName}\"[/]...')\n", + "\t\t\tArchive.write(File, ArcName)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "files.download(Archive_File)" + ], + "metadata": { + "id": "rpPfi2g7gnTi", + "cellView": "form" + } + }, + { + "cell_type": "code", + "source": [ + "#@title Terminate runtime after specified time ๐Ÿ”Œ\n", + "#@markdown In case if you don't want to waste this account's resources while performing other tasks.\n", + "#@markdown > ### **This cancellable action is irreversible and will result in loss of ALL session data!**\n", + "\n", + "#@markdown
\n", + "#@markdown
\n", + "#@markdown Time sheet\n", + "#@markdown\n", + "#@markdown
\n", + "#@markdown\n", + "#@markdown | Seconds | Minutes |\n", + "#@markdown |:-|:-|\n", + "#@markdown | `60` | `1` |\n", + "#@markdown | `300` | `5` |\n", + "#@markdown | `600` | `10` |\n", + "#@markdown | `1800` | `30` |\n", + "#@markdown | `3600` | `60` |\n", + "#@markdown
\n", + "\n", + "#@markdown ---\n", + "\n", + "Seconds_Default = 30\n", + "Seconds = 300 # @param {type: \"integer\"}\n", + "\n", + "if Seconds < 0:\n", + "\trprint(f\"[b][#FFCC00]Seconds are[/] [#FF0000]< 0[/][#FFCC00], defaulting to[/] [#FF0000]{Seconds_Default}[/][#FFCC00].[/][/]\")\n", + "\n", + "__Spaces = \" \" * 8\n", + "\n", + "\n", + "\n", + "if is_colab:\n", + "\ttry:\n", + "\t\tfor i in range(Seconds, -1, -1):\n", + "\t\t\tprint(\"\\r\", end = f\"Runtime will be terminated in {i} seconds...\" + __Spaces)\n", + "\n", + "\t\trprint(\"\\n\\n[b #FF0000]Runtime has been terminated.[/]\")\n", + "\t\truntime.unassign()\n", + "\texcept (KeyboardInterrupt, EOFError):\n", + "\t\tprint()\n", + "\t\trprint(\"[b #FF0000]Operation cancelled by user.[/]\")\n", + "else:\n", + "\trprint(\"[b #FFCC00]Not in Colab, unsupported.[/]\")" + ], + "metadata": { + "id": "rhKs_AmESZew", + "cellView": "form" + } + } + ] +} \ No newline at end of file diff --git a/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS.ipynb b/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS.ipynb new file mode 100644 index 0000000..abe52f7 --- /dev/null +++ b/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS.ipynb @@ -0,0 +1,1075 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "Coqui XTTS", + "provenance": [], + "collapsed_sections": [ + "XfDlrVA9Qc1x" + ], + "gpuType": "T4" + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + }, + "accelerator": "GPU" + }, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# **COQUI ๐Ÿธ**\n", + "\n", + "> *Compact implementation of [**`camenduru/coqui-XTTS-colab`**](camenduru/coqui-XTTS-colab).*\n", + "\n", + "


\n", + "\n", + "### Features:\n", + "- URL support ๐Ÿ”—\n", + "- **Batch processing** ๐Ÿ”ฐ\n", + "\n", + "


\n", + "\n", + "" + ], + "metadata": { + "id": "0D-OWUaK7rjM" + } + }, + { + "cell_type": "markdown", + "source": [ + "#
**1.** Re/install requirements ๐Ÿ“ฅ `โ‰ˆ03m56s`
" + ], + "metadata": { + "id": "mekHMX3m7oIt" + } + }, + { + "cell_type": "code", + "source": [ + "#@markdown > โ„น๏ธ Runtime does not need to be restarted.\n", + "import os\n", + "import re\n", + "import time\n", + "import torch\n", + "import locale\n", + "import warnings\n", + "import torchaudio\n", + "from time import time\n", + "from pathlib import Path\n", + "from shutil import rmtree\n", + "from zipfile import ZipFile\n", + "from datetime import timedelta\n", + "from rich import print as rprint\n", + "from mimetypes import guess_type\n", + "from psutil import virtual_memory\n", + "from requests import Session, utils\n", + "from contextlib import redirect_stdout\n", + "from IPython.display import clear_output\n", + "\n", + "try:\n", + "\tfrom google.colab import files, runtime\n", + "\tis_colab = True\n", + "except ImportError:\n", + "\tis_colab = False\n", + "\n", + "GPU = torch.cuda.device_count()\n", + "warnings.filterwarnings(\"ignore\")\n", + "locale.getpreferredencoding = lambda: \"UTF-8\"\n", + "\n", + "#-=-=-=-#\n", + "# Metadata\n", + "\n", + "__title__ = \"Coqui XTTS\"\n", + "__author__ = \"kubinka0505\"\n", + "__date__ = \"31st December 2023\"\n", + "__title__ = __title__.replace(\" \", \"_\")\n", + "\n", + "#-=-=-=-#\n", + "# Modules & packages\n", + "\n", + "requirements = {\n", + "\t\"modules\": [\"TTS==0.21.1\", \"langid\", \"unidic-lite\", \"unidic\", \"deepspeed\", \"mutagen\"],\n", + "\t\"packages\": [\"sox\"]\n", + "}\n", + "\n", + "if GPU:\n", + "\tGPU_Name = torch.cuda.get_device_name(torch.cuda.current_device())\n", + "\trprint(\"[b #00CC00]GPU Available![/] [#A0A0A0]({0})[/]\".format(GPU_Name))\n", + "else:\n", + "\trprint(\"[#FF0000][b]GPU Unavailable!\\n[/]Processing will be impossible - requirements will not be installed.[/]\")\n", + "\traise SystemExit()\n", + "\n", + "print(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "\n", + "try:\n", + "\t__modules = requirements[\"modules\"]\n", + "\t__packages = requirements[\"packages\"]\n", + "\n", + "\tif __modules:\n", + "\t\tfor Name in __modules:\n", + "\t\t\t!pip uninstall {Name} -y -q | grep -v \"WARNING: Skip\"\n", + "\t\t\t!pip install -U {Name} --progress-bar off | grep -v \"already\"\n", + "\t\t\tif all((len(__modules) > 1, Name != __modules[-1])):\n", + "\t\t\t\tprint()\n", + "\n", + "\tprint()\n", + "\n", + "\t!pip install numpy==1.22.0 --force-reinstall\n", + "\t!python -m unidic download\n", + "\n", + "\tif __packages:\n", + "\t\tfor Name in __packages:\n", + "\t\t\t!apt-get install --reinstall {Name} -qq > /dev/null 2 >&1\n", + "\t\t\tif all((len(__packages) > 1, Name != __packages[-1])):\n", + "\t\t\t\tprint()\n", + "\n", + "\timport langid\n", + "\tfrom TTS.api import TTS\n", + "\tfrom TTS.tts.configs.xtts_config import XttsConfig\n", + "\tfrom TTS.tts.models.xtts import Xtts\n", + "\tfrom TTS.utils.manage import ModelManager\n", + "\tfrom TTS.utils.generic_utils import get_user_data_dir\n", + "\n", + "\tfrom mutagen import File as mFile\n", + "\n", + "\tos.environ[\"COQUI_TOS_AGREED\"] = \"1\"\n", + "\n", + "\t#-=-=-=-#\n", + "\t# Requests\n", + "\n", + "\tsession = Session()\n", + "\tsession.headers.update(\n", + "\t\t{\n", + "\t\t\t\"User-Agent\":\n", + "\t\t\t\"Mozilla/5.0 (Windows NT 10.0; Win32; x32) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36\"\n", + "\t\t}\n", + "\t)\n", + "\n", + "\t#-=-=-=-#\n", + "\t# Functions\n", + "\n", + "\tdef fdb_size(obj: str, extended_units: bool = False, bits: bool = False, recursive: bool = False) -> str:\n", + "\t\t\"\"\"\n", + "\t\tArgs:\n", + "\t\t\tobj: Bytes integer or string path of existing file or directory.\n", + "\t\t\textended_units: Extends the unit of the result, i.e. \"Megabytes\" instead of \"MB\".\n", + "\t\t\tbits: Uses decimal divider (1000) instead of binary one. (1024)\n", + "\t\t\trecursive: Iterate subdirectories, applicable only if `obj` is directory. (slow!)\n", + "\n", + "\t\tReturns:\n", + "\t\t\tHuman-readable files size string.\n", + "\t\t\"\"\"\n", + "\t\t# Setup\n", + "\n", + "\t\tif bits:\n", + "\t\t\tBits = 1000\n", + "\t\t\tBits_Display_Single = \"bit\"\n", + "\t\t\tBits_Display_Multiple = \"bits\"\n", + "\t\telse:\n", + "\t\t\tBits = 1024\n", + "\t\t\tBits_Display_Single = \"byte\"\n", + "\t\t\tBits_Display_Multiple = \"bytes\"\n", + "\n", + "\t\tUnits = {\n", + "\t\t\t\"\":\t \"\",\n", + "\t\t\t\"K\": \"kilo\",\n", + "\t\t\t\"M\": \"mega\",\n", + "\t\t\t\"G\": \"giga\",\n", + "\t\t\t\"T\": \"tera\",\n", + "\t\t\t\"P\": \"peta\",\n", + "\t\t\t\"E\": \"exa\",\n", + "\t\t\t\"Z\": \"zetta\",\n", + "\t\t\t\"Y\": \"yotta\",\n", + "\t\t\t\"R\": \"ronna\",\n", + "\t\t\t\"Q\": \"quetta\"\n", + "\t\t}\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Search for files\n", + "\n", + "\t\tif isinstance(obj, str):\n", + "\t\t\tpath = str(Path(obj).resolve())\n", + "\n", + "\t\t\tif not os.path.exists(path):\n", + "\t\t\t\traise FileNotFoundError(path)\n", + "\n", + "\t\t\tif os.path.isfile(obj):\n", + "\t\t\t\tFiles = [obj]\n", + "\t\t\telse:\n", + "\t\t\t\tWildcard = \"*\"\n", + "\t\t\t\tif recursive:\n", + "\t\t\t\t\tWildcard += \"*/*\"\n", + "\t\t\t\tFiles = list(Path(obj).glob(Wildcard))\n", + "\t\t\t\tfor File in Files:\n", + "\t\t\t\t\tFiles[Files.index(File)] = str(File.resolve())\n", + "\n", + "\t\t\tFiles = map(os.path.getsize, Files)\n", + "\t\t\tBytes = sum(Files)\n", + "\t\telse:\n", + "\t\t\tBytes = obj\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Calculate integer\n", + "\n", + "\t\tfor Unit in Units:\n", + "\t\t\tif Bytes < Bits:\n", + "\t\t\t\tbreak\n", + "\t\t\tBytes /= Bits\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Ending conditions\n", + "\n", + "\t\tif extended_units:\n", + "\t\t\tif Bytes == 1:\n", + "\t\t\t\tBits_Display = Bits_Display_Single\n", + "\t\t\telse:\n", + "\t\t\t\tBits_Display = Bits_Display_Multiple\n", + "\t\t\tUnit = (Units[Unit] + Bits_Display).capitalize()\n", + "\t\telse:\n", + "\t\t\tUnit += \"B\"\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Add zero to integer\n", + "\n", + "\t\tif \".\" in str(Bytes):\n", + "\t\t\tBytes = round(Bytes, 2)\n", + "\t\t\tBytes = str(Bytes).split(\".\")\n", + "\t\t\tBytes[1] = Bytes[1][:2]\n", + "\t\t\tBytes[1] = Bytes[1].ljust(2, \"0\")\n", + "\t\t\tBytes = \".\".join(Bytes)\n", + "\n", + "\t\tBytes = str(Bytes)\n", + "\n", + "\t\t#-=-=-=-#\n", + "\t\t# Return string\n", + "\n", + "\t\treturn \" \".join((Bytes, Unit))\n", + "\n", + "\t#-=-=-=-#\n", + "\t# Directories\n", + "\n", + "\tDirectory_Main = os.path.abspath(__title__)\n", + "\tDirectory_Primary = os.path.join(Directory_Main, \"Repository\")\n", + "\tDirectory_Inputs = os.path.join(Directory_Main, \"_Inputs\")\n", + "\tDirectory_Outputs = os.path.join(Directory_Main, \"_Outputs\")\n", + "\n", + "\tfor Directory in Directory_Inputs, Directory_Outputs:\n", + "\t\trmtree(Directory, True)\n", + "\t\tos.makedirs(Directory, exist_ok = True)\n", + "except (KeyboardInterrupt, EOFError):\n", + "\tprint(\"\\n\" + \"โ”€\" * 32 + \"\\n\" + \"Operation cancelled by user.\")" + ], + "metadata": { + "id": "ctLvxT2RxEyR", + "cellView": "form" + } + }, + { + "cell_type": "markdown", + "source": [ + "#
**2.** Upload files ๐Ÿ“ค
" + ], + "metadata": { + "id": "h9Sg8W6159zf" + } + }, + { + "cell_type": "code", + "source": [ + "#@markdown > ๐Ÿ—ƒ๏ธ **URL of `ZIP` archive with files is supported.**\n", + "\n", + "Direct_URL = \"\" #@param {type: \"string\"}\n", + "Allow_non_WAV_URL = True #@param {type: \"boolean\"}\n", + "__URL_Fail = False if Direct_URL else True\n", + "\n", + "#@markdown ---\n", + "\n", + "#@markdown > โ„น๏ธ `Lazy Unpacking` determines whether **files from the archive should only be unpacked if their file name extension** is in the `Formats` variable.\n", + "\n", + "Lazy_Unpacking = True #@param {type: \"boolean\"}\n", + "Formats = \"AAC, AIFF, ALAC, APE, FLAC, M4A, MP3, OGG, OPUS, WAV, WV\" #@param {type: \"string\"}\n", + "Formats = [Format.lower().strip() for Format in Formats.split(\",\")]\n", + "\n", + "#@markdown ---\n", + "\n", + "Ask_to_upload_files_if_download_succeeds = True #@param {type: \"boolean\"}\n", + "Remove_previously_uploaded_files_and_subdirectories = True #@param {type: \"boolean\"}\n", + "\n", + "#-=-=-=-#\n", + "\n", + "if \"rmtree\" not in locals():\n", + "\traise SystemExit(\"Requirements were not installed!\\nPlease run the first cell.\")\n", + "\n", + "if \"Files\" not in locals():\n", + "\tFiles = []\n", + "\n", + "#-=-=-=-#\n", + "\n", + "__Directory_Base = os.getcwd()\n", + "\n", + "# `os.chdir` since `files.upload` does not have the target directory argument\n", + "os.chdir(Directory_Inputs)\n", + "\n", + "if Remove_previously_uploaded_files_and_subdirectories:\n", + "\tFiles_Inputs = []\n", + "\tfor File in Path(Directory_Inputs).rglob(\"*\"):\n", + "\t\tFile = str(File.resolve())\n", + "\t\tif is_colab:\n", + "\t\t\tif \".ipynb_checkpoints\" not in os.path.basename(File):\n", + "\t\t\t\tFiles_Inputs.append(File)\n", + "\t\telse:\n", + "\t\t\tFile_Inputs.append(File)\n", + "\n", + "\tfor File in Files_Inputs:\n", + "\t\tif os.path.isfile(File):\n", + "\t\t\tos.remove(File)\n", + "\t\t\trprint('Removed [b #44AAFF]\"{0}\"[/]'.format(\n", + "\t\t\t\tos.path.relpath(File, Directory_Inputs)\n", + "\t\t\t))\n", + "\n", + "\tfor File in Files_Inputs:\n", + "\t\tif os.path.isdir(File):\n", + "\t\t\trmtree(File)\n", + "\n", + "\tif Files_Inputs:\n", + "\t\tprint(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "\n", + "\tFiles = []\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Allowed_Specifiers = \"http\", \"https\", \"ftp\"\n", + "Allowed_Specifiers = [Specifier + \"://\" for Specifier in Allowed_Specifiers]\n", + "Allowed_Specifiers = tuple(Allowed_Specifiers)\n", + "\n", + "if Direct_URL.lower().startswith(Allowed_Specifiers):\n", + "\tfor Delimiter in ((\"?\", \"&\", \"#\")):\n", + "\t\tDirect_URL = Direct_URL.split(Delimiter)[0]\n", + "\n", + "\tDownloaded_File_Location = utils.unquote(Direct_URL.split(\"/\")[-1])\n", + "\n", + "\t__URL_Fail = False\n", + "\ttry:\n", + "\t\tSession_obj = session.get(Direct_URL, stream = 1)\n", + "\texcept Exception:\n", + "\t\t__URL_Fail = True\n", + "\n", + "\tif __URL_Fail:\n", + "\t\trprint(\"[b #FF0000]Provided URL is invalid![/]\")\n", + "\t\t__URL_Fail = True\n", + "\n", + "\tif not __URL_Fail:\n", + "\t\twith Session_obj as Site:\n", + "\t\t\tif Site.ok:\n", + "\t\t\t\tSite_MIME = Site.headers[\"content-type\"].lower().split()[0].split(\";\")[0].split(\"/\")\n", + "\t\t\t\tif Site_MIME[0] == \"audio\":\n", + "\t\t\t\t\tif any((Site_MIME[1].endswith(\"wav\"), Allow_non_WAV_URL)):\n", + "\t\t\t\t\t\twith open(Downloaded_File_Location, \"wb\") as File:\n", + "\t\t\t\t\t\t\trprint(f'Downloading [b #00CC00]\"{Downloaded_File_Location}\"[/]...')\n", + "\n", + "\t\t\t\t\t\t\tfor Chunk in Site.iter_content(chunk_size = 1024):\n", + "\t\t\t\t\t\t\t\tif Chunk:\n", + "\t\t\t\t\t\t\t\t\tFile.write(Chunk)\n", + "\t\t\t\t\t\t\tFiles.append(Downloaded_File_Location)\n", + "\t\t\t\t\telse:\n", + "\t\t\t\t\t\trprint(\"[b #FF0000]Permission to download non-WAV files was not granted.[/]\")\n", + "\t\t\t\t\t\t__URL_Fail = True\n", + "\t\t\t\telse:\n", + "\t\t\t\t\t# ZIP Archive Handling\n", + "\t\t\t\t\tif \"/\".join(Site_MIME) == \"application/zip\":\n", + "\t\t\t\t\t\twith open(Downloaded_File_Location, \"wb\") as File:\n", + "\t\t\t\t\t\t\trprint(f'Downloading [b #00CC00]\"{Downloaded_File_Location}\"[/]...')\n", + "\n", + "\t\t\t\t\t\t\tfor Chunk in Site.iter_content(chunk_size = 1024):\n", + "\t\t\t\t\t\t\t\tif Chunk:\n", + "\t\t\t\t\t\t\t\t\tFile.write(Chunk)\n", + "\n", + "\t\t\t\t\t\ttry:\n", + "\t\t\t\t\t\t\tArchive_Files_Amount = 0\n", + "\t\t\t\t\t\t\twith ZipFile(Downloaded_File_Location) as Archive:\n", + "\t\t\t\t\t\t\t\tfor Archive_File in Archive.infolist():\n", + "\t\t\t\t\t\t\t\t\tif Lazy_Unpacking:\n", + "\t\t\t\t\t\t\t\t\t\tif os.path.splitext(Archive_File.filename.lower())[1][1:] in Formats:\n", + "\t\t\t\t\t\t\t\t\t\t\tArchive_Files_Amount += 1\n", + "\t\t\t\t\t\t\t\t\t\t\tArchive.extract(Archive_File)\n", + "\t\t\t\t\t\t\t\t\telse:\n", + "\t\t\t\t\t\t\t\t\t\tArchive_Files_Amount += 1\n", + "\t\t\t\t\t\t\t\t\t\tArchive.extract(Archive_File)\n", + "\n", + "\t\t\t\t\t\t\tos.remove(Downloaded_File_Location)\n", + "\n", + "\t\t\t\t\t\t\t#-=-=-=-#\n", + "\n", + "\t\t\t\t\t\t\tfor File in Path().rglob(\"*.*\"):\n", + "\t\t\t\t\t\t\t\tFile = str(File.resolve())\n", + "\n", + "\t\t\t\t\t\t\t\tif os.path.isfile(File):\n", + "\t\t\t\t\t\t\t\t\tFiles.append(File)\n", + "\n", + "\t\t\t\t\t\t\trprint(f\"[b #00CC00]{Archive_Files_Amount} files from main directory were extracted successfully![/]\")\n", + "\t\t\t\t\t\texcept RuntimeError:\n", + "\t\t\t\t\t\t\trprint(\"[b #FF0000]Files extraction was not successful due to password requirement, file corruption or other internal error.[/]\")\n", + "\t\t\t\t\t\t\t__URL_Fail = True\n", + "\t\t\t\t\telse:\n", + "\t\t\t\t\t\trprint(\"[b #FF0000]Provided URL is not an audio file.[/] [i #A0A0A0](undetected MIME type in header)[/]\")\n", + "\t\t\t\t\t\t__URL_Fail = True\n", + "\t\t\telse:\n", + "\t\t\t\trprint(\"[b #FF0000]Failed to fetch the URL due to {0} status code. ({1})[/]\".format(\n", + "\t\t\t\t\tSite.status_code, Site.reason.title()\n", + "\t\t\t\t))\n", + "\t\t\t\t__URL_Fail = True\n", + "\n", + "#-=-=-=-#\n", + "# Upload files\n", + "\n", + "__Cancel_Permission = \"\" if __URL_Fail else \" [i #A0A0A0](can be cancelled)[/]\"\n", + "\n", + "if any((Ask_to_upload_files_if_download_succeeds, __URL_Fail)):\n", + "\tprint(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "\trprint(f\"Upload [b #44AAFF]AUDIO[/] files{__Cancel_Permission}\")\n", + "\n", + "\ttry:\n", + "\t\tfor File in files.upload():\n", + "\t\t\tFiles.append(File)\n", + "\texcept TypeError:\n", + "\t\tpass\n", + "\texcept (KeyboardInterrupt, EOFError):\n", + "\t\trprint(\"\\n\\n[b #FFCC00]File upload cancelled.[/]\")\n", + "\n", + "\tFiles = [str(Path(File).resolve()) for File in Files]\n", + "\tif is_colab:\n", + "\t\tFiles = [File for File in Files if os.path.basename(File) != \".ipynb_checkpoints\"]\n", + "\tFiles = list(set(Files))\n", + "\n", + "#-=-=-=-#\n", + "# Check for files\n", + "\n", + "Files = [os.path.abspath(File) for File in Files]\n", + "\n", + "err = 0\n", + "try:\n", + "\t# Use this later for string formatting\n", + "\tLongest_File_Name_Length = [File.split(Directory_Inputs)[1][1:] for File in Files]\n", + "\tLongest_File_Name_Length.sort(key = len)\n", + "\tLongest_File_Name_Length = len(Longest_File_Name_Length[-1])\n", + "except IndexError:\n", + "\terr = 1\n", + "\n", + "if err:\n", + "\traise SystemExit(\"No uploaded files has been found.\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "os.chdir(__Directory_Base)" + ], + "metadata": { + "cellView": "form", + "id": "c5fYSLEj5_zv" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Verify files and convert them to `WAV` โš™๏ธ
\n", + "#@markdown > โš ๏ธ **Files whose [MIME type](https://wikipedia.org/wiki/Media_type)'s first segment will not be detected as `audio` will be removed without warning.**\n", + "if \"Files\" not in locals():\n", + "\traise SystemExit(\"Requirements were not installed!\\nPlease run the first cell.\")\n", + "\n", + "if not Files:\n", + "\traise SystemExit(\"No files has been found!\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Target = \"WAV\"\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Target = Target.split()[0].upper().strip(\".\")\n", + "\n", + "for Input in Files:\n", + "\tInput_Name = os.path.basename(Input)\n", + "\n", + "\ttry:\n", + "\t\tInput_MIME = mFile(Input).mime\n", + "\texcept AttributeError:\n", + "\t\tInput_MIME = guess_type(Input)\n", + "\tInput_MIME = Input_MIME[0].lower().split(\"/\")\n", + "\n", + "\tif Input_MIME[0] == \"audio\":\n", + "\t\tif Input_MIME[1] != Target.lower():\n", + "\t\t\tos.environ[\"FILE_INPUT\"] = Input\n", + "\t\t\tos.environ[\"FILE_OUTPUT\"] = os.path.splitext(Input)[0] + f\".{Target.lower()}\"\n", + "\n", + "\t\t\trprint(f'[b #00CC00]\"{Input_Name}\" is not a {Target} file, converting...[/]')\n", + "\t\t\t!ffmpeg -i \"$FILE_INPUT\" -hide_banner -loglevel 16 \\\n", + "\t\t\t\t-map_metadata 0 -map_metadata 0:s:0 \\\n", + "\t\t\t\t-fflags +bitexact -flags:v +bitexact -flags:a +bitexact \\\n", + "\t\t\t\t\"$FILE_OUTPUT\"\n", + "\n", + "\t\t\tFiles[Files.index(Input)] = os.environ[\"FILE_OUTPUT\"]\n", + "\t\t\tos.remove(Input)\n", + "\telse:\n", + "\t\trprint(f'[b #FF0000]\"{Input_Name}\" is not an audio file, removing[/]')\n", + "\t\tFiles.remove(Input)\n", + "\t\tos.remove(Input)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "if not Files:\n", + "\traise SystemExit(\"No files has been found!\")" + ], + "metadata": { + "cellView": "form", + "id": "yeSfavNJ9ndO" + } + }, + { + "cell_type": "markdown", + "source": [ + "#
**3.** Generate ๐Ÿ—ฃ๏ธ
" + ], + "metadata": { + "id": "i0dxtaLy9_eN" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Setup `(โ‰ˆ02m19s)` โš™๏ธ
\n", + "# For unknown reasons, takes over 6 minutes to install while put in the first cell\n", + "\n", + "# Download XTTS\n", + "model_name = \"tts_models/multilingual/multi-dataset/xtts_v2\"\n", + "model_path = os.path.join(get_user_data_dir(\"tts\"), model_name.replace(\"/\", \"--\"))\n", + "\n", + "config_json = os.path.join(model_path, \"config.json\")\n", + "vocab_json = os.path.join(model_path, \"vocab.json\")\n", + "\n", + "if os.path.exists(model_path):\n", + "\trmtree(model_path)\n", + "\n", + "# Download model\n", + "with redirect_stdout(None):\n", + "\tModelManager().download_model(model_name)\n", + "\n", + "config = XttsConfig()\n", + "config.load_json(config_json)\n", + "\n", + "# Loading model\n", + "model = Xtts.init_from_config(config)\n", + "model.load_checkpoint(\n", + "\tconfig,\n", + "\tcheckpoint_path = os.path.join(model_path, \"model.pth\"),\n", + "\tvocab_path = vocab_json,\n", + "\teval = True,\n", + "\tuse_deepspeed = True,\n", + ")\n", + "model.cuda()\n", + "\n", + "supported_languages = config.languages" + ], + "metadata": { + "id": "8CTi2dx0L-mB", + "cellView": "form" + } + }, + { + "cell_type": "code", + "source": [ + "#@title #
**Upload prompts file** ๐Ÿ“๐Ÿ“ค
\n", + "\n", + "Prompts = \"\"\"\n", + "\n", + "# This line is ignored\n", + "\n", + "# Please write your dialogs here\n", + "\n", + "\"\"\"\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Languages = {\n", + "\t#\"id\": (\"long_name\", characters_limit),\n", + "\t\"en\": [\"English\", 250],\n", + "\t\"es\": [\"Spanish\", 239],\n", + "\t\"fr\": [\"French\", 273],\n", + "\t\"de\": [\"Deutsch\", 253],\n", + "\t\"it\": [\"Italian\", 213],\n", + "\t\"pt\": [\"Portuguese\", 203],\n", + "\t\"tr\": [\"Turkish\", 226],\n", + "\t\"ru\": [\"Russian\", 182],\n", + "\t\"nl\": [\"Dutch\", 251],\n", + "\t\"pl\": [\"Polish\", 224],\n", + "\t\"cs\": [\"Czech\", 186],\n", + "\t\"ar\": [\"Arabic\", 166],\n", + "\t\"zh-cn\": [\"Chinese\", 82],\n", + "\t\"ja\": [\"Japanese\", 71],\n", + "\t\"ko\": [\"Korean\", 95],\n", + "\t\"hu\": [\"Hungarian\", 224]\n", + "}\n", + "\n", + "#@markdown - **Can be modified inside this cell as a `Prompts` multiline string variable**\n", + "\n", + "Upload_Prompt_File = True #@param {type: \"boolean\"}\n", + "\n", + "#@markdown - Saved to `_prompt.txt`, inside main directory.\n", + "#@markdown - Separated by pipe: `|`\n", + "#@markdown\n", + "#@markdown ---\n", + "\n", + "#@markdown ### Parameters:\n", + "#@markdown  `speaker_name``|``language_code``|``Some text``|``OUTPUT_NAME`\n", + "\n", + "#@markdown
\n", + "\n", + "#@markdown `speaker_name`: Existing file without extension inside `/content/Coqui_XTTS/_inputs` directory.\n", + "\n", + "#@markdown `language_code`: Short language code like `en` (English), `de` (Deutsch) [etc](https://hf.co/coqui/XTTS-v2#languages).\n", + "#@markdown - *If `auto`, `none` or `x`, language is being recognized from prompt by the [`langid`](https://github.com/saffsd/langid.py) module.*\n", + "\n", + "#@markdown `Some text`: A string shorter than the number of characters assigned to the language.\n", + "#@markdown - [[**Languages character limits**]](https://github.com/coqui-ai/TTS/blob/5dcc16d1931538e5bce7cb20c1986df371ee8cd6/TTS/tts/layers/xtts/tokenizer.py#L597-L614)\n", + "#@markdown - *The reason for the limit is models inability for longer text processing.*\n", + "#@markdown - *Colab prompt **display** is truncated to `75` characters.*\n", + "\n", + "#@markdown `OUTPUT_NAME`: Output file name in `Directory_Outputs` directory.\n", + "#@markdown - *Optional, if not passed file is saved as `Some_text``.wav`*\n", + "#@markdown - *Truncated to 150 characters by default.*\n", + "\n", + "#@markdown ---\n", + "\n", + "#@markdown ## Example file structure\n", + "\n", + "#@markdown ```ini\n", + "#@markdown # Lines that are empty or that start with a #, like this one are ignored\n", + "#@markdown # Each element of list is stripped out of spaces - it can look like a table\n", + "#@markdown\n", + "#@markdown # 01. Dialogs of former/USA presidents alive in 2024\n", + "#@markdown biden | x | Hi Barack and Donald | HI_BIDEN\n", + "#@markdown obama | x | Hi Joe and Donald | HI_OBAMA\n", + "#@markdown # kennedy | x | I should not be here | HI_KENNEDY\n", + "#@markdown # adams | x | I was not even recorded | HI_ADAMS\n", + "#@markdown trump | x | Hi Joe and Barrack | HI_TRUMP\n", + "#@markdown\n", + "#@markdown # 02. (...)\n", + "#@markdown speaker_01|it|Ora so parlare italiano!\n", + "#@markdown speaker_02|en|I can speak in english\n", + "#@markdown speaker_01|de|I am experimenting\n", + "#@markdown\n", + "#@markdown # 03. (...)\n", + "#@markdown ```\n", + "\n", + "#-=-=-=-#\n", + "\n", + "IDs = {v[0]: k for k, v in Languages.items()}\n", + "\n", + "if Upload_Prompt_File:\n", + "\tfn = \"_prompt.txt\"\n", + "\tfn = os.path.join(Directory_Inputs, fn)\n", + "\n", + "\tif os.path.exists(fn):\n", + "\t\tos.remove(fn)\n", + "\n", + "\terr = 0\n", + "\ttry:\n", + "\t\tfiles.upload_file(fn)\n", + "\n", + "\t\twith open(fn, \"r\", encoding = \"UTF-8\") as File:\n", + "\t\t\tPrompts = File.read()\n", + "\texcept ValueError:\n", + "\t\terr = 1\n", + "\n", + "\tif err:\n", + "\t\tprint()\n", + "\t\trprint(f\"[b #FFCC00] File upload aborted, using prompts variable.[/]\")\n", + "\t\tprint(\"\\n\" + \"โ”€\" * 32)\n", + "\n", + "#-=-=-=-#\n", + "# Old\n", + "\n", + "Prompts_List = Prompts.strip(\"\\n\")\n", + "Prompts_List = Prompts_List.split(\"\\n\")\n", + "Prompts_List = [Line for Line in Prompts_List if Line]\n", + "__Lines_Old = len(Prompts_List)\n", + "\n", + "# New\n", + "Prompts_List = [Line for Line in Prompts_List if not Line.startswith(\"#\")]\n", + "__Lines_New = len(Prompts_List)\n", + "\n", + "__Ignored = __Lines_Old - __Lines_New\n", + "\n", + "print()\n", + "rprint(\"[b #{0}]Found {1} prompts, {2} {3} ignored.[/]\".format(\n", + "\t\"00CC00\" if __Lines_New else \"FF0000\",\n", + "\t__Lines_New, __Ignored,\n", + "\t\"was\" if __Ignored < 2 else \"were\"\n", + "))" + ], + "metadata": { + "id": "WyX8llI5-4O7", + "cellView": "form" + } + }, + { + "cell_type": "code", + "source": [ + "#@title #
**Run**
\n", + "\n", + "def commaFix(s: str) -> str:\n", + "\treturn re.sub(\"([^\\x00-\\x7F]|\\w)(\\.|\\ใ€‚|\\?)\", r\"\\1 \\2\\2\", s)\n", + "\n", + "#@markdown > ## โš ๏ธ **Previously processed files with same speakers will be removed without warning!**\n", + "\n", + "#@markdown > ## ๐Ÿ“‰ **Returns `24 000 Hz` mono files.**\n", + "#@markdown >  \n", + "#@markdown > #### *See also:* [**HiFi GAN BWE**](https://colab.research.google.com/github/kubinka0505/colab-notebooks/blob/master/Notebooks/AI/Audio/Upscale/HiFi_GAN_BWE.ipynb) โœจ\n", + "\n", + "#@markdown ---\n", + "\n", + "#@markdown > *Performs `Prompt = re.sub(\"([^\\x00-\\x7F]|\\w)(\\.|\\ใ€‚|\\?)\", r\"\\1 \\2\\2\", Prompt)` for each `Prompt`*\n", + "\n", + "Use_Comma_Fix = True #@param {type: \"boolean\"}\n", + "Max_Prompt_Display_Length = 75\n", + "Truncate_Output_Name_After = 150\n", + "\n", + "#@markdown ---\n", + "\n", + "#@markdown > ### *Internal Coqui XTTS variables. Do not modify unless you are sure what you are doing.*\n", + "Length_GPT_Condition = 30 #@param {type: \"integer\"}\n", + "Length_GPT_Condition_Chunk = 4 #@param {type: \"integer\"}\n", + "Length_Reference_Max = 60 #@param {type: \"integer\"}\n", + "\n", + "#@markdown > *If `Length_Reference_Max` is `0`, the seconds of `speaker_name` file are taken.*\n", + "\n", + "Repetition_Penalty = 5.0 #@param {type: \"number\"}\n", + "Temperature = 0.75 # @param {type:\"slider\", min:0.01, max:0.99, step:0.01}\n", + "\n", + "#@markdown ---\n", + "\n", + "#@markdown ### Other settings\n", + "Clear_Colab_console_output_after_each_prompt = False #@param {type: \"boolean\"}\n", + "\n", + "#-=-=-=-#\n", + "\n", + "if not \"model\" in locals():\n", + "\traise Exception(\"No model has been found! Please run the previous cell.\")\n", + "\n", + "#-=-=-=-#\n", + "# Preprocess prompts\n", + "\n", + "Prompts_List = Prompts.strip(\"\\n\")\n", + "Prompts_List = Prompts_List.split(\"\\n\")\n", + "\n", + "Prompts_List = [\n", + "\tLine for Line in Prompts_List\n", + "\tif not Line.startswith(\"#\")\n", + "]\n", + "\n", + "IDs = {v[0]: k for k, v in Languages.items()}\n", + "Prompts_List = [Line for Line in Prompts_List if Line]\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Runtime = time()\n", + "Counter = 1\n", + "\n", + "for Line in Prompts_List:\n", + "\tElements = Line.split(\"|\")\n", + "\tElements = [Element.strip() for Element in Elements]\n", + "\n", + "\t#-=-=-=-#\n", + "\n", + "\tSpeaker_Name = Elements[0]\n", + "\tLanguage = Elements[1]\n", + "\tPrompt_String = Elements[2]\n", + "\n", + "\tSpeaker_Path = os.path.join(Directory_Inputs, Speaker_Name) + \".wav\"\n", + "\tSpeaker_Display = os.path.splitext(os.path.basename(Speaker_Path))[0]\n", + "\n", + "\tif Language.lower().startswith((\"auto\", \"none\", \"x\")):\n", + "\t\tLanguage = None\n", + "\n", + "\tif Use_Comma_Fix:\n", + "\t\tPrompt_String = commaFix(Prompt_String)\n", + "\n", + "\tif Language:\n", + "\t\tif Language in Languages:\n", + "\t\t\tLanguage = IDs[Languages[Language][0]]\n", + "\t\telse:\n", + "\t\t\traise ValueError(\"Unsupported language\")\n", + "\telse:\n", + "\t\tPredicted = langid.classify(Prompt_String)[0].strip()\n", + "\n", + "\t\tif Predicted == \"zh\":\n", + "\t\t\tPredicted = \"zh-cn\"\n", + "\n", + "\t\tif Language != Predicted:\n", + "\t\t\tLanguage = Predicted\n", + "\n", + "\tMaxLen = Languages[Language][1]\n", + "\tLanguage_Display = Languages[Language][0]\n", + "\n", + "\t#-=-=-=-#\n", + "\t# Errors\n", + "\n", + "\tif os.path.basename(Speaker_Path) not in os.listdir(Directory_Inputs):\n", + "\t\traise FileNotFoundError(Speaker_Path)\n", + "\n", + "\tif len(Prompt_String) > MaxLen:\n", + "\t\trprint(\"[b #44AAFF]Prompt string length exceeds {}, truncating[/]\")\n", + "\t\tPrompt_String = Prompt_String[:MaxLen]\n", + "\n", + "\tif len(Prompt_String) < Max_Prompt_Display_Length:\n", + "\t\tPrompt_Display = f'\"{Prompt_String}\"'\n", + "\telse:\n", + "\t\tPrompt_Display = f'\"{Prompt_String[:Max_Prompt_Display_Length]}(...)\"'\n", + "\n", + "\t#-=-=-=-#\n", + "\t# Print information\n", + "\n", + "\tCounter_Display = str(Counter).rjust(len(str(len(Prompts_List))) + 1, \"0\")\n", + "\n", + "\tprint(f\"{Counter_Display}.\")\n", + "\tprint(\" Speaker Name: \", Speaker_Display)\n", + "\tprint(\" Language: \", \"{0} ({1} characters limit)\".format(Language_Display, MaxLen))\n", + "\tprint(\" Prompt: \", Prompt_Display)\n", + "\n", + "\t#-=-=-=-#\n", + "\t# Setup output file name\n", + "\n", + "\tif len(Elements) > 3:\n", + "\t\toutput_name = Elements[3]\n", + "\t\trprint(\" Output Name: \", output_name)\n", + "\telse:\n", + "\t\toutput_name = re.sub(r\"[,.;@#?!&$]+\\ *\", \"_\", Prompt_String).replace(\"_\", \" \")\n", + "\t\toutput_name = output_name.split()\n", + "\t\toutput_name = \"_\".join([x for x in output_name if output_name])\n", + "\n", + "\toutput_name = output_name[:Truncate_Output_Name_After]\n", + "\toutput_path = os.path.join(Directory_Outputs, Speaker_Display, output_name + \".wav\")\n", + "\toutput_path = os.path.abspath(output_path)\n", + "\n", + "\toutput_dir = os.path.dirname(output_path)\n", + "\n", + "\tif not os.path.exists(output_dir):\n", + "\t\tos.makedirs(output_dir, exist_ok = True)\n", + "\n", + "\tif os.path.exists(output_path):\n", + "\t\tos.remove(output_path)\n", + "\n", + "\t# Run\n", + "\tif not Length_Reference_Max:\n", + "\t\tLength_Reference_Max = round(mFile(Speaker_Path).info.length)\n", + "\n", + "\ttorch.cuda.empty_cache()\n", + "\n", + "\t(gpt_cond_latent, speaker_embedding) = model.get_conditioning_latents(\n", + "\t\taudio_path = Speaker_Path,\n", + "\t\tgpt_cond_len = Length_GPT_Condition,\n", + "\t\tgpt_cond_chunk_len = Length_GPT_Condition_Chunk,\n", + "\t\tmax_ref_length = Length_Reference_Max\n", + "\t)\n", + "\n", + "\tout = model.inference(\n", + "\t\tPrompt_String, Language,\n", + "\t\tgpt_cond_latent, speaker_embedding,\n", + "\t\trepetition_penalty = Repetition_Penalty,\n", + "\t\ttemperature = Temperature,\n", + "\t)\n", + "\n", + "\ttorchaudio.save(\n", + "\t\toutput_path,\n", + "\t\ttorch.tensor(out[\"wav\"]).unsqueeze(0),\n", + "\t\t24000\n", + "\t)\n", + "\n", + "\tif Clear_Colab_console_output_after_each_prompt:\n", + "\t\tif Line != Prompts_List[-1]:\n", + "\t\t\tclear_output(wait = True)\n", + "\telse:\n", + "\t\tprint()\n", + "\n", + "\t\trprint('[b][#44AAFF]\\nSaved to \"{0}\" [#A0A0A0]({1}s) ({2})[/][/]'.format(\n", + "\t\t\tos.path.relpath(output_path, Directory_Outputs),\n", + "\t\t\tround(mFile(output_path).info.length, 3),\n", + "\t\t\tfdb_size(output_path)\n", + "\t\t))\n", + "\n", + "\t\tif Line != Prompts_List[-1]:\n", + "\t\t\tprint(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "\n", + "\tCounter += 1\n", + "\n", + "#-=-=-=-#\n", + "\n", + "__Run_Time = time() - Runtime\n", + "print(\"\\n\" + \"โ”€\" * 32 + \"\\n\")\n", + "rprint(\"[b #00CC00]Done![/]\")\n", + "rprint(\"Runtime: [b #44AAFF]{0}[/] [i #A0A0A0](avg. {1} per line)[/]\".format(\n", + "\tstr(timedelta(seconds = __Run_Time))[2:-3],\n", + "\tstr(timedelta(seconds = __Run_Time / len(Prompts_List)))[2:-3]\n", + "))" + ], + "metadata": { + "id": "QCrlHuDDWpB2", + "cellView": "form" + } + }, + { + "cell_type": "markdown", + "source": [ + "#
Utils โš™๏ธ
" + ], + "metadata": { + "id": "XfDlrVA9Qc1x" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Convert output files to `FLAC` ๐ŸŽถ
\n", + "\n", + "Bit_Depth = \"24-bit\" #@param [\"16-bit\", \"24-bit\"]\n", + "Bit_Depth = Bit_Depth.split(\"-\")[0]\n", + "Normalize_dB = 1 # @param {type: \"slider\", min: -6, max: 1, step: 1}\n", + "#@markdown > โ„น๏ธ To **disable** normalization, set `Normalize_dB` to **`1`**.\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Target = \"FLAC\"\n", + "Target = Target.split()[0].lower().strip(\".\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "os.environ[\"BIT_DEPTH\"] = \"-b \" + Bit_Depth\n", + "os.environ[\"NORMALIZE\"] = (\"--norm \" + str(Normalize_dB)) if Normalize_dB < 1 else \"\"\n", + "\n", + "for File in Path(Directory_Outputs).rglob(\"*.*\"):\n", + "\tInput = str(File.resolve())\n", + "\n", + "\tif os.path.isfile(Input):\n", + "\t\tInput_MIME = mFile(Input).mime[0].lower().split(\"/\")\n", + "\t\tInput_Name = os.path.relpath(Input, Directory_Outputs)\n", + "\n", + "\t\tOutput_FLAC = os.path.splitext(Input)[0], f\".{Target.lower()}\"\n", + "\t\tOutput_Temp = \"_\".join(Output_FLAC)\n", + "\t\tOutput_FLAC = \"\".join(Output_FLAC)\n", + "\n", + "\t\tos.environ[\"INPUT\"] = Input\n", + "\t\tos.environ[\"OUTPUT\"] = Output_Temp\n", + "\n", + "\t\trprint('[b i]{1}onverting [#44AAFF]\"{0}\"[/] to FLAC...[/]'.format(\n", + "\t\t\tInput_Name,\n", + "\t\t\t(\"rec\" if Input_MIME[1] == \"flac\" else \"c\").capitalize()\n", + "\t\t))\n", + "\n", + "\t\t!sox \"$INPUT\" -D $BIT_DEPTH -C 8 $NORMALIZE --comment \"\" -G \"$OUTPUT\" -V0\n", + "\n", + "\t\tos.remove(Input)\n", + "\t\tos.rename(Output_Temp, Output_FLAC)" + ], + "metadata": { + "cellView": "form", + "id": "nxkupjCJpf5R" + } + }, + { + "cell_type": "code", + "source": [ + "#@title
Download archive with output files ๐Ÿ—ƒ๏ธ
\n", + "Emphasize_archive_file_name = True #@param {type: \"boolean\"}\n", + "Beggining = \"!_\" if Emphasize_archive_file_name else \"\"\n", + "\n", + "#@markdown > โ„น๏ธ Pushes the archive file to top of the explorer's file list (**if** it's sorted by name) by putting `!_` to its file name beggining.\n", + "\n", + "#-=-=-=-#\n", + "\n", + "__Padding = 7\n", + "Archive_File = Beggining + \"_\".join((__title__, str(time()).split(\".\")[1][:__Padding].rjust(__Padding, \"0\")))\n", + "Archive_File += \".zip\"\n", + "Archive_File = os.path.abspath(Archive_File)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "# Archive Creation\n", + "print(\"Making Archive...\")\n", + "with ZipFile(Archive_File, \"w\", 14, 1, 9) as Archive:\n", + "\tfor File in Path(Directory_Outputs).rglob(\"*.*\"):\n", + "\t\tFile = str(File.resolve())\n", + "\n", + "\t\tif os.path.isfile(File):\n", + "\t\t\tArcName = os.path.relpath(File, Directory_Outputs)\n", + "\n", + "\t\t\trprint(f'\\t[b i]Writing [#44AACC]\"{ArcName}\"[/]...')\n", + "\t\t\tArchive.write(File, ArcName)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "files.download(Archive_File)" + ], + "metadata": { + "cellView": "form", + "id": "rpPfi2g7gnTi" + } + }, + { + "cell_type": "code", + "source": [ + "#@title Terminate runtime after specified time ๐Ÿ”Œ\n", + "#@markdown In case if you don't want to waste this account's resources while performing other tasks.\n", + "#@markdown > ### **This cancellable action is irreversible and will result in loss of ALL session data!**\n", + "\n", + "#@markdown
\n", + "#@markdown
\n", + "#@markdown Time sheet\n", + "#@markdown\n", + "#@markdown
\n", + "#@markdown\n", + "#@markdown | Seconds | Minutes |\n", + "#@markdown |:-|:-|\n", + "#@markdown | `60` | `1` |\n", + "#@markdown | `300` | `5` |\n", + "#@markdown | `600` | `10` |\n", + "#@markdown | `1800` | `30` |\n", + "#@markdown | `3600` | `60` |\n", + "#@markdown
\n", + "\n", + "#@markdown ---\n", + "\n", + "Seconds_Default = 30\n", + "Seconds = 300 # @param {type: \"integer\"}\n", + "\n", + "if Seconds < 0:\n", + "\trprint(f\"[b][#FFCC00]Seconds are[/] [#FF0000]< 0[/][#FFCC00], defaulting to[/] [#FF0000]{Seconds_Default}[/][#FFCC00].[/][/]\")\n", + "\n", + "__Spaces = \" \" * 8\n", + "\n", + "\n", + "\n", + "if is_colab:\n", + "\ttry:\n", + "\t\tfor i in range(Seconds, -1, -1):\n", + "\t\t\tprint(\"\\r\", end = f\"Runtime will be terminated in {i} seconds...\" + __Spaces)\n", + "\n", + "\t\trprint(\"\\n\\n[b #FF0000]Runtime has been terminated.[/]\")\n", + "\t\truntime.unassign()\n", + "\texcept (KeyboardInterrupt, EOFError):\n", + "\t\tprint()\n", + "\t\trprint(\"[b #FF0000]Operation cancelled by user.[/]\")\n", + "else:\n", + "\trprint(\"[b #FFCC00]Not in Colab, unsupported.[/]\")" + ], + "metadata": { + "id": "rhKs_AmESZew", + "cellView": "form" + } + } + ] +} \ No newline at end of file diff --git a/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/Run.py b/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/Run.py new file mode 100644 index 0000000..4193b8c --- /dev/null +++ b/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/Run.py @@ -0,0 +1,29 @@ +"""Static version of Coqui XTTS Notebook.""" +__title__ = "Coqui XTTS" +__author__ = "kubinka0505" +__date__ = "31st December 2023" +__title__ = __title__.replace(" ", "_") + +#-=-=-=-# + +# Does not print information about output file +Clear_console_output_after_each_prompt = False + +# If None, the first found ".txt" file from the current directory is taken +Prompts_File = "prompts.txt" + +Pause_on_finish = False + +#-=-=-=-# + +exec(open("src/setup_variables.pyw", "r", encoding = "UTF-8").read()) +exec(open("src/setup_prompts.pyw", "r", encoding = "UTF-8").read()) +exec(open("src/setup_tts.pyw", "r", encoding = "UTF-8").read()) + +__Run_Time_Start = time() - Runtime_Start +print("Setup took {0}".format( + str(timedelta(seconds = __Run_Time_Start))[2:-3]) +) + +exec(open("src/setup_runner.pyw", "r", encoding = "UTF-8").read()) +exec(open("src/setup_end.pyw", "r", encoding = "UTF-8").read()) \ No newline at end of file diff --git a/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/src/setup_end.pyw b/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/src/setup_end.pyw new file mode 100644 index 0000000..353395f --- /dev/null +++ b/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/src/setup_end.pyw @@ -0,0 +1,5 @@ +print("\a") + +if Pause_on_finish: + cmd = "pause" if is_NT else 'read -n1 -r -p "Press any key to continue. . ." key' + os.system(cmd) \ No newline at end of file diff --git a/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/src/setup_prompts.pyw b/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/src/setup_prompts.pyw new file mode 100644 index 0000000..2f39a97 --- /dev/null +++ b/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/src/setup_prompts.pyw @@ -0,0 +1,46 @@ +# Setup prompts +rprint("[b #00CC00]Retrieving prompts...[/]") + +IDs = {v[0]: k for k, v in Languages.items()} + +#-=-=-=-# + +if Prompts_File: + Prompts_File = os.path.abspath(Prompts_File) + + if not os.path.exists(Prompts_File): + raise FileNotFoundError(Prompts_File) +else: + Prompts_File = [str(File.resolve()) for File in Path().glob("*.txt")] + + if not Prompts_File: + raise FileNotFoundError("No .txt files has been found in the current directory") + + Prompts_File = sorted(Prompts_File, key = os.path.getmtime)[0] + +with open(Prompts_File, "r", encoding = "UTF-8") as File: + Prompts = File.read() + +#-=-=-=-# +# Old + +Prompts_List = Prompts.strip("\n") +Prompts_List = Prompts_List.split("\n") +Prompts_List = [Line for Line in Prompts_List if Line] +__Lines_Old = len(Prompts_List) + +# New +Prompts_List = [Line for Line in Prompts_List if not Line.startswith("#")] +__Lines_New = len(Prompts_List) + +__Ignored = __Lines_Old - __Lines_New + +rprint("[b #{0}]Found {1} prompts, {2} {3} ignored.[/]".format( + "00CC00" if __Lines_New else "FF0000", + __Lines_New, __Ignored, + "was" if __Ignored == 1 else "were" +)) + +if not Prompts_List: + print() + raise ValueError("No prompts found.") \ No newline at end of file diff --git a/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/src/setup_runner.pyw b/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/src/setup_runner.pyw new file mode 100644 index 0000000..b1d105e --- /dev/null +++ b/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/src/setup_runner.pyw @@ -0,0 +1,147 @@ +Runtime = time() +Counter = 1 + +def commaFix(s: str) -> str: + return re.sub("([^\x00-\x7F]|\w)(\.|\ใ€‚|\?)", r"\1 \2\2", s) + +#-=-=-=-# + +for Line in Prompts_List: + Elements = Line.split("|") + Elements = [Element.strip() for Element in Elements] + + #-=-=-=-# + + Speaker_Name = Elements[0] + Language = Elements[1] + Prompt_String = Elements[2] + + Speaker_Path = os.path.join(Directory_Inputs, Speaker_Name) + ".flac" + Speaker_Display = os.path.splitext(os.path.basename(Speaker_Path))[0] + + if Language.lower().startswith(("auto", "none", "x")): + Language = None + + if Use_Comma_Fix: + Prompt_String = commaFix(Prompt_String) + + if Language: + if Language in Languages: + Language = IDs[Languages[Language][0]] + else: + raise ValueError("Unsupported language") + else: + Predicted = langid.classify(Prompt_String)[0].strip() + + if Predicted == "zh": + Predicted = "zh-cn" + + if Language != Predicted: + Language = Predicted + + MaxLen = Languages[Language][1] + Language_Display = Languages[Language][0] + + #-=-=-=-# + # Errors + + if os.path.basename(Speaker_Path) not in os.listdir(Directory_Inputs): + raise FileNotFoundError(Speaker_Path) + + if len(Prompt_String) > MaxLen: + rprint(f"[b #44AAFF]Prompt string length exceeds {MaxLen}, truncating[/]") + Prompt_String = Prompt_String[:MaxLen] + + if len(Prompt_String) < Max_Prompt_Display_Length: + Prompt_Display = f'"{Prompt_String}"' + else: + Prompt_Display = f'"{Prompt_String[:Max_Prompt_Display_Length]}(...)"' + + #-=-=-=-# + # Print information + + Counter_Display = str(Counter).rjust(len(str(len(Prompts_List))) + 1, "0") + + print(f"{Counter_Display}.") + print(" Speaker Name: ", Speaker_Display) + print(" Language: ", "{0} ({1} characters limit)".format(Language_Display, MaxLen)) + print(" Prompt: ", Prompt_Display) + + #-=-=-=-# + # Setup output file name + + if len(Elements) > 3: + output_name = Elements[3] + rprint(" Output Name: ", output_name) + else: + output_name = re.sub(r"[,.;@#?!&$]+\ *", "_", Prompt_String).replace("_", " ") + output_name = output_name.split() + output_name = "_".join([x for x in output_name if output_name]) + + output_name = output_name[:Truncate_Output_Name_After] + output_path = os.path.join(Directory_Outputs, Speaker_Display, output_name + ".wav") + output_path = os.path.abspath(output_path) + + output_dir = os.path.dirname(output_path) + + if not os.path.exists(output_dir): + os.makedirs(output_dir, exist_ok = True) + + if os.path.exists(output_path): + os.remove(output_path) + + # Run + if not Length_Reference_Max: + Length_Reference_Max = round(mFile(Speaker_Path).info.length) + + torch.cuda.empty_cache() + + #-=-=-=-# + + (gpt_cond_latent, speaker_embedding) = model.get_conditioning_latents( + audio_path = Speaker_Path, + gpt_cond_len = Length_GPT_Condition, + gpt_cond_chunk_len = Length_GPT_Condition_Chunk, + max_ref_length = Length_Reference_Max + ) + + out = model.inference( + Prompt_String, Language, + gpt_cond_latent, speaker_embedding, + repetition_penalty = Repetition_Penalty, + temperature = Temperature, + ) + + torchaudio.save( + output_path, + torch.tensor(out["wav"]).unsqueeze(0), + 24000 + ) + + if Clear_console_output_after_each_prompt: + if Line != Prompts_List[-1]: + cmd = "cls" if is_NT else "clear" + os.system(cmd) + else: + print() + + rprint('[b][#44AAFF]\nSaved to "{0}" [#A0A0A0]({1}s) ({2})[/][/]'.format( + os.path.relpath(output_path, Directory_Main), + round(mFile(output_path).info.length, 3), + fdb_size(output_path) + )) + + if Line != Prompts_List[-1]: + print("\n" + "โ”€" * 32 + "\n") + + Counter += 1 + +#-=-=-=-# + +__Run_Time = time() - Runtime +print("\n" + "โ”€" * 32 + "\n") +rprint("[b #00CC00]Done![/]") +rprint("Runtime: [b #44AAFF]{0}[/] [i #A0A0A0](avg. {1} per line)[/]".format( + str(timedelta(seconds = __Run_Time))[2:-3], + str(timedelta(seconds = __Run_Time / len(Prompts_List)))[2:-3] +)) \ No newline at end of file diff --git a/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/src/setup_tts.pyw b/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/src/setup_tts.pyw new file mode 100644 index 0000000..1003c05 --- /dev/null +++ b/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/src/setup_tts.pyw @@ -0,0 +1,48 @@ +print() +rprint("[b #FFCC00]Importing TTS modules...[/]") + +from TTS.api import TTS +from TTS.tts.configs.xtts_config import XttsConfig +from TTS.tts.models.xtts import Xtts +from TTS.utils.manage import ModelManager +from TTS.utils.generic_utils import get_user_data_dir + +os.environ["COQUI_TOS_AGREED"] = "1" + +#-=-=-=-# + +rprint("[b #FFCC00]Retrieving model...[/]") + +# Download XTTS +model_name = "tts_models/multilingual/multi-dataset/xtts_v2" +model_path = os.path.join(get_user_data_dir("tts"), model_name.replace("/", "--")) +ckpt_path = os.path.join(model_path, "model.pth") + +config_json = os.path.join(model_path, "config.json") +vocab_json = os.path.join(model_path, "vocab.json") + +if not os.path.exists(model_path): + # Download model + rprint("[b #FFCC00]Downloading model...[/]") + ModelManager().download_model(model_name) +#else: +# rmtree(model_path) + +rprint("[b #FFCC00]Configuring...[/]") +config = XttsConfig() +config.load_json(config_json) + +# Loading model +model = Xtts.init_from_config(config) +model.load_checkpoint( + config, + checkpoint_path = ckpt_path, + vocab_path = vocab_json, + eval = True, + use_deepspeed = False +) +model.cuda() + +supported_languages = config.languages + +print("\n" + "โ”€" * 32 + "\n") \ No newline at end of file diff --git a/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/src/setup_variables.pyw b/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/src/setup_variables.pyw new file mode 100644 index 0000000..5242389 --- /dev/null +++ b/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS/src/setup_variables.pyw @@ -0,0 +1,157 @@ +from time import time +Runtime_Start = time() + +import os +import re +import torch +import langid +import torchaudio +from pathlib import Path +from shutil import rmtree +from datetime import timedelta +from rich import print as rprint +from mutagen import File as mFile + +Use_Comma_Fix = True +Max_Prompt_Display_Length = 75 +Truncate_Output_Name_After = 50 + +Length_GPT_Condition = 30 +Length_GPT_Condition_Chunk = 4 +Length_Reference_Max = 60 +Repetition_Penalty = 5.0 +Temperature = 0.75 + +#-=-=-=-# + +is_NT = os.sys.platform.lower().startswith("win") + +Languages = { + #"id": ("long_name", characters_limit), + "en": ["English", 250], + "es": ["Spanish", 239], + "fr": ["French", 273], + "de": ["Deutsch", 253], + "it": ["Italian", 213], + "pt": ["Portuguese", 203], + "tr": ["Turkish", 226], + "ru": ["Russian", 182], + "nl": ["Dutch", 251], + "pl": ["Polish", 224], + "cs": ["Czech", 186], + "ar": ["Arabic", 166], + "zh-cn": ["Chinese", 82], + "ja": ["Japanese", 71], + "ko": ["Korean", 95], + "hu": ["Hungarian", 224] +} + +#-=-=-=-# +# Directories + +Directory_Main = os.getcwd() +Directory_Main = os.path.abspath(Directory_Main) +Directory_Inputs = os.path.join(Directory_Main, "_inputs") +Directory_Outputs = os.path.join(Directory_Main, "_outputs") + +for Directory in Directory_Inputs, Directory_Outputs: + os.makedirs(Directory, exist_ok = True) + +#-=-=-=-# + +def fdb_size(obj: str, extended_units: bool = False, bits: bool = False, recursive: bool = False) -> str: + """ + Args: + obj: Bytes integer or string path of existing file or directory. + extended_units: Extends the unit of the result, i.e. "Megabytes" instead of "MB". + bits: Uses decimal divider (1000) instead of binary one. (1024) + recursive: Iterate subdirectories, applicable only if `obj` is directory. (slow!) + + Returns: + Human-readable files size string. + """ + # Setup + + if bits: + Bits = 1000 + Bits_Display_Single = "bit" + Bits_Display_Multiple = "bits" + else: + Bits = 1024 + Bits_Display_Single = "byte" + Bits_Display_Multiple = "bytes" + + Units = { + "": "", + "K": "kilo", + "M": "mega", + "G": "giga", + "T": "tera", + "P": "peta", + "E": "exa", + "Z": "zetta", + "Y": "yotta", + "R": "ronna", + "Q": "quetta" + } + + #-=-=-=-# + # Search for files + + if isinstance(obj, str): + path = str(Path(obj).resolve()) + + if not os.path.exists(path): + raise FileNotFoundError(path) + + if os.path.isfile(obj): + Files = [obj] + else: + Wildcard = "*" + if recursive: + Wildcard += "*/*" + Files = list(Path(obj).glob(Wildcard)) + for File in Files: + Files[Files.index(File)] = str(File.resolve()) + + Files = map(os.path.getsize, Files) + Bytes = sum(Files) + else: + Bytes = obj + + #-=-=-=-# + # Calculate integer + + for Unit in Units: + if Bytes < Bits: + break + Bytes /= Bits + + #-=-=-=-# + # Ending conditions + + if extended_units: + if Bytes == 1: + Bits_Display = Bits_Display_Single + else: + Bits_Display = Bits_Display_Multiple + Unit = (Units[Unit] + Bits_Display).capitalize() + else: + Unit += "B" + + #-=-=-=-# + # Add zero to integer + + if "." in str(Bytes): + Bytes = round(Bytes, 2) + Bytes = str(Bytes).split(".") + Bytes[1] = Bytes[1][:2] + Bytes[1] = Bytes[1].ljust(2, "0") + Bytes = ".".join(Bytes) + + Bytes = str(Bytes) + + #-=-=-=-# + # Return string + + return " ".join((Bytes, Unit)) \ No newline at end of file diff --git a/Notebooks/AI/Visual/Generate/Stable-Diffusion-WebUI/Config/config.json b/Notebooks/AI/Visual/Generate/Stable-Diffusion-WebUI/Config/config.json new file mode 100644 index 0000000..b706c0a --- /dev/null +++ b/Notebooks/AI/Visual/Generate/Stable-Diffusion-WebUI/Config/config.json @@ -0,0 +1,155 @@ +{ + "samples_save": true, + "samples_format": "jpg", + "samples_filename_pattern": "", + "save_images_add_number": true, + "grid_save": true, + "grid_format": "jpg", + "grid_extended_filename": true, + "grid_only_if_multiple": true, + "grid_prevent_empty_spots": false, + "n_rows": -1, + "enable_pnginfo": true, + "save_txt": false, + "save_images_before_face_restoration": false, + "jpeg_quality": 100, + "export_for_4chan": false, + "use_original_name_batch": false, + "save_selected_only": true, + "do_not_add_watermark": true, + "outdir_samples": "", + "outdir_txt2img_samples": "outputs/txt2img-images", + "outdir_img2img_samples": "outputs/img2img-images", + "outdir_extras_samples": "outputs/extras-images", + "outdir_grids": "", + "outdir_txt2img_grids": "outputs/txt2img-grids", + "outdir_img2img_grids": "outputs/img2img-grids", + "outdir_save": "log/images", + "save_to_dirs": false, + "grid_save_to_dirs": false, + "use_save_to_dirs_for_ui": false, + "directories_filename_pattern": "", + "directories_max_prompt_words": 8, + "ESRGAN_tile": 192, + "ESRGAN_tile_overlap": 8, + "realesrgan_enabled_models": [ + "R-ESRGAN x4+", + "R-ESRGAN x4+ Anime6B", + "R-ESRGAN General 4xV3", + "R-ESRGAN AnimeVideo", + "R-ESRGAN 4x+", + "R-ESRGAN 4x+ Anime6B", + "R-ESRGAN General WDN 4xV3", + "R-ESRGAN 2x+" + ], + "SWIN_tile": 192, + "SWIN_tile_overlap": 8, + "ldsr_steps": 100, + "upscaler_for_img2img": "R-ESRGAN General 4xV3", + "use_scale_latent_for_hires_fix": false, + "face_restoration_model": "GFPGAN", + "code_former_weight": 0.5, + "face_restoration_unload": false, + "memmon_poll_rate": 4, + "samples_log_stdout": false, + "multiple_tqdm": true, + "unload_models_when_training": false, + "dataset_filename_word_regex": "", + "dataset_filename_join_string": " ", + "training_image_repeats_per_epoch": 1, + "training_write_csv_every": 500.0, + "sd_model_checkpoint": null, + "sd_checkpoint_cache": 0, + "sd_hypernetwork": "None", + "sd_hypernetwork_strength": 1, + "img2img_color_correction": false, + "save_images_before_color_correction": false, + "img2img_fix_steps": false, + "enable_quantization": false, + "enable_emphasis": true, + "use_old_emphasis_implementation": false, + "enable_batch_seeds": true, + "comma_padding_backtrack": 20, + "filter_nsfw": false, + "CLIP_stop_at_last_layers": 1, + "random_artist_categories": [], + "interrogate_keep_models_in_memory": false, + "interrogate_use_builtin_artists": true, + "interrogate_return_ranks": false, + "interrogate_clip_num_beams": 1, + "interrogate_clip_min_length": 24, + "interrogate_clip_max_length": 48, + "interrogate_clip_dict_limit": 1500.0, + "interrogate_deepbooru_score_threshold": 0.5, + "deepbooru_sort_alpha": true, + "deepbooru_use_spaces": false, + "deepbooru_escape": true, + "show_progressbar": true, + "show_progress_every_n_steps": 0, + "show_progress_grid": true, + "return_grid": false, + "do_not_show_images": false, + "add_model_hash_to_info": true, + "add_model_name_to_info": false, + "disable_weights_auto_swap": false, + "font": "", + "js_modal_lightbox": true, + "js_modal_lightbox_initially_zoomed": true, + "show_progress_in_title": true, + "quicksettings": "sd_model_checkpoint", + "localization": "None", + "hide_samplers": [], + "eta_ddim": 0, + "eta_ancestral": 1, + "ddim_discretize": "uniform", + "s_churn": 0, + "s_tmin": 0, + "s_noise": 1, + "eta_noise_seed_delta": 0, + "training_xattention_optimizations": false, + "inpainting_mask_weight": 1, + "send_seed": true, + "ais_exif_pnginfo_group": [ + "aesthetic_score", + "cfg_scale", + "sampler", + "sd_model_hash", + "seed", + "hash" + ], + "ais_windows_tag_group": [ + "aesthetic_score", + "sampler", + "cfg_scale", + "seed", + "sd_model_hash", + "hash" + ], + "ais_windows_category_group": [ + "aesthetic_score", + "cfg_scale", + "sampler", + "sd_model_hash", + "seed", + "hash" + ], + "ais_generation_params_text_group": [ + "aesthetic_score", + "sampler", + "cfg_scale", + "seed", + "sd_model_hash", + "hash" + ], + "ais_force_cpu": false, + "images_history_preload": false, + "images_history_page_columns": 6.0, + "images_history_page_rows": 6.0, + "images_history_pages_perload": 20.0, + "inspiration_max_samples": 4, + "inspiration_rows_num": 4, + "inspiration_cols_num": 6, + "save_images_before_highres_fix": false, + "save_optimizer_state": false, + "sd_vae": "auto" +} \ No newline at end of file diff --git a/Notebooks/AI/Visual/Generate/Stable-Diffusion-WebUI/Config/styles.csv b/Notebooks/AI/Visual/Generate/Stable-Diffusion-WebUI/Config/styles.csv new file mode 100644 index 0000000..6371f41 --- /dev/null +++ b/Notebooks/AI/Visual/Generate/Stable-Diffusion-WebUI/Config/styles.csv @@ -0,0 +1,74 @@ +๏ปฟname,prompt,negative_prompt +None,,, +DEFAULT: Positive,"(masterpiece: 2.0), YOUR_PROMPT_HERE, +best quality, highest quality, high quality, +ultra-detailed, highly detailed, +hyperrealistic, realistic", +DEFAULT: Negative,,"text, extra digits, fewer digits, +(bad proportions: 2.0), (bad anatomy: 2.0), +(deformed face: 2.0), (poorly drawn face: 1.0), +(bad hands: 2.0), (bad fingers: 2.5), (missing finger: 1.0), (mutated hands and fingers: 2.0), +cropped, blurry, low resolution, lowres, +normal quality, low quality, worst quality, +jpeg, (jpeg artifacts: 2.0), (jpg artifacts: 2.0)" +GENERAL: Art,"portrait, illustration, (cinematic: 1.5),", +ARTIST: Claude Monet,"(Claude Monet painting: 2.0), (painting: 1.5), +(impressionism: 1.0), (modernism: 1.0) + +a bit of abstraction, + +(Barbizon school art: 0.75), +(Alfred Sisley: 0.75), +(Auguste Renoir: 0.75), +(Jean Frederic Bazille: 0.75), +(Johan Barthold Jongkind: 0.75), +(William Turner: 0.75), +(John Constable: 0.75)", +ARTIST: Gustav Klimt,"(Gustav Klimt painting: 2.0), (painting: 1.5), +(modernism: 0.25), (symbolism: 0.25), (modernism: 1.0), +(Japanese art: 0.25), (Chinese art: 0.25), (Ancient Egyptian art: 0.25), (Mycenaean art: 0.25), + +(Egon Schiele art: 0.75), +(Courtney Adams art: 0.75), +(Fletcher Sibthorp art: 0.75), +(Kimon Loghi art: 0.75), +(Kevin Wasden art: 0.75), +(Nagura Hiroo art: 0.75)", +ARTIST: Leonardo Da Vinci,"(Leonardo da Vinci painting: 2.0), (painting: 1.5), +(renessaince art: 1.0), italian art), + +(sharp contours: 1.0), (sfumato: 1.0), (chiaroscuro: 1.0), (aria restretta: 1.0), (lumo libero: 1.0), (3d perspective: 1.0), +(flemish painters: 0.25), (venetian painters: 0.5), + +(Michelangelo art: 0.5), (Rafael Santi art: 0.25)", +ARTIST: Michelangelo,"(Michelangelo frescoes: 2.0), +(renessaince art: 1.0), (italian art: 0.5), (biblical art: 0.75), (symbolism: 0.25), + +(Leonardo da Vinci art: 0.5), (Rafael Santi art: 0.25)", +ARTIST: Pablo Picasso,"(Pablo Picasso painting: 2.0), +(postimpressionism: 1.0), (symbolism: 1.0), (surrealism: 1.0), (modernism: 1.0), +(analytical cubism: 0.5), (synthetical cubism: 0.5), + +(abstract work: 0.5), (geometrical shapes: 0.5), (layers: 0.5), + +(Iberian art: 0.25), (African art: 0.25), +(Paulo Cezanne art: 0.5), +(Henri de Toulouse-Lautrec art: 0.5), +(Georges Braque art: 0.5)", +ARTIST: Rembrandt,"(Rembrandt painting: 2.0), +(Baroque art: 0.25), (biblical art: 0.75), +(Dutch Golden Age art: 0.5), + +(light effects: 0.5), (deep shadows: 0.25), + +(Caravaggio art: 0.5), +(Carel Fabritius art: 0.5), +(Pieter de Hooch art: 0.5), +(Vincent van Gogh art: 0.25)", +ARTIST: Vincent van Gogh,"(Vincent van Gogh painting: 2.0), +(postimpressionism: 1.0), (neoimpressionism: 1.0), (pointilism: 0.75), (japonaiserie: 0.25), + +(oil on canvas: 1.5), +(impasto: 0.25), (brushstokes of thickly laid-on paint: 1.0), (spiraling movements: 1.5), + +(Jean-Francois Millet art: 0.25)", \ No newline at end of file diff --git a/Notebooks/AI/Visual/Generate/Stable-Diffusion-WebUI/Config/ui-config.json b/Notebooks/AI/Visual/Generate/Stable-Diffusion-WebUI/Config/ui-config.json new file mode 100644 index 0000000..9b14b5d --- /dev/null +++ b/Notebooks/AI/Visual/Generate/Stable-Diffusion-WebUI/Config/ui-config.json @@ -0,0 +1,677 @@ +{ + "txt2img/Prompt/visible": true, + "txt2img/Prompt/value": "", + "txt2img/Negative prompt/visible": true, + "txt2img/Negative prompt/value": "", + "txt2img/Style 1/value": "DEFAULT: Positive", + "txt2img/Style 1/visible": true, + "txt2img/Style 2/value": "DEFAULT: Negative", + "txt2img/Style 2/visible": true, + "txt2img/Sampling Steps/visible": true, + "txt2img/Sampling Steps/value": 25, + "txt2img/Sampling Steps/minimum": 1, + "txt2img/Sampling Steps/maximum": 150, + "txt2img/Sampling Steps/step": 1, + "txt2img/Sampling method/visible": true, + "txt2img/Sampling method/value": "DPM2 Karras", + "txt2img/Width/visible": true, + "txt2img/Width/value": 640, + "txt2img/Width/minimum": 64, + "txt2img/Width/maximum": 2048, + "txt2img/Width/step": 64, + "txt2img/Height/visible": true, + "txt2img/Height/value": 640, + "txt2img/Height/minimum": 64, + "txt2img/Height/maximum": 2048, + "txt2img/Height/step": 64, + "txt2img/Restore faces/visible": true, + "txt2img/Restore faces/value": true, + "txt2img/Tiling/visible": true, + "txt2img/Tiling/value": false, + "txt2img/Highres. fix/visible": true, + "txt2img/Highres. fix/value": false, + "txt2img/Firstpass width/visible": true, + "txt2img/Firstpass width/value": 0, + "txt2img/Firstpass width/minimum": 0, + "txt2img/Firstpass width/maximum": 1024, + "txt2img/Firstpass width/step": 64, + "txt2img/Firstpass height/visible": true, + "txt2img/Firstpass height/value": 0, + "txt2img/Firstpass height/minimum": 0, + "txt2img/Firstpass height/maximum": 1024, + "txt2img/Firstpass height/step": 64, + "txt2img/Denoising strength/visible": true, + "txt2img/Denoising strength/value": 0.6, + "txt2img/Denoising strength/minimum": 0.0, + "txt2img/Denoising strength/maximum": 1.0, + "txt2img/Denoising strength/step": 0.01, + "txt2img/Batch count/visible": true, + "txt2img/Batch count/value": 4, + "txt2img/Batch count/minimum": 1, + "txt2img/Batch count/maximum": 100, + "txt2img/Batch count/step": 1, + "txt2img/Batch size/visible": true, + "txt2img/Batch size/value": 1, + "txt2img/Batch size/minimum": 1, + "txt2img/Batch size/maximum": 8, + "txt2img/Batch size/step": 1, + "txt2img/CFG Scale/visible": true, + "txt2img/CFG Scale/value": 7.5, + "txt2img/CFG Scale/minimum": 1.0, + "txt2img/CFG Scale/maximum": 30.0, + "txt2img/CFG Scale/step": 0.5, + "txt2img/Seed/visible": true, + "txt2img/Seed/value": -1.0, + "txt2img/Extra/visible": true, + "txt2img/Extra/value": false, + "txt2img/Variation seed/visible": true, + "txt2img/Variation seed/value": -1.0, + "txt2img/Variation strength/visible": true, + "txt2img/Variation strength/value": 0.0, + "txt2img/Variation strength/minimum": 0, + "txt2img/Variation strength/maximum": 1, + "txt2img/Variation strength/step": 0.01, + "txt2img/Resize seed from width/visible": true, + "txt2img/Resize seed from width/value": 0, + "txt2img/Resize seed from width/minimum": 0, + "txt2img/Resize seed from width/maximum": 2048, + "txt2img/Resize seed from width/step": 64, + "txt2img/Resize seed from height/visible": true, + "txt2img/Resize seed from height/value": 0, + "txt2img/Resize seed from height/minimum": 0, + "txt2img/Resize seed from height/maximum": 2048, + "txt2img/Resize seed from height/step": 64, + "txt2img/Script/value": "None", + "txt2img/Script/visible": true, + "customscript/custom_code.py/txt2img/Python code/value": "", + "customscript/prompt_matrix.py/txt2img/Put variable parts at start of prompt/value": false, + "customscript/prompts_from_file.py/txt2img/Iterate seed every line/value": false, + "customscript/prompts_from_file.py/txt2img/List of prompt inputs/value": "", + "customscript/xy_grid.py/txt2img/X values/value": "", + "customscript/xy_grid.py/txt2img/Y values/value": "", + "customscript/xy_grid.py/txt2img/Draw legend/value": true, + "customscript/xy_grid.py/txt2img/Include Separate Images/value": false, + "customscript/xy_grid.py/txt2img/Keep -1 for seeds/value": false, + "txt2img/Make Zip when Save?/visible": true, + "txt2img/Make Zip when Save?/value": true, + "img2img/Prompt/visible": true, + "img2img/Prompt/value": "", + "img2img/Negative prompt/visible": true, + "img2img/Negative prompt/value": "", + "img2img/Style 1/value": "None", + "img2img/Style 1/visible": true, + "img2img/Style 2/value": "None", + "img2img/Style 2/visible": true, + "img2img/Mask blur/visible": true, + "img2img/Mask blur/value": 4, + "img2img/Mask blur/minimum": 0, + "img2img/Mask blur/maximum": 64, + "img2img/Mask blur/step": 1, + "img2img/Mask mode/visible": true, + "img2img/Mask mode/value": "Draw mask", + "img2img/Masking mode/visible": true, + "img2img/Masking mode/value": "Inpaint masked", + "img2img/Masked content/visible": true, + "img2img/Masked content/value": "original", + "img2img/Inpaint at full resolution/visible": true, + "img2img/Inpaint at full resolution/value": true, + "img2img/Inpaint at full resolution padding, pixels/visible": true, + "img2img/Inpaint at full resolution padding, pixels/value": 32, + "img2img/Inpaint at full resolution padding, pixels/minimum": 0, + "img2img/Inpaint at full resolution padding, pixels/maximum": 256, + "img2img/Inpaint at full resolution padding, pixels/step": 4, + "img2img/Input directory/visible": true, + "img2img/Input directory/value": "", + "img2img/Output directory/visible": true, + "img2img/Output directory/value": "", + "img2img/Resize mode/visible": true, + "img2img/Resize mode/value": "Just resize", + "img2img/Sampling Steps/visible": true, + "img2img/Sampling Steps/value": 30, + "img2img/Sampling Steps/minimum": 1, + "img2img/Sampling Steps/maximum": 150, + "img2img/Sampling Steps/step": 1, + "img2img/Sampling method/visible": true, + "img2img/Sampling method/value": "DDIM", + "img2img/Width/visible": true, + "img2img/Width/value": 512, + "img2img/Width/minimum": 64, + "img2img/Width/maximum": 2048, + "img2img/Width/step": 64, + "img2img/Height/visible": true, + "img2img/Height/value": 512, + "img2img/Height/minimum": 64, + "img2img/Height/maximum": 2048, + "img2img/Height/step": 64, + "img2img/Restore faces/visible": true, + "img2img/Restore faces/value": true, + "img2img/Tiling/visible": true, + "img2img/Tiling/value": false, + "img2img/Batch count/visible": true, + "img2img/Batch count/value": 3, + "img2img/Batch count/minimum": 1, + "img2img/Batch count/maximum": 100, + "img2img/Batch count/step": 1, + "img2img/Batch size/visible": true, + "img2img/Batch size/value": 1, + "img2img/Batch size/minimum": 1, + "img2img/Batch size/maximum": 8, + "img2img/Batch size/step": 1, + "img2img/CFG Scale/visible": true, + "img2img/CFG Scale/value": 12.5, + "img2img/CFG Scale/minimum": 1.0, + "img2img/CFG Scale/maximum": 30.0, + "img2img/CFG Scale/step": 0.5, + "img2img/Denoising strength/visible": true, + "img2img/Denoising strength/value": 0.75, + "img2img/Denoising strength/minimum": 0.0, + "img2img/Denoising strength/maximum": 1.0, + "img2img/Denoising strength/step": 0.01, + "img2img/Seed/visible": true, + "img2img/Seed/value": -1.0, + "img2img/Extra/visible": true, + "img2img/Extra/value": false, + "img2img/Variation seed/visible": true, + "img2img/Variation seed/value": -1.0, + "img2img/Variation strength/visible": true, + "img2img/Variation strength/value": 0.0, + "img2img/Variation strength/minimum": 0, + "img2img/Variation strength/maximum": 1, + "img2img/Variation strength/step": 0.01, + "img2img/Resize seed from width/visible": true, + "img2img/Resize seed from width/value": 0, + "img2img/Resize seed from width/minimum": 0, + "img2img/Resize seed from width/maximum": 2048, + "img2img/Resize seed from width/step": 64, + "img2img/Resize seed from height/visible": true, + "img2img/Resize seed from height/value": 0, + "img2img/Resize seed from height/minimum": 0, + "img2img/Resize seed from height/maximum": 2048, + "img2img/Resize seed from height/step": 64, + "img2img/Script/value": "None", + "img2img/Script/visible": true, + "customscript/custom_code.py/img2img/Python code/value": "", + "customscript/img2imgalt.py/img2img/Override `Sampling method` to Euler?(this method is built for it)/value": true, + "customscript/img2imgalt.py/img2img/Override `prompt` to the same value as `original prompt`?(and `negative prompt`)/value": true, + "customscript/img2imgalt.py/img2img/Original prompt/value": "", + "customscript/img2imgalt.py/img2img/Original negative prompt/value": "", + "customscript/img2imgalt.py/img2img/Override `Sampling Steps` to the same value as `Decode steps`?/value": true, + "customscript/img2imgalt.py/img2img/Decode steps/value": 50, + "customscript/img2imgalt.py/img2img/Decode steps/minimum": 1, + "customscript/img2imgalt.py/img2img/Decode steps/maximum": 150, + "customscript/img2imgalt.py/img2img/Decode steps/step": 1, + "customscript/img2imgalt.py/img2img/Override `Denoising strength` to 1?/value": true, + "customscript/img2imgalt.py/img2img/Decode CFG scale/value": 7.5, + "customscript/img2imgalt.py/img2img/Decode CFG scale/minimum": 0.0, + "customscript/img2imgalt.py/img2img/Decode CFG scale/maximum": 15.0, + "customscript/img2imgalt.py/img2img/Decode CFG scale/step": 0.1, + "customscript/img2imgalt.py/img2img/Randomness/value": 0.0, + "customscript/img2imgalt.py/img2img/Randomness/minimum": 0.0, + "customscript/img2imgalt.py/img2img/Randomness/maximum": 1.0, + "customscript/img2imgalt.py/img2img/Randomness/step": 0.01, + "customscript/img2imgalt.py/img2img/Sigma adjustment for finding noise for image/value": false, + "customscript/loopback.py/img2img/Loops/value": 4, + "customscript/loopback.py/img2img/Loops/minimum": 1, + "customscript/loopback.py/img2img/Loops/maximum": 32, + "customscript/loopback.py/img2img/Loops/step": 1, + "customscript/loopback.py/img2img/Denoising strength change factor/value": 1, + "customscript/loopback.py/img2img/Denoising strength change factor/minimum": 0.9, + "customscript/loopback.py/img2img/Denoising strength change factor/maximum": 1.1, + "customscript/loopback.py/img2img/Denoising strength change factor/step": 0.01, + "customscript/outpainting_mk_2.py/img2img/Pixels to expand/value": 128, + "customscript/outpainting_mk_2.py/img2img/Pixels to expand/minimum": 8, + "customscript/outpainting_mk_2.py/img2img/Pixels to expand/maximum": 256, + "customscript/outpainting_mk_2.py/img2img/Pixels to expand/step": 8, + "customscript/outpainting_mk_2.py/img2img/Mask blur/value": 8, + "customscript/outpainting_mk_2.py/img2img/Mask blur/minimum": 0, + "customscript/outpainting_mk_2.py/img2img/Mask blur/maximum": 64, + "customscript/outpainting_mk_2.py/img2img/Mask blur/step": 1, + "customscript/outpainting_mk_2.py/img2img/Fall-off exponent (lower=higher detail)/value": 1.0, + "customscript/outpainting_mk_2.py/img2img/Fall-off exponent (lower=higher detail)/minimum": 0.0, + "customscript/outpainting_mk_2.py/img2img/Fall-off exponent (lower=higher detail)/maximum": 4.0, + "customscript/outpainting_mk_2.py/img2img/Fall-off exponent (lower=higher detail)/step": 0.01, + "customscript/outpainting_mk_2.py/img2img/Color variation/value": 0.05, + "customscript/outpainting_mk_2.py/img2img/Color variation/minimum": 0.0, + "customscript/outpainting_mk_2.py/img2img/Color variation/maximum": 1.0, + "customscript/outpainting_mk_2.py/img2img/Color variation/step": 0.01, + "customscript/poor_mans_outpainting.py/img2img/Pixels to expand/value": 128, + "customscript/poor_mans_outpainting.py/img2img/Pixels to expand/minimum": 8, + "customscript/poor_mans_outpainting.py/img2img/Pixels to expand/maximum": 256, + "customscript/poor_mans_outpainting.py/img2img/Pixels to expand/step": 8, + "customscript/poor_mans_outpainting.py/img2img/Mask blur/value": 4, + "customscript/poor_mans_outpainting.py/img2img/Mask blur/minimum": 0, + "customscript/poor_mans_outpainting.py/img2img/Mask blur/maximum": 64, + "customscript/poor_mans_outpainting.py/img2img/Mask blur/step": 1, + "customscript/poor_mans_outpainting.py/img2img/Masked content/value": "fill", + "customscript/prompt_matrix.py/img2img/Put variable parts at start of prompt/value": false, + "customscript/prompts_from_file.py/img2img/Iterate seed every line/value": false, + "customscript/prompts_from_file.py/img2img/List of prompt inputs/value": "", + "customscript/sd_upscale.py/img2img/Tile overlap/value": 64, + "customscript/sd_upscale.py/img2img/Tile overlap/minimum": 0, + "customscript/sd_upscale.py/img2img/Tile overlap/maximum": 256, + "customscript/sd_upscale.py/img2img/Tile overlap/step": 16, + "customscript/sd_upscale.py/img2img/Upscaler/value": "None", + "customscript/xy_grid.py/img2img/X values/value": "", + "customscript/xy_grid.py/img2img/Y values/value": "", + "customscript/xy_grid.py/img2img/Draw legend/value": true, + "customscript/xy_grid.py/img2img/Include Separate Images/value": false, + "customscript/xy_grid.py/img2img/Keep -1 for seeds/value": false, + "img2img/Make Zip when Save?/visible": true, + "img2img/Make Zip when Save?/value": true, + "extras/Input directory/visible": true, + "extras/Input directory/value": "", + "extras/Output directory/visible": true, + "extras/Output directory/value": "", + "extras/Show result images/visible": true, + "extras/Show result images/value": true, + "extras/Resize/visible": true, + "extras/Resize/value": 2, + "extras/Resize/minimum": 1.0, + "extras/Resize/maximum": 4.0, + "extras/Resize/step": 0.05, + "extras/Width/visible": true, + "extras/Width/value": 1024, + "extras/Height/visible": true, + "extras/Height/value": 1024, + "extras/Crop to fit/visible": true, + "extras/Crop to fit/value": false, + "extras/Upscaler 1/visible": true, + "extras/Upscaler 1/value": "R-ESRGAN General WDN 4xV3", + "extras/Upscaler 2/visible": true, + "extras/Upscaler 2/value": "R-ESRGAN General 4xV3", + "extras/Upscaler 2 visibility/visible": true, + "extras/Upscaler 2 visibility/value": 0.0, + "extras/Upscaler 2 visibility/minimum": 0.0, + "extras/Upscaler 2 visibility/maximum": 1.0, + "extras/Upscaler 2 visibility/step": 0.001, + "extras/GFPGAN visibility/visible": true, + "extras/GFPGAN visibility/value": 0.0, + "extras/GFPGAN visibility/minimum": 0.0, + "extras/GFPGAN visibility/maximum": 1.0, + "extras/GFPGAN visibility/step": 0.001, + "extras/CodeFormer visibility/visible": true, + "extras/CodeFormer visibility/value": 0, + "extras/CodeFormer visibility/minimum": 0.0, + "extras/CodeFormer visibility/maximum": 1.0, + "extras/CodeFormer visibility/step": 0.001, + "extras/CodeFormer weight (0 = maximum effect, 1 = minimum effect)/visible": true, + "extras/CodeFormer weight (0 = maximum effect, 1 = minimum effect)/value": 0, + "extras/CodeFormer weight (0 = maximum effect, 1 = minimum effect)/minimum": 0.0, + "extras/CodeFormer weight (0 = maximum effect, 1 = minimum effect)/maximum": 1.0, + "extras/CodeFormer weight (0 = maximum effect, 1 = minimum effect)/step": 0.001, + "extras/Upscale Before Restoring Faces/visible": true, + "extras/Upscale Before Restoring Faces/value": true, + "modelmerger/Custom Name (Optional)/visible": true, + "modelmerger/Custom Name (Optional)/value": "", + "modelmerger/Multiplier (M) - set to 0 to get model A/visible": true, + "modelmerger/Multiplier (M) - set to 0 to get model A/value": 0.3, + "modelmerger/Multiplier (M) - set to 0 to get model A/minimum": 0.0, + "modelmerger/Multiplier (M) - set to 0 to get model A/maximum": 1.0, + "modelmerger/Multiplier (M) - set to 0 to get model A/step": 0.05, + "modelmerger/Interpolation Method/visible": true, + "modelmerger/Interpolation Method/value": "Weighted sum", + "modelmerger/Save as float16/visible": true, + "modelmerger/Save as float16/value": false, + "customscript/aesthetic.py/txt2img/Aesthetic weight/visible": true, + "customscript/aesthetic.py/txt2img/Aesthetic weight/value": 0.9, + "customscript/aesthetic.py/txt2img/Aesthetic weight/minimum": 0, + "customscript/aesthetic.py/txt2img/Aesthetic weight/maximum": 1, + "customscript/aesthetic.py/txt2img/Aesthetic weight/step": 0.01, + "customscript/aesthetic.py/txt2img/Aesthetic steps/visible": true, + "customscript/aesthetic.py/txt2img/Aesthetic steps/value": 15, + "customscript/aesthetic.py/txt2img/Aesthetic steps/minimum": 0, + "customscript/aesthetic.py/txt2img/Aesthetic steps/maximum": 50, + "customscript/aesthetic.py/txt2img/Aesthetic steps/step": 1, + "customscript/aesthetic.py/txt2img/Aesthetic learning rate/visible": true, + "customscript/aesthetic.py/txt2img/Aesthetic learning rate/value": "0.0001", + "customscript/aesthetic.py/txt2img/Slerp interpolation/visible": true, + "customscript/aesthetic.py/txt2img/Slerp interpolation/value": false, + "customscript/aesthetic.py/txt2img/Aesthetic text for imgs/visible": true, + "customscript/aesthetic.py/txt2img/Aesthetic text for imgs/value": "", + "customscript/aesthetic.py/txt2img/Slerp angle/visible": true, + "customscript/aesthetic.py/txt2img/Slerp angle/value": 0.1, + "customscript/aesthetic.py/txt2img/Slerp angle/minimum": 0, + "customscript/aesthetic.py/txt2img/Slerp angle/maximum": 1, + "customscript/aesthetic.py/txt2img/Slerp angle/step": 0.01, + "customscript/aesthetic.py/txt2img/Is negative text/visible": true, + "customscript/aesthetic.py/txt2img/Is negative text/value": false, + "customscript/prompts_from_file.py/txt2img/Use same random seed for all lines/value": false, + "customscript/inspiration.py/txt2img/Prompt words before artist or style name/value": "a painting in", + "customscript/inspiration.py/txt2img/Prompt words after artist or style name/value": "style", + "customscript/inspiration.py/txt2img/Negative Prompt/value": "picture frame, portrait photo", + "customscript/inspiration.py/txt2img/Batch size/value": 1.0, + "customscript/inspiration.py/txt2img/Batch count/value": 2.0, + "customscript/aesthetic.py/img2img/Aesthetic weight/visible": true, + "customscript/aesthetic.py/img2img/Aesthetic weight/value": 0.9, + "customscript/aesthetic.py/img2img/Aesthetic weight/minimum": 0, + "customscript/aesthetic.py/img2img/Aesthetic weight/maximum": 1, + "customscript/aesthetic.py/img2img/Aesthetic weight/step": 0.01, + "customscript/aesthetic.py/img2img/Aesthetic steps/visible": true, + "customscript/aesthetic.py/img2img/Aesthetic steps/value": 15, + "customscript/aesthetic.py/img2img/Aesthetic steps/minimum": 0, + "customscript/aesthetic.py/img2img/Aesthetic steps/maximum": 50, + "customscript/aesthetic.py/img2img/Aesthetic steps/step": 1, + "customscript/aesthetic.py/img2img/Aesthetic learning rate/visible": true, + "customscript/aesthetic.py/img2img/Aesthetic learning rate/value": "0.0001", + "customscript/aesthetic.py/img2img/Slerp interpolation/visible": true, + "customscript/aesthetic.py/img2img/Slerp interpolation/value": false, + "customscript/aesthetic.py/img2img/Aesthetic text for imgs/visible": true, + "customscript/aesthetic.py/img2img/Aesthetic text for imgs/value": "", + "customscript/aesthetic.py/img2img/Slerp angle/visible": true, + "customscript/aesthetic.py/img2img/Slerp angle/value": 0.1, + "customscript/aesthetic.py/img2img/Slerp angle/minimum": 0, + "customscript/aesthetic.py/img2img/Slerp angle/maximum": 1, + "customscript/aesthetic.py/img2img/Slerp angle/step": 0.01, + "customscript/aesthetic.py/img2img/Is negative text/visible": true, + "customscript/aesthetic.py/img2img/Is negative text/value": false, + "customscript/prompts_from_file.py/img2img/Use same random seed for all lines/value": false, + "customscript/inspiration.py/img2img/Prompt words before artist or style name/value": "a painting in", + "customscript/inspiration.py/img2img/Prompt words after artist or style name/value": "style", + "customscript/inspiration.py/img2img/Negative Prompt/value": "picture frame, portrait photo", + "customscript/inspiration.py/img2img/Batch size/value": 1.0, + "customscript/inspiration.py/img2img/Batch count/value": 2.0, + "txt2img/Styles/visible": true, + "txt2img/Styles/value": [], + "txt2img/Sampling steps/visible": true, + "txt2img/Sampling steps/value": 20, + "txt2img/Sampling steps/minimum": 1, + "txt2img/Sampling steps/maximum": 150, + "txt2img/Sampling steps/step": 1, + "txt2img/Hires. fix/visible": true, + "txt2img/Hires. fix/value": false, + "txt2img/Upscaler/visible": true, + "txt2img/Upscaler/value": "Latent", + "txt2img/Hires steps/visible": true, + "txt2img/Hires steps/value": 0, + "txt2img/Hires steps/minimum": 0, + "txt2img/Hires steps/maximum": 150, + "txt2img/Hires steps/step": 1, + "txt2img/Upscale by/visible": true, + "txt2img/Upscale by/value": 2.0, + "txt2img/Upscale by/minimum": 1.0, + "txt2img/Upscale by/maximum": 4.0, + "txt2img/Upscale by/step": 0.05, + "txt2img/Resize width to/visible": true, + "txt2img/Resize width to/value": 0, + "txt2img/Resize width to/minimum": 0, + "txt2img/Resize width to/maximum": 2048, + "txt2img/Resize width to/step": 8, + "txt2img/Resize height to/visible": true, + "txt2img/Resize height to/value": 0, + "txt2img/Resize height to/minimum": 0, + "txt2img/Resize height to/maximum": 2048, + "txt2img/Resize height to/step": 8, + "customscript/custom_code.py/txt2img/Python code/visible": true, + "customscript/prompt_matrix.py/txt2img/Put variable parts at start of prompt/visible": true, + "customscript/prompt_matrix.py/txt2img/Use different seed for each picture/visible": true, + "customscript/prompt_matrix.py/txt2img/Use different seed for each picture/value": false, + "customscript/prompts_from_file.py/txt2img/Iterate seed every line/visible": true, + "customscript/prompts_from_file.py/txt2img/Use same random seed for all lines/visible": true, + "customscript/prompts_from_file.py/txt2img/List of prompt inputs/visible": true, + "customscript/xy_grid.py/txt2img/X type/visible": true, + "customscript/xy_grid.py/txt2img/X type/value": "Seed", + "customscript/xy_grid.py/txt2img/X values/visible": true, + "customscript/xy_grid.py/txt2img/Y type/visible": true, + "customscript/xy_grid.py/txt2img/Y type/value": "Nothing", + "customscript/xy_grid.py/txt2img/Y values/visible": true, + "customscript/xy_grid.py/txt2img/Draw legend/visible": true, + "customscript/xy_grid.py/txt2img/Include Separate Images/visible": true, + "customscript/xy_grid.py/txt2img/Keep -1 for seeds/visible": true, + "img2img/Styles/visible": true, + "img2img/Styles/value": [], + "img2img/Mask transparency/value": 0, + "img2img/Mask transparency/minimum": 0, + "img2img/Mask transparency/maximum": 100, + "img2img/Mask transparency/step": 1, + "img2img/Inpaint area/visible": true, + "img2img/Inpaint area/value": "Whole picture", + "img2img/Only masked padding, pixels/visible": true, + "img2img/Only masked padding, pixels/value": 32, + "img2img/Only masked padding, pixels/minimum": 0, + "img2img/Only masked padding, pixels/maximum": 256, + "img2img/Only masked padding, pixels/step": 4, + "img2img/Sampling steps/visible": true, + "img2img/Sampling steps/value": 20, + "img2img/Sampling steps/minimum": 1, + "img2img/Sampling steps/maximum": 150, + "img2img/Sampling steps/step": 1, + "customscript/custom_code.py/img2img/Python code/visible": true, + "customscript/img2imgalt.py/img2img/Override `Sampling method` to Euler?(this method is built for it)/visible": true, + "customscript/img2imgalt.py/img2img/Override `prompt` to the same value as `original prompt`?(and `negative prompt`)/visible": true, + "customscript/img2imgalt.py/img2img/Original prompt/visible": true, + "customscript/img2imgalt.py/img2img/Original negative prompt/visible": true, + "customscript/img2imgalt.py/img2img/Override `Sampling Steps` to the same value as `Decode steps`?/visible": true, + "customscript/img2imgalt.py/img2img/Decode steps/visible": true, + "customscript/img2imgalt.py/img2img/Override `Denoising strength` to 1?/visible": true, + "customscript/img2imgalt.py/img2img/Decode CFG scale/visible": true, + "customscript/img2imgalt.py/img2img/Randomness/visible": true, + "customscript/img2imgalt.py/img2img/Sigma adjustment for finding noise for image/visible": true, + "customscript/loopback.py/img2img/Loops/visible": true, + "customscript/loopback.py/img2img/Denoising strength change factor/visible": true, + "customscript/outpainting_mk_2.py/img2img/Pixels to expand/visible": true, + "customscript/outpainting_mk_2.py/img2img/Mask blur/visible": true, + "customscript/outpainting_mk_2.py/img2img/Fall-off exponent (lower=higher detail)/visible": true, + "customscript/outpainting_mk_2.py/img2img/Color variation/visible": true, + "customscript/poor_mans_outpainting.py/img2img/Pixels to expand/visible": true, + "customscript/poor_mans_outpainting.py/img2img/Mask blur/visible": true, + "customscript/poor_mans_outpainting.py/img2img/Masked content/visible": true, + "customscript/prompt_matrix.py/img2img/Put variable parts at start of prompt/visible": true, + "customscript/prompt_matrix.py/img2img/Use different seed for each picture/visible": true, + "customscript/prompt_matrix.py/img2img/Use different seed for each picture/value": false, + "customscript/prompts_from_file.py/img2img/Iterate seed every line/visible": true, + "customscript/prompts_from_file.py/img2img/Use same random seed for all lines/visible": true, + "customscript/prompts_from_file.py/img2img/List of prompt inputs/visible": true, + "customscript/sd_upscale.py/img2img/Tile overlap/visible": true, + "customscript/sd_upscale.py/img2img/Scale Factor/visible": true, + "customscript/sd_upscale.py/img2img/Scale Factor/value": 2.0, + "customscript/sd_upscale.py/img2img/Scale Factor/minimum": 1.0, + "customscript/sd_upscale.py/img2img/Scale Factor/maximum": 4.0, + "customscript/sd_upscale.py/img2img/Scale Factor/step": 0.05, + "customscript/sd_upscale.py/img2img/Upscaler/visible": true, + "customscript/xy_grid.py/img2img/X type/visible": true, + "customscript/xy_grid.py/img2img/X type/value": "Seed", + "customscript/xy_grid.py/img2img/X values/visible": true, + "customscript/xy_grid.py/img2img/Y type/visible": true, + "customscript/xy_grid.py/img2img/Y type/value": "Nothing", + "customscript/xy_grid.py/img2img/Y values/visible": true, + "customscript/xy_grid.py/img2img/Draw legend/visible": true, + "customscript/xy_grid.py/img2img/Include Separate Images/visible": true, + "customscript/xy_grid.py/img2img/Keep -1 for seeds/visible": true, + "customscript/postprocessing_upscale.py/extras/Resize/visible": true, + "customscript/postprocessing_upscale.py/extras/Resize/value": 4, + "customscript/postprocessing_upscale.py/extras/Resize/minimum": 1.0, + "customscript/postprocessing_upscale.py/extras/Resize/maximum": 8.0, + "customscript/postprocessing_upscale.py/extras/Resize/step": 0.05, + "customscript/postprocessing_upscale.py/extras/Width/visible": true, + "customscript/postprocessing_upscale.py/extras/Width/value": 512, + "customscript/postprocessing_upscale.py/extras/Height/visible": true, + "customscript/postprocessing_upscale.py/extras/Height/value": 512, + "customscript/postprocessing_upscale.py/extras/Crop to fit/visible": true, + "customscript/postprocessing_upscale.py/extras/Crop to fit/value": true, + "customscript/postprocessing_upscale.py/extras/Upscaler 1/visible": true, + "customscript/postprocessing_upscale.py/extras/Upscaler 1/value": "None", + "customscript/postprocessing_upscale.py/extras/Upscaler 2/visible": true, + "customscript/postprocessing_upscale.py/extras/Upscaler 2/value": "None", + "customscript/postprocessing_upscale.py/extras/Upscaler 2 visibility/visible": true, + "customscript/postprocessing_upscale.py/extras/Upscaler 2 visibility/value": 0.0, + "customscript/postprocessing_upscale.py/extras/Upscaler 2 visibility/minimum": 0.0, + "customscript/postprocessing_upscale.py/extras/Upscaler 2 visibility/maximum": 1.0, + "customscript/postprocessing_upscale.py/extras/Upscaler 2 visibility/step": 0.001, + "customscript/postprocessing_gfpgan.py/extras/GFPGAN visibility/visible": true, + "customscript/postprocessing_gfpgan.py/extras/GFPGAN visibility/value": 0, + "customscript/postprocessing_gfpgan.py/extras/GFPGAN visibility/minimum": 0.0, + "customscript/postprocessing_gfpgan.py/extras/GFPGAN visibility/maximum": 1.0, + "customscript/postprocessing_gfpgan.py/extras/GFPGAN visibility/step": 0.001, + "customscript/postprocessing_codeformer.py/extras/CodeFormer visibility/visible": true, + "customscript/postprocessing_codeformer.py/extras/CodeFormer visibility/value": 0, + "customscript/postprocessing_codeformer.py/extras/CodeFormer visibility/minimum": 0.0, + "customscript/postprocessing_codeformer.py/extras/CodeFormer visibility/maximum": 1.0, + "customscript/postprocessing_codeformer.py/extras/CodeFormer visibility/step": 0.001, + "customscript/postprocessing_codeformer.py/extras/CodeFormer weight (0 = maximum effect, 1 = minimum effect)/visible": true, + "customscript/postprocessing_codeformer.py/extras/CodeFormer weight (0 = maximum effect, 1 = minimum effect)/value": 0, + "customscript/postprocessing_codeformer.py/extras/CodeFormer weight (0 = maximum effect, 1 = minimum effect)/minimum": 0.0, + "customscript/postprocessing_codeformer.py/extras/CodeFormer weight (0 = maximum effect, 1 = minimum effect)/maximum": 1.0, + "customscript/postprocessing_codeformer.py/extras/CodeFormer weight (0 = maximum effect, 1 = minimum effect)/step": 0.001, + "modelmerger/Primary model (A)/visible": true, + "modelmerger/Primary model (A)/value": null, + "modelmerger/Secondary model (B)/visible": true, + "modelmerger/Secondary model (B)/value": null, + "modelmerger/Tertiary model (C)/visible": true, + "modelmerger/Tertiary model (C)/value": null, + "modelmerger/Checkpoint format/visible": true, + "modelmerger/Checkpoint format/value": "ckpt", + "modelmerger/Copy config from/visible": true, + "modelmerger/Copy config from/value": "A, B or C", + "modelmerger/Bake in VAE/visible": true, + "modelmerger/Bake in VAE/value": "None", + "modelmerger/Discard weights with matching name/visible": true, + "modelmerger/Discard weights with matching name/value": "", + "train/Name/visible": true, + "train/Name/value": "", + "train/Initialization text/visible": true, + "train/Initialization text/value": "*", + "train/Number of vectors per token/visible": true, + "train/Number of vectors per token/value": 1, + "train/Number of vectors per token/minimum": 1, + "train/Number of vectors per token/maximum": 75, + "train/Number of vectors per token/step": 1, + "train/Overwrite Old Embedding/visible": true, + "train/Overwrite Old Embedding/value": false, + "train/Enter hypernetwork layer structure/visible": true, + "train/Enter hypernetwork layer structure/value": "1, 2, 1", + "train/Select activation function of hypernetwork. Recommended : Swish / Linear(none)/visible": true, + "train/Select activation function of hypernetwork. Recommended : Swish / Linear(none)/value": "linear", + "train/Select Layer weights initialization. Recommended: Kaiming for relu-like, Xavier for sigmoid-like, Normal otherwise/visible": true, + "train/Select Layer weights initialization. Recommended: Kaiming for relu-like, Xavier for sigmoid-like, Normal otherwise/value": "Normal", + "train/Add layer normalization/visible": true, + "train/Add layer normalization/value": false, + "train/Use dropout/visible": true, + "train/Use dropout/value": false, + "train/Enter hypernetwork Dropout structure (or empty). Recommended : 0~0.35 incrementing sequence: 0, 0.05, 0.15/visible": true, + "train/Enter hypernetwork Dropout structure (or empty). Recommended : 0~0.35 incrementing sequence: 0, 0.05, 0.15/value": "0, 0, 0", + "train/Overwrite Old Hypernetwork/visible": true, + "train/Overwrite Old Hypernetwork/value": false, + "train/Source directory/visible": true, + "train/Source directory/value": "", + "train/Destination directory/visible": true, + "train/Destination directory/value": "", + "train/Width/visible": true, + "train/Width/value": 512, + "train/Width/minimum": 64, + "train/Width/maximum": 2048, + "train/Width/step": 8, + "train/Height/visible": true, + "train/Height/value": 512, + "train/Height/minimum": 64, + "train/Height/maximum": 2048, + "train/Height/step": 8, + "train/Existing Caption txt Action/visible": true, + "train/Existing Caption txt Action/value": "ignore", + "train/Create flipped copies/visible": true, + "train/Create flipped copies/value": false, + "train/Split oversized images/visible": true, + "train/Split oversized images/value": false, + "train/Auto focal point crop/visible": true, + "train/Auto focal point crop/value": false, + "train/Auto-sized crop/visible": true, + "train/Auto-sized crop/value": false, + "train/Use BLIP for caption/visible": true, + "train/Use BLIP for caption/value": false, + "train/Use deepbooru for caption/visible": true, + "train/Use deepbooru for caption/value": false, + "train/Split image threshold/visible": true, + "train/Split image threshold/value": 0.5, + "train/Split image threshold/minimum": 0.0, + "train/Split image threshold/maximum": 1.0, + "train/Split image threshold/step": 0.05, + "train/Split image overlap ratio/visible": true, + "train/Split image overlap ratio/value": 0.2, + "train/Split image overlap ratio/minimum": 0.0, + "train/Split image overlap ratio/maximum": 0.9, + "train/Split image overlap ratio/step": 0.05, + "train/Focal point face weight/visible": true, + "train/Focal point face weight/value": 0.9, + "train/Focal point face weight/minimum": 0.0, + "train/Focal point face weight/maximum": 1.0, + "train/Focal point face weight/step": 0.05, + "train/Focal point entropy weight/visible": true, + "train/Focal point entropy weight/value": 0.15, + "train/Focal point entropy weight/minimum": 0.0, + "train/Focal point entropy weight/maximum": 1.0, + "train/Focal point entropy weight/step": 0.05, + "train/Focal point edges weight/visible": true, + "train/Focal point edges weight/value": 0.5, + "train/Focal point edges weight/minimum": 0.0, + "train/Focal point edges weight/maximum": 1.0, + "train/Focal point edges weight/step": 0.05, + "train/Create debug image/visible": true, + "train/Create debug image/value": false, + "train/Dimension lower bound/visible": true, + "train/Dimension lower bound/value": 384, + "train/Dimension lower bound/minimum": 64, + "train/Dimension lower bound/maximum": 2048, + "train/Dimension lower bound/step": 8, + "train/Dimension upper bound/visible": true, + "train/Dimension upper bound/value": 768, + "train/Dimension upper bound/minimum": 64, + "train/Dimension upper bound/maximum": 2048, + "train/Dimension upper bound/step": 8, + "train/Area lower bound/visible": true, + "train/Area lower bound/value": 4096, + "train/Area lower bound/minimum": 4096, + "train/Area lower bound/maximum": 4194304, + "train/Area lower bound/step": 1, + "train/Area upper bound/visible": true, + "train/Area upper bound/value": 409600, + "train/Area upper bound/minimum": 4096, + "train/Area upper bound/maximum": 4194304, + "train/Area upper bound/step": 1, + "train/Resizing objective/visible": true, + "train/Resizing objective/value": "Maximize area", + "train/Error threshold/visible": true, + "train/Error threshold/value": 0.1, + "train/Error threshold/minimum": 0, + "train/Error threshold/maximum": 1, + "train/Error threshold/step": 0.01, + "train/Embedding/visible": true, + "train/Embedding/value": null, + "train/Hypernetwork/visible": true, + "train/Hypernetwork/value": null, + "train/Embedding Learning rate/visible": true, + "train/Embedding Learning rate/value": "0.005", + "train/Hypernetwork Learning rate/visible": true, + "train/Hypernetwork Learning rate/value": "0.00001", + "train/Gradient Clipping/visible": true, + "train/Gradient Clipping/value": "disabled", + "train/Batch size/visible": true, + "train/Batch size/value": 1, + "train/Gradient accumulation steps/visible": true, + "train/Gradient accumulation steps/value": 1, + "train/Dataset directory/visible": true, + "train/Dataset directory/value": "", + "train/Log directory/visible": true, + "train/Log directory/value": "textual_inversion", + "train/Prompt template/visible": true, + "train/Prompt template/value": "style_filewords.txt", + "train/Do not resize images/visible": true, + "train/Do not resize images/value": false, + "train/Max steps/visible": true, + "train/Max steps/value": 100000, + "train/Save an image to log directory every N steps, 0 to disable/visible": true, + "train/Save an image to log directory every N steps, 0 to disable/value": 500, + "train/Save a copy of embedding to log directory every N steps, 0 to disable/visible": true, + "train/Save a copy of embedding to log directory every N steps, 0 to disable/value": 500, + "train/Save images with embedding in PNG chunks/visible": true, + "train/Save images with embedding in PNG chunks/value": true, + "train/Read parameters (prompt, etc...) from txt2img tab when making previews/visible": true, + "train/Read parameters (prompt, etc...) from txt2img tab when making previews/value": false, + "train/Shuffle tags by ',' when creating prompts./visible": true, + "train/Shuffle tags by ',' when creating prompts./value": false, + "train/Drop out tags when creating prompts./visible": true, + "train/Drop out tags when creating prompts./value": 0, + "train/Drop out tags when creating prompts./minimum": 0, + "train/Drop out tags when creating prompts./maximum": 1, + "train/Drop out tags when creating prompts./step": 0.1, + "train/Choose latent sampling method/visible": true, + "train/Choose latent sampling method/value": "once" +} \ No newline at end of file diff --git a/Notebooks/AI/Visual/Generate/Stable-Diffusion-WebUI/Stable-Diffusion_WebUI.ipynb b/Notebooks/AI/Visual/Generate/Stable-Diffusion-WebUI/Stable-Diffusion_WebUI.ipynb new file mode 100644 index 0000000..ac66b0c --- /dev/null +++ b/Notebooks/AI/Visual/Generate/Stable-Diffusion-WebUI/Stable-Diffusion_WebUI.ipynb @@ -0,0 +1,747 @@ +{ + "metadata": { + "accelerator": "GPU", + "colab": { + "name": "Stable-Diffusion-WebUI (Old)", + "collapsed_sections": [ + "n6stH_uiejQc", + "PbAjvcMog1LM" + ] + }, + "gpuClass": "standard", + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 0, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "gfKvWAVnz8OB" + }, + "source": [ + "[Stable Diffusion WebUI](https://github.com/AUTOMATIC1111/stable-diffusion-webui)\n", + "
\n", + "\n", + "โ„น๏ธ ***Requires [HuggingFace](https://hf.co/login) account!***\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "61-1k-wIfY9Y" + }, + "source": [ + "# ๐Ÿ“ Documentation" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "StGCee2ofS0a" + }, + "source": [ + "## ๐Ÿ”— Useful Websites Index\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "source": [ + "| โ„– | Website | Additional Description | Language |\n", + "|:-:|:-:|:-:|:-:|\n", + "| 01 | **[Models List](https://rentry.org/sdmodels)** | Contains over `150` models. | ๐Ÿ‡บ๐Ÿ‡ธ English |\n", + "| 02 | [DreamBooth models library](https://hf.co/sd-dreambooth-library) | Contains over `200` models
in different styles **and quality**. | ๐Ÿ‡บ๐Ÿ‡ธ English |\n", + "| 03 | [Subreddit](https://www.reddit.com/r/StableDiffusion/new) | | ๐Ÿ‡บ๐Ÿ‡ธ English |\n", + "| 04 | **[Prompts library](https://publicprompts.art/prompts-library)** | Small. | ๐Ÿ‡บ๐Ÿ‡ธ English |\n", + "| 05 | [Stable Diffusion prompt guide](https://prompthero.com/stable-diffusion-prompt-guide#top) | Childish. | ๐Ÿ‡บ๐Ÿ‡ธ English |\n", + "| 06 | [*ExHentai* translated tags](https://github.com/scooderic/exhentai-tags-chinese-translation) | Useful with creating anime pornography. | ๐Ÿ‡บ๐Ÿ‡ธ English |\n", + "| 07 | [***NovelAI Tag Experiments***](https://zele.st/NovelAI) | May be useful with anime models. | ๐Ÿ‡บ๐Ÿ‡ธ English |\n", + "| 08 | [Anime models Keywords](https://paste.ubuntu.com/p/dFBhdJR8PQ) | | ๐Ÿ‡ฏ๐Ÿ‡ต Japanese |\n", + "| 09 | **[HuggingFace space community creations](https://hf.co/spaces/stabilityai/stable-diffusion/discussions)** | Created with [Stable Diffusion `v1.4`](https://hf.co/CompVis/stable-diffusion-v1-4) | ๐Ÿ‡บ๐Ÿ‡ธ English |" + ], + "metadata": { + "id": "ferH77QwL4cJ" + } + }, + { + "cell_type": "markdown", + "metadata": { + "id": "QoaRp0emf6LN" + }, + "source": [ + "---\n", + "# ๐Ÿ–ฅ๏ธ Program" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "n6stH_uiejQc" + }, + "source": [ + "## ๐ŸŒ **Main**" + ] + }, + { + "cell_type": "code", + "metadata": { + "cellView": "form", + "id": "nC5n0manejQg" + }, + "source": [ + "#@title ## **1.** Install requirements.\n", + "#@markdown - [`Stable-Diffusion-WebUI`](https://github.com/AUTOMATIC1111/stable-diffusion-webui)\n", + "#@markdown - [`JPEGOptim`](https://github.com/tjko/jpegoptim)\n", + "\n", + "#@markdown ---\n", + "\n", + "WebUI_Version = \"08 November 2022\" #@param [\"Latest\", \"08 November 2022\"]\n", + "\n", + "#@markdown
\n", + "#@markdown\n", + "#@markdown | Version | Simpler GUI | Image previews | `.safetensors` | Plugins | Hypernetworks | AddNet |\n", + "#@markdown |:-:|:-:|:-:|:-:|:-:|:-:|:-:|\n", + "#@markdown | Latest | โŒ | [**โŒ**](https://github.com/AUTOMATIC1111/stable-diffusion-webui/discussions/4092) | โœ”๏ธ | โœ”๏ธ | โœ”๏ธ | โœ”๏ธ | โœ”๏ธ |\n", + "#@markdown | 08 November 2022 | โœ”๏ธ | **โœ”** | โŒ | โ” | โ” | โŒ |\n", + "\n", + "#@markdown ---\n", + "\n", + "#@markdown # ๐Ÿ“ Custom configuration\n", + "#@markdown Input **direct links** to files. ๐Ÿ”—\n", + "URL_Config_JSON = \"https://raw.githubusercontent.com/kubinka0505/colab-notebooks/master/Notebooks/AI/Visual/Generate/Stable-Diffusion-WebUI/Config/config.json\" #@param {type: \"string\"}\n", + "URL_Styles_CSV = \"https://raw.githubusercontent.com/kubinka0505/colab-notebooks/master/Notebooks/AI/Visual/Generate/Stable-Diffusion-WebUI/Config/styles.csv\" #@param {type: \"string\"}\n", + "URL_UI_Config_JSON = \"https://raw.githubusercontent.com/kubinka0505/colab-notebooks/master/Notebooks/AI/Visual/Generate/Stable-Diffusion-WebUI/Config/ui-config.json\" #@param {type: \"string\"}\n", + "URL_Style_CSS = \"\" #@param {type: \"string\"}\n", + "\n", + "#-=-=-=-#\n", + "\n", + "import sys\n", + "import cv2\n", + "import json\n", + "import IPython\n", + "from os import *\n", + "from time import time\n", + "from gc import collect\n", + "from pathlib import Path\n", + "from shutil import rmtree\n", + "from requests import head\n", + "from PIL import ImageColor\n", + "from zipfile import ZipFile\n", + "from tensorflow import config\n", + "from subprocess import getoutput\n", + "from torch.cuda import empty_cache\n", + "del open\n", + "\n", + "try:\n", + "\tfrom google.colab import drive, files\n", + "\tis_Colab = 1\n", + "\tPython = \"python\"\n", + "\t__Return = \"\"\n", + "except ImportError:\n", + "\tis_Colab = 0\n", + "\tPython = sys.executable\n", + "\t__Return = \"\\r\"\n", + "__Return += \" \" * 150\n", + "\n", + "GPU = config.list_physical_devices(\"GPU\")[0].device_type == \"GPU\"\n", + "if not GPU:\n", + "\traise SystemExit(\"GPU unavailable, exiting\")\n", + "\n", + "chdir(\"/content/\")\n", + "system(\"\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "__author__ = \"kubinka0505\"\n", + "__credits__ = [\n", + "\t\"exlolicon\",\n", + "\t\"Voldy\",\n", + "\t\"FuouM\",\n", + "\t\"Neo Hidamari\",\n", + "\t\"kubinka0505\"\n", + "]\n", + "__version__ = \"1.3\"\n", + "__date__ = \"27.01.2023\"\n", + "\n", + "#-=-=-=-#\n", + "\n", + "def DirSize(Directory: str) -> int:\n", + "\t\"\"\"Calculates folder size recursively\"\"\"\n", + "\tSize = 0\n", + "\tfor File in Path(Directory).rglob(\"*.*\"):\n", + "\t\tSize += path.getsize(File)\n", + "\t#-=-=-=-#\n", + "\treturn Size\n", + "\n", + "def HumanReadableSize(Bytes: float) -> str:\n", + "\t\"\"\"Returns human-readable file size\"\"\"\n", + "\tfor Unit in [\"B\", \"KB\", \"MB\", \"GB\"]:\n", + "\t\tif Bytes < 1024:\n", + "\t\t\tbreak\n", + "\t\tBytes /= 1024.\n", + "\t#-=-=-=-#\n", + "\treturn \"{0} {1}\".format(round(Bytes, 2), Unit)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "__Path = \"/content/stable-diffusion-webui/\"\n", + "if path.exists(__Path):\n", + "\trmtree(__Path)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "# - Languages - #\n", + "__LanguageRepos = {\n", + "\t\"Chinese (Simplified)\": \"https://github.com/dtlnor/stable-diffusion-webui-localization-zh_CN\",\n", + "\t\"Chinese (Traditional)\": \"https://github.com/benlisquare/stable-diffusion-webui-localization-zh_TW\",\n", + "\t\"German\": \"https://github.com/Strothis/stable-diffusion-webui-de_DE\",\n", + "\t\"Italian\": \"https://github.com/Harvester62/stable-diffusion-webui-localization-it_IT\",\n", + "\t\"Japanese\": \"https://github.com/yuuki76/webui-localization-ja_JP\",\n", + "\t\"Korean\": \"https://github.com/36DB/stable-diffusion-webui-localization-ko_KR\",\n", + "\t\"Norwegian\": \"https://github.com/Cyanz83/stable-diffusion-webui-localization-no_NO\",\n", + "\t\"Portuguese\": \"https://github.com/M-art-ucci/stable-diffusion-webui-localization-pt_BR\",\n", + "\t\"Spanish\": \"https://github.com/innovaciones/stable-diffusion-webui-localization-es_ES\",\n", + "\t\"Turkish\": \"https://github.com/camenduru/stable-diffusion-webui-localization-tr_TR\"\n", + "}\n", + "\n", + "# - Custom Configuration - #\n", + "__Styles = {\n", + "\t\"config.json\": URL_Config_JSON,\n", + "\t\"styles.csv\": URL_Styles_CSV,\n", + "\t\"ui-config.json\": URL_UI_Config_JSON,\n", + "\t\"style.css\": URL_Style_CSS\n", + "}\n", + "\n", + "#-=-=-=-#\n", + "\n", + "__C = ImageColor.getrgb(\"#0F0\")\n", + "__C_Green = f\"\\033[1m\\x1b[38;2;{__C[0]};{__C[1]};{__C[2]}m\"\n", + "__C_Reset = \"\\33[0m\"\n", + "printC = lambda Text, Prefix = \"\\n\": \\\n", + "\tprint(f\"{__C_Green}{Prefix}Installing {str(Text)}...{__C_Reset}\")\n", + "\n", + "printC(\"Stable-Diffusion-WebUI\", \"\")\n", + "if \"Latest\" in WebUI_Version:\n", + "\tAuthor = \"AUTOMATIC1111\"\n", + "else:\n", + "\tAuthor = \"kubinka0505\"\n", + "\t!pip install -U fastapi==0.90.1\n", + "Repository = f\"https://github.com/{Author}/stable-diffusion-webui\"\n", + "\n", + "!git clone $Repository\n", + "chdir(__Path)\n", + "\n", + "printC(\"Stable-Diffusion-WebUI dependencies\")\n", + "!COMMANDLINE_ARGS=\"--exit\" REQS_FILE=\"requirements.txt\" $Python launch.py\n", + "print()\n", + "\n", + "#-=-=-=-#\n", + "\n", + "print(\"โ€•\" * 32)\n", + "\n", + "printC(\"JPEGOptim\")\n", + "!apt-get install jpegoptim\n", + "\n", + "#-=-=-=-#\n", + "\n", + "if \"Latest\" in WebUI_Version:\n", + "\tchdir(path.join(__Path, \"localizations/\"))\n", + "\tprintC(\"Languages\")\n", + "\n", + "\tif path.exists(\"./localizations\"):\n", + "\t\trmtree(\"./localizations\")\n", + "\n", + "\tCounter = 1\n", + "\tfor Name, Repository in __LanguageRepos.items():\n", + "\t\t#-=-=-=-#\n", + "\t\t# Author\n", + "\t\tUser = Repository.split(\"/\")[3]\n", + "\t\t# Repository name\n", + "\t\tName = Repository.split(\"/\")[-1]\n", + "\t\t# Language code\n", + "\t\tFile = Repository.split(\"-\")[-1] + \".json\"\n", + "\t\t#-=-=-=-#\n", + "\t\tRepository = f\"https://raw.githubusercontent.com/{User}/{Name}/master/localizations/{File}\"\n", + "\t\tprint(f\"\\t[{__Counter}/{len(__Languages.values())}] {Name}...\", end = __Return)\n", + "\t\t!curl -s -Lo $File $Repository > /dev/null\n", + "\n", + "\tchdir(__Path)\n", + " \n", + "printC(\"Custom Configuration\")\n", + "for Key, Value in __Styles.items():\n", + "\tKey = path.abspath(Key)\n", + "\tif path.exists(Key):\n", + "\t\tif Value:\n", + "\t\t\tremove(Key)\n", + "\tif Value:\n", + "\t\twith head(Value, allow_redirects = 1) as Site:\n", + "\t\t\tprint(f'\\rDownloading \"{Key.split(sep)[-1]}\"', end = __Return)\n", + "\t\t\tif not Site.ok:\n", + "\t\t\t\traise SystemExit('Can\\'t fetch \"{0}\" file: {1} (\"{2}\").'.format(\n", + "\t\t\t\t\tSite.url.split(\"/\")[-1], Site.status_code, Site.reason\n", + "\t\t\t\t\t)\n", + "\t\t\t\t)\n", + "\t\t\t!curl -Lo $Key $Value" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "DQC21mwk3Rpn", + "cellView": "form" + }, + "source": [ + "#@title # **2.** Install **diffusers**.\n", + "#@markdown ### โ„น๏ธ **Most models are pruned `EMA`s in `float16` format.**\n", + "\n", + "#@markdown | โ„– | Name | Version | Size | `CKPT` | `VAE` | Trained on | Trigger phrase
(prompt beggining) |\n", + "#@markdown |:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|\n", + "#@markdown | 01 | [Stable Diffusion](https://hf.co/runwayml/stable-diffusion-v1-5) | 1.5 |**`4.27 GB`** | โœ”๏ธ | โŒ | *Latent, [Stable Diffusion `v1.2`](http://hf.co/CompVis/stable-diffusion-v1-2)* | |\n", + "#@markdown | 02 | [Stable Diffusion](https://hf.co/CompVis/stable-diffusion-v1-4) | 1.4 | **`4.00 GB`** | โœ”๏ธ |\tโŒ | *Latent, [Stable Diffusion `v1.2`](http://hf.co/CompVis/stable-diffusion-v1-2)* | |\n", + "#@markdown | 03 | [OpenJourney](https://hf.co/prompthero/midjourney-v4-diffusion) | 4.0 | **`2.13 GB`** | โœ”๏ธ | โŒ | Midjourney images | `mdjrny-v4 style` |\n", + "#@markdown | 04 | [DreamLike PhotoReal](https://hf.co/dreamlike-art/dreamlike-photoreal-2.0) | 2.0 | **`2.13 GB`** | โœ”๏ธ | โŒ | [Stable Diffusion `v1.5`](https://hf.co/runwayml/stable-diffusion-v1-5) | `photo` *(optional)* |\n", + "#@markdown | 05 | [ProtoGen](https://hf.co/darkstorm2150/Protogen_x5.3_Official_Release) | 5.3 | **`1.72 GB`** | โœ”๏ธ | โŒ | | |\n", + "#@markdown | 06 | Novel AI | | **`4.13 GB`** | โœ”๏ธ | **โœ”๏ธ** | | |\n", + "#@markdown | 07 | [AniReal](https://hf.co/Hosioka/AniReal) | 1.3 | **`2.13 GB`** | **โŒ** | **โœ”๏ธ** | *Danbooru* photorealistic
anime illustrations | [**Danbooru tags**](https://danbooru.donmai.us/tags?commit=Search&search[order]=count)\n", + "#@markdown | 08 | [Anything](https://hf.co/andite/anything-v4.0) | 4.5 | **`3.85 GB`** | โœ”๏ธ | **โœ”๏ธ** | | |\n", + "#@markdown | 09 | [AbyssOrangeMix](https://hf.co/WarriorMama777/OrangeMixs) (SFW) | | **`5.98 GB`** | โœ”๏ธ | **โœ”๏ธ** | | |\n", + "#@markdown | 10 | [BloodOrangeMix](https://hf.co/WarriorMama777/OrangeMixs) (NSFW) | | **`5.98 GB`** | โœ”๏ธ | **โœ”๏ธ** | | |\n", + "#@markdown | 11 | [PastelMix](https://hf.co/andite/pastel-mix) | | **`2.13 GB`** | โœ”๏ธ | **โœ”๏ธ** | | `mksks style` *(optional)* |\n", + "#@markdown | 12 | [Kenshi](https://hf.co/SweetLuna/Kenshi) | 1.0 | **`4.27 GB`** | โœ”๏ธ | **โœ”๏ธ** | Multiple models merge | (`WLOP`, `Nixeu`, `Guweiz`) *(optional)* |\n", + "#@markdown | 13 | [Archer Diffusion](https://hf.co/nitrosocke/archer-diffusion) | 3.0 | **`2.13 GB`** | โœ”๏ธ | โŒ | TV-show \"[Archer](https://wikipedia.org/wiki/Archer_(2009_TV_series))\" pictures | `archer style` |\n", + "#@markdown | 14 | [seek.art Mega](https://hf.co/coreco/seek.art_MEGA) | 1.0 | **`2.13 GB`** | โœ”๏ธ | โŒ | |\n", + "#@markdown | 15 | [3D Style](https://hf.co/Guizmus/SD_DreamerCommunities_Collection) | 1.0 | **`2.13 GB`** | โœ”๏ธ | โŒ | [Stable Diffusion `v1.5`](https://hf.co/runwayml/stable-diffusion-v1-5) | `3D Style`\n", + "#@markdown | 16 | [Redshift Diffusion](https://hf.co/nitrosocke/redshift-diffusion) | 1.0 | **`2.13 GB`** | โœ”๏ธ | โŒ | High resolution 3D artworks | `redshift style` |\n", + "#@markdown | 17 | [Elden Ring Diffusion](https://hf.co/nitrosocke/elden-ring-diffusion) | 2.0 | **`2.13 GB`** | โœ”๏ธ | โŒ | \"[Elden Ring](https://wikipedia.org/wiki/Elden_Ring)\" video game art | `elden ring style` |\n", + "#@markdown | 18 | [Robo Diffusion](https://hf.co/nousr/robo-diffusion) | 2.0 | `4.27 GB` | โœ”๏ธ | โŒ | \"*Finetuned Stable Diffusion*\" | `nousr robot` |\n", + "#@markdown | 19 | [Van Gogh Diffusion](https://hf.co/dallinmackay/Van-Gogh-diffusion) | 2.0 | `4.27 GB` | โœ”๏ธ | โŒ | Screenshots of the
\"[Loving Vincent](https://en.wikipedia.org/wiki/Loving_Vincent)\" movie | `lvngvncnt`
|\n", + "#@markdown | 20 | [PaperCut Model](https://hf.co/Fictiverse/Stable_Diffusion_PaperCut_Model) | 1.0 | `4.27 GB` | โœ”๏ธ | โŒ | Paper cut images | `PaperCut` |\n", + "#@markdown | 21 | [App Icons Generator DreamBooth](https://publicprompts.art/app-icons-generator-v1-dreambooth-model) | 1.0 | `2.13 GB` | โœ”๏ธ | **N/A** | | `SKSKS app icon` |\n", + "\n", + "#@markdown ---\n", + "\n", + "#@markdown โš™๏ธ Token can be obtained from **[HuggingFace account settings](http://hf.co/settings/tokens)**.\n", + "\n", + "#@markdown Official *`Stable Diffusion`* models may require it.\n", + "Token = \"\" #@param {type: \"string\"}\n", + "__Header = f\"Authorization: Bearer {Token}\"\n", + "#@markdown *(This is the moment where you should save this notebook copy to your Google Drive)*\n", + "\n", + "#@markdown ---\n", + "\n", + "#@markdown ## ๐Ÿ“ฅ **Models**\n", + "\n", + "#@markdown General Purpose\n", + "Stable_Diffusion_v15 = True #@param {type: \"boolean\"}\n", + "Stable_Diffusion_v14 = False #@param {type: \"boolean\"}\n", + "OpenJourney_v4 = False #@param {type: \"boolean\"}\n", + "DreamLike_PhotoReal_v2 = True #@param {type: \"boolean\"}\n", + "ProtoGen_v53 = True #@param {type: \"boolean\"}\n", + "\n", + "#@markdown Anime\n", + "Novel_AI = False #@param {type: \"boolean\"}\n", + "AniReal_v1 = False #@param {type: \"boolean\"}\n", + "Anything_v45 = True #@param {type: \"boolean\"}\n", + "AbyssOrangeMix_v1 = False #@param {type: \"boolean\"}\n", + "BloodOrangeMix_v1 = True #@param {type: \"boolean\"}\n", + "PastelMix_v1 = True #@param {type: \"boolean\"}\n", + "Kenshi_v1 = False #@param {type: \"boolean\"}\n", + "\n", + "#@markdown Cartoons\n", + "Archer_Diffusion_v3 = False #@param {type: \"boolean\"}\n", + "\n", + "#@markdown Art\n", + "Seek_Art_Mega_v1 = True #@param {type: \"boolean\"}\n", + "_3D_Style_v1 = True #@param {type: \"boolean\"}\n", + "Redshift_Diffusion_v1 = False #@param {type: \"boolean\"}\n", + "Elden_Ring_Diffusion_v3 = False #@param {type: \"boolean\"}\n", + "Robo_Diffusion_v2 = False #@param {type: \"boolean\"}\n", + "Van_Gogh_Diffusion_v1 = False #@param {type: \"boolean\"}\n", + "PaperCut_Model_v1 = False #@param {type: \"boolean\"}\n", + "\n", + "#@markdown Miscellaneous\n", + "App_Icons_Generator_DreamBooth_v1 = False #@param {type: \"boolean\"}\n", + "\n", + "#-=-=-=-#\n", + "\n", + "try:\n", + "\tchdir(path.join(__Path, \"models\"))\n", + "except NameError:\n", + "\traise SystemExit(\"Requirements weren't installed!\\nPlease run the first cell.\")\n", + "\n", + "__Models = {\n", + "\t# General Purpose\n", + "\t\"Stable_Diffusion_v15\": [\n", + "\t\t\"https://hf.co/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.ckpt\"\n", + "\t],\n", + "\t\"Stable_Diffusion_v14\": [\n", + "\t\t\"https://hf.co/CompVis/stable-diffusion-v-1-4-original/resolve/main/sd-v1-4.ckpt\"\n", + "\t],\n", + "\t\"OpenJourney_v4\": [\n", + "\t\t\"https://hf.co/prompthero/openjourney/resolve/main/mdjrny-v4.ckpt\"\n", + "\t],\n", + "\t\"DreamLike_PhotoReal_v2\": [\n", + "\t\t\"https://hf.co/dreamlike-art/dreamlike-photoreal-2.0/resolve/main/dreamlike-photoreal-2.0.ckpt\"\n", + "\t],\n", + "\t\"ProtoGen_v53\": [\n", + "\t\t\"https://hf.co/darkstorm2150/Protogen_x5.3_Official_Release/resolve/main/ProtoGen_X5.3-pruned-fp16.ckpt\"\n", + "\t],\n", + "\t# Anime\n", + "\t\"Novel_AI\": [\n", + "\t\t\"https://cloudflare-ipfs.com/ipfs/bafybeicpamreyp2bsocyk3hpxr7ixb2g2rnrequub3j2ahrkdxbvfbvjc4/model.ckpt\",\n", + "\t\t\"https://hf.co/WarriorMama777/OrangeMixs/resolve/main/VAEs/orangemix.vae.pt\"\n", + "\t],\n", + "\t\"AniReal_v1\": [\n", + "\t\t\"https://hf.co/Hosioka/AniReal/resolve/main/AniReal.safetensors\",\n", + "\t\t\"https://hf.co/Hosioka/AniReal/resolve/main/AniReal.vae.pt\"\n", + "\t],\n", + "\t\"Anything_v45\": [\n", + "\t\t\"https://hf.co/andite/anything-v4.0/resolve/main/anything-v4.5-pruned-fp16.ckpt\",\n", + "\t\t\"https://hf.co/andite/anything-v4.0/resolve/main/anything-v4.0.vae.pt\"\n", + "\t],\n", + "\t\"AbyssOrangeMix_v1\": [\n", + "\t\t\"https://hf.co/WarriorMama777/OrangeMixs/resolve/main/Models/AbyssOrangeMix/AbyssOrangeMix_base.ckpt\",\n", + "\t\t\"https://hf.co/WarriorMama777/OrangeMixs/resolve/main/VAEs/orangemix.vae.pt\"\n", + "\t],\n", + "\t\"BloodOrangeMix_v1\": [\n", + "\t\t\"https://hf.co/WarriorMama777/OrangeMixs/resolve/main/Models/BloodOrangeMix/BloodOrangeMix_half.ckpt\",\n", + "\t\t\"https://hf.co/WarriorMama777/OrangeMixs/resolve/main/VAEs/orangemix.vae.pt\"\n", + "\t],\n", + "\t\"PastelMix_v1\": [\n", + "\t\t\"https://hf.co/andite/pastel-mix/resolve/main/pastelmix-fp16.ckpt\",\n", + "\t\t\"https://hf.co/andite/pastel-mix/resolve/main/pastel-waifu-diffusion.vae.pt\"\n", + "\t],\n", + "\t\"Kenshi_v1\": [\n", + "\t\t\"https://hf.co/SweetLuna/Kenshi/resolve/main/KENSHI%2001/KENSHI01_Pruned.ckpt\",\n", + "\t\t\"https://hf.co/hakurei/waifu-diffusion-v1-4/resolve/main/vae/kl-f8-anime.ckpt\",\n", + "\t],\n", + "\t# Cartoon\n", + "\t\"Archer_Diffusion_v3\": [\n", + "\t\t\"https://hf.co/nitrosocke/archer-diffusion/resolve/main/archer-v1.ckpt\"\n", + "\t],\n", + "\t# Art\n", + "\t\"Seek_Art_Mega_v1\": [\n", + "\t\t\"https://hf.co/coreco/seek.art_MEGA/resolve/main/seek_art_mega_v1.ckpt\"\n", + "\t],\n", + "\t\"_3D_Style_v1\": [\n", + "\t\t\"https://hf.co/Guizmus/SD_DreamerCommunities_Collection/resolve/main/diffusers/3DStyle/3DStyle-v1.ckpt\"\n", + "\t],\n", + "\t\"Redshift_Diffusion_v1\": [\n", + "\t\t\"https://hf.co/nitrosocke/redshift-diffusion/resolve/main/redshift-diffusion-v1.ckpt\"\n", + "\t],\n", + "\t\"Elden_Ring_Diffusion_v3\": [\n", + "\t\t\"https://hf.co/nitrosocke/elden-ring-diffusion/resolve/main/eldenRing-v3-pruned.ckpt\"\n", + "\t],\n", + "\t\"Robo_Diffusion_v2\": [\n", + "\t\t\"https://hf.co/nousr/robo-diffusion-2-base/resolve/main/robo-diffusion-v2-base.ckpt\"\n", + "\t],\n", + "\t\"Van_Gogh_Diffusion_v1\": [\n", + "\t\t\"https://hf.co/dallinmackay/Van-Gogh-diffusion/resolve/main/Van-Gogh-Style-lvngvncnt-v2.ckpt\"\n", + "\t],\n", + "\t\"PaperCut_Model_v1\": [\n", + "\t\t\"https://hf.co/Fictiverse/Stable_Diffusion_PaperCut_Model/resolve/main/PaperCut_v1.ckpt\"\n", + "\t],\n", + "\t# Miscellaneous\n", + "\t\"App_Icons_Generator_DreamBooth_v1\": [\n", + "\t\t\"https://drive.google.com/uc?id=1TNZTQfk0CNZg7nwy033olwOpQAkcglAN\"\n", + "\t]\n", + "}\n", + "\n", + "if not any([eval(Key) for Key in __Models.keys()]):\n", + "\t# ๐Ÿ™‚ #\n", + "\traise Warning(\"What do you want to do?\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "# Verify URLs\n", + "print(f\"{__C_Green}Verifying URL existence{__C_Reset}\")\n", + "try:\n", + "\tfor Key, Value in __Models.items():\n", + "\t\tfor URL in Value:\n", + "\t\t\twith head(URL, headers={\"Authorization\": r\"Bearer {Token}\"}, allow_redirects = 1) as Site:\n", + "\t\t\t\tprint(f\"\\r\\t{URL}\", end = __Return)\n", + "\t\t\t\tif not Site.ok:\n", + "\t\t\t\t\traise SystemExit('Can\\'t fetch \"{0}\" file: {1} (\"{2}\").'.format(\n", + "\t\t\t\t\t\tSite.url.split(\"/\")[-1], Site.status_code, Site.reason\n", + "\t\t\t\t\t\t)\n", + "\t\t\t\t\t)\n", + "except KeyboardInterrupt:\n", + "\tpass\n", + "\n", + "IPython.display.clear_output()\n", + "\n", + "#-=-=-=-#\n", + "\n", + "for Key, Value in __Models.items():\n", + "\tif Key in locals():\n", + "\t\tif eval(Key):\n", + "\t\t\tprintC(Key, \"\")\n", + "\t\t\tfor Model_URL in Value:\n", + "\t\t\t\t# Diffusers\n", + "\t\t\t\tfor Format in (\"ckpt\", \"safetensors\"):\n", + "\t\t\t\t\tif Model_URL.lower().endswith(Format):\n", + "\t\t\t\t\t\tif all((Model_URL.lower().endswith(\"safetensors\"), \"Latest\" not in WebUI_Version)):\n", + "\t\t\t\t\t\t\traise Warning('\".safetensors\" model format isn\\'t supported in this version.\\nPlease read the first cell.')\n", + "\t\t\t\t\t\t\tbreak\n", + "\t\t\t\t\t\telse:\n", + "\t\t\t\t\t\t\tDirectory = path.abspath(\"Stable-diffusion\")\n", + "\t\t\t\t\t\t\tModel_Path = path.join(f\"{Key}.{Format}\")\n", + "\t\t\t\t# VAEs\n", + "\t\t\t\tfor Format in (\".vae.pt\", \".bin\"):\n", + "\t\t\t\t\tif Format in Model_URL.lower():\n", + "\t\t\t\t\t\tDirectory = path.abspath(\"VAE\")\n", + "\t\t\t\t\t\t#-=-=-=-#\n", + "\t\t\t\t\t\t__VAE_FP = Model_URL.lower().split(\"/\")[-1].split(\".\")[1:]\n", + "\t\t\t\t\t\t__VAE_FP = \".\".join(__VAE_FP)\n", + "\t\t\t\t\t\t__VAE_FP = \".\" + __VAE_FP.lstrip(\".\")\n", + "\t\t\t\t\t\t__VAE_FP = __VAE_FP.replace(\".0.vae.pt\", \".vae.pt\")\t# not fixing that\n", + "\t\t\t\t\t\t#-=-=-=-#\n", + "\t\t\t\t\t\tModel_Path = path.join(Key +__VAE_FP)\n", + "\t\t\t\tModel_Path = path.join(Directory, Model_Path)\n", + "\t\t\t\tprint(Model_Path)\n", + "\t\t\t\t#-=-=-=-#\n", + "\t\t\t\tif path.exists(Model_Path):\n", + "\t\t\t\t\tremove(Model_Path)\n", + "\t\t\t\t#-=-=-=-#\n", + "\t\t\t\ttry:\n", + "\t\t\t\t\tif \"drive.google\" in Model_URL.lower():\n", + "\t\t\t\t\t\t!gdown $Model_URL -O $Model_Path\n", + "\t\t\t\t\telse:\n", + "\t\t\t\t\t\t!curl \\\n", + "\t\t\t\t\t\t\t-A \"Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1\" \\\n", + "\t\t\t\t\t\t\t-H \"$__Header\" \\\n", + "\t\t\t\t\t\t\t-Lo $Model_Path \\\n", + "\t\t\t\t\t\t\t$Model_URL\n", + "\t\t\t\t\t\tprint()\n", + "\t\t\t\texcept KeyboardInterrupt:\n", + "\t\t\t\t\tprint(f'Cancelled download of the \"{Key}\" model.')" + ] + }, + { + "cell_type": "code", + "metadata": { + "cellView": "form", + "id": "2KMeCP1nejQh" + }, + "source": [ + "#@title ## **3.** Run.\n", + "Language = \"๐Ÿ‡บ๐Ÿ‡ธ English\" #@param [\"๐Ÿ‡จ๐Ÿ‡ณ Chinese (Simplified)\", \"๐Ÿ‡จ๐Ÿ‡ณ Chinese (Traditional)\", \"๐Ÿ‡บ๐Ÿ‡ธ English\", \"๐Ÿ‡ฉ๐Ÿ‡ช German\", \"๐Ÿ‡ฎ๐Ÿ‡น Italian\", \"๐Ÿ‡ฏ๐Ÿ‡ต Japanese\", \"๐Ÿ‡ฐ๐Ÿ‡ท Korean\", \"๐Ÿ‡ณ๐Ÿ‡ด Norwegian\", \"๐Ÿ‡ต๐Ÿ‡น Portuguese\", \"๐Ÿ‡ช๐Ÿ‡ธ Spanish\", \"๐Ÿ‡น๐Ÿ‡ท Turkish\"]\n", + "#@markdown โš ๏ธ **Doesn't work if `WebUI_Version` is not `Latest`.**\n", + "\n", + "#@markdown ---\n", + "Alert_Notification = True #@param {\"type\": \"boolean\"}\n", + "#@markdown โš ๏ธ **Check only if you are running all subcells from the `Main` at the same time.**\n", + "\n", + "#@markdown ---\n", + "Debug_Mode = True #@param {\"type\": \"boolean\"}\n", + "#@markdown Launch **even if no models were installed**.\n", + "\n", + "#@markdown ---\n", + "\n", + "try:\n", + "\timport fastapi\n", + "except ImportError:\n", + "\traise SystemExit(\"GPU Requirements weren't installed!\\nPlease run the first cell.\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Language = \" \".join(Language.split(\" \")[1:])\n", + "__Languages = {\n", + "\t\t\"Chinese (Simplified)\": \"zh_CN\",\n", + "\t\t\"Chinese (Traditional)\": \"zh_TW\",\n", + "\t\t\"Deutsch\": \"de_DE\",\n", + "\t\t\"English\": \"None\",\n", + "\t\t\"Italian\": \"it_IT\",\n", + "\t\t\"Japanese\": \"ja_JP\",\n", + "\t\t\"Korean\": \"ko_KR\",\n", + "\t\t\"Norwegian\": \"no_NO\",\n", + "\t\t\"Portuguese\": \"pt_BR\",\n", + "\t\t\"Spanish\": \"es_ES\",\n", + "\t\t\"Turkish\": \"tr_TR\"\n", + "}\n", + "\n", + "chdir(__Path)\n", + "with open(\"config.json\", \"r+\") as File:\n", + "\tData = json.load(File)\n", + "\t#-=-=-=#\n", + "\tif \"Latest\" in WebUI_Version:\n", + "\t\tData[\"localization\"] = __Languages[Language]\n", + "\t\tMSG = f\"Launguage set to {Language}.\"\n", + "\telse:\n", + "\t\tMSG = \"Using older version, cannot change language.\"\n", + "\tprint(MSG)\n", + "\t#-=-=-=-#\n", + "\tFile.seek(0)\n", + "\tjson.dump(Data, File, indent = 4)\n", + "\tFile.truncate()\n", + "\n", + "print()\n", + "print(\"โ€•\" * 32)\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Debug_Flag = \"\"\n", + "if not len(list(Path().rglob(\"*.ckpt\"))):\n", + "\tprint()\n", + "\tif not Debug_Mode:\n", + "\t\traise SystemExit(\"No models found, exiting.\\nPlease run subcell 2 from `Main` cell to install models.\")\n", + "\telse:\n", + "\t\tprint(\"No models detected, running in the debug mode.\")\n", + "\t\tDebug_Flag = \"--ui-debug-mode\"\n", + "\n", + "#-=-=-=-#\n", + "\n", + "# Reserve RAM space\n", + "collect()\n", + "empty_cache()\n", + "\n", + "print()\n", + "if Alert_Notification:\n", + "\tdisplay(IPython.display.Javascript('alert(\"Starting soon...\")'))\n", + "\n", + "!$Python webui.py \\\n", + "\t--no-half \\\n", + "\t--allow-code \\\n", + "\t--precision full \\\n", + "\t--share \\\n", + "\t$Debug_Flag \\\n", + "\t--autolaunch \\\n", + "\t--disable-safe-unpickle" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "PbAjvcMog1LM" + }, + "source": [ + "## โš™๏ธ Useful optional postprocessing commands (***use after*** session ends)" + ] + }, + { + "cell_type": "code", + "metadata": { + "cellView": "form", + "id": "sLOycNVfacB9" + }, + "source": [ + "#@title ### ๐Ÿ–ผ๏ธ Convert all output images to HQ `JPG` and optimize ๐Ÿ“‰\n", + "#@markdown ## โš ๏ธ **This cell can only be run once!!!**\n", + "\n", + "try:\n", + "\tchdir(path.join(__Path, \"outputs\"))\n", + "except NameError:\n", + "\traise SystemExit(\"Requirements weren't installed!\\nPlease run the first cell.\")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "__Size_In = DirSize(\".\")\n", + "__Counter = 1\n", + "__Images = []\n", + "\n", + "# Add Images\n", + "for File in Path().rglob(\"*\"):\n", + "\tFile = path.abspath(str(File.resolve()))\n", + "\tif path.exists(File):\n", + "\t\tif path.isfile(File):\n", + "\t\t\t__Images += [File]\n", + "\n", + "# Convert Images\n", + "for File in __Images:\n", + "\tprint(f\"\\r[{__Counter}/{len(__Images)}] Converting images...\", end = __Return)\n", + "\t#-=-=-=-#\n", + "\tName = path.splitext(File)[0] + \".jpg\"\n", + "\t#-=-=-=-#\n", + "\tIMG = cv2.imread(File)\n", + "\tIMG = cv2.cvtColor(IMG, cv2.COLOR_BGR2RGB)\n", + "\tcv2.imwrite(Name, IMG, [int(cv2.IMWRITE_JPEG_QUALITY), 100])\n", + "\tremove(File)\n", + "\t#-=-=-=-#\n", + "\t!jpegoptim -o -m 100 --all-progressive --strip-all \"$Name\" -q\n", + "\t__Counter += 1\n", + "\n", + "#-=-=-=-#\n", + "\n", + "__Size_Out = DirSize(\".\")\n", + "\n", + "if __Size_In == __Size_Out:\n", + "\t__Percentage = \"0.00\"\n", + "else:\n", + "\t__Percentage = round((100 - (__Size_Out / __Size_In) * 100), 2)\n", + "\n", + "__Size_Reduced = HumanReadableSize(__Size_In - __Size_Out)\n", + "__Size_In = HumanReadableSize(__Size_In)\n", + "__Size_Out = HumanReadableSize(DirSize(\".\"))\n", + "\n", + "print(f\"\\nSize reduced from {__Size_In} to {__Size_Out} (-{__Size_Reduced}, {__Percentage}%)\")" + ] + }, + { + "cell_type": "code", + "metadata": { + "cellView": "form", + "id": "81bkjYwJg1LP" + }, + "source": [ + "#@title ### ๐Ÿ—ƒ๏ธ Output images management\n", + "\n", + "try:\n", + "\tif not path.exists(path.join(__Path, \"outputs/\")):\n", + "\t\traise NameError\n", + "except NameError:\n", + "\traise SystemExit(\"Requirements weren't installed!\\nPlease run the first cell.\")\n", + "\n", + "chdir(path.join(__Path, \"outputs/\"))\n", + "\n", + "__Date = str(time()).split(\".\")[-1]\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Action = \"๐Ÿ“ฅ Get Archive\" #@param [\"๐Ÿ“ฅ Get Archive\", \"๐Ÿ“ค Copy pictures to Google Drive\"]\n", + "if \"Archive\" in Action:\n", + "\t__Counter = 1\n", + "\tArchive_Name = path.abspath(\"/content/\" + \"_\".join([\n", + "\t\t\"SD WebUI\", Path().resolve().name.title(), __Date\n", + "\t\t]) + \".zip\"\n", + "\t).replace(\" \", \"_\")\n", + "\t#-=-=-=-#\n", + "\tif path.exists(Archive_Name):\n", + "\t\tremove(Archive_Name)\n", + "\t#-=-=-=-#\n", + "\t__Outputs = [\"./\" + str(File.resolve()).split(getcwd())[-1] for File in Path().rglob(\"*\")]\n", + "\ttry:\n", + "\t\twith ZipFile(Archive_Name, \"w\", 14) as Archive:\n", + "\t\t\tfor File in __Outputs:\n", + "\t\t\t\tprint(f\"\\r[{__Counter}/{len(__Outputs)}] Adding \"{File}\" to archive...\", end = __Return)\n", + "\t\t\t\tArchive.write(File)\n", + "\t\t\t\t__Counter += 1\n", + "\texcept OSError:\n", + "\t\tremove(Archive_Name)\n", + "\texcept KeyboardInterrupt:\n", + "\t\tprint(\"File packing interrupted, saving.\")\n", + "\tprint()\n", + "\tif is_Colab:\n", + "\t\tfiles.download(Archive_Name)\n", + "\telse:\n", + "\t\tprint(\"\\nDone!\")\n", + "elif is_Colab:\n", + "\ttry:\n", + "\t\tdrive.mount(\"/content/drive\", force_remount = 0)\n", + "\texcept:\n", + "\t\tprint(\" mounting drive / with drive path variables\")\n", + "\t!cp -r /outputs \"/content/drive/MyDrive/!_SD_WebUI/Images/$__Date\"\n", + "else:\n", + "\traise Warning(\"Not in Google Colab, cannot upload.\")" + ] + } + ] +} \ No newline at end of file diff --git a/Notebooks/General/Math/Music/Calculators.ipynb b/Notebooks/General/Math/Music/Calculators.ipynb new file mode 100644 index 0000000..1950f70 --- /dev/null +++ b/Notebooks/General/Math/Music/Calculators.ipynb @@ -0,0 +1,179 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "Music Calculators", + "provenance": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "" + }, + "source": [ + "Music functions related to pitch and time. ๐ŸŽถ" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "" + }, + "source": [ + "# **Various** โš™๏ธ" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "", + "cellView": "form" + }, + "source": [ + "#@title ## Closest value to given BPM that can be used for *Dancing Waveform Experiment*\n", + "#@markdown Float values are esmaited.\n", + "BPM = 130.000 #@param {type:\"number\"}\n", + "#---#\n", + "\n", + "BPMs = []\n", + "Values = []\n", + "\n", + "#---#\n", + "\n", + "def frange(start = 0, stop = None, step = 1) -> list:\n", + "\t\"\"\"Range with floats support\"\"\"\n", + "\tn = int(round((stop - start)/float(step)))\n", + "\tif n > 1:\n", + "\t\treturn [start + step*i for i in range(n+1)]\n", + "\telif n == 1:\n", + "\t\treturn [start]\n", + "\telse:\n", + "\t\treturn []\n", + "\n", + "for Value in frange(1, BPM, 0.001):\n", + "\tValues += [round(Value, 3)]\n", + "\n", + "for BPM in Values:\n", + "\tif not len(str(BPM / 60).split(\".\")[-1]) > 2:\n", + "\t\tBPMs += [BPM]\n", + "\n", + "print(min(BPMs, key = lambda Value: abs(Value - BPM)), \"BPM\")" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "", + "cellView": "form" + }, + "source": [ + "#@title ## Time stretch or pitch shift required to convert `From` BPM to `Target` BPM.\n", + "#@markdown Works with sample rates too.\n", + "From = 135 #@param {type: \"number\"}\n", + "Target = 120 #@param {type: \"number\"}\n", + "\n", + "from math import *\n", + "Result_Pitch = ceil((1200 / log(2)) * log(Target / From))\n", + "Result_Time = 100 * (From / Target)\n", + "\n", + "print(\"Time stretch:\\t\" + str(round(Result_Time, 3)) + \"%\")\n", + "print(\"Pitch shift:\\t\" + str(Result_Pitch), \"cents\")" + ], + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Time stretch:\t112.5%\n", + "Pitch shift:\t-203 cents\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "#@title ## Resample by cents.\n", + "#@markdown Values are esmaited.\n", + "SampleRate = 44100 #@param {type: \"number\"}\n", + "Resample_by = -50 #@param {type: \"number\"}\n", + "\n", + "if Resample_by < 0:\n", + "\tSign = \"\"\n", + "\tResample_by_Display = \" \".join((str(Resample_by)[0], str(Resample_by)[1:]))\n", + "else:\n", + "\tSign = \"+ \"\n", + "\tResample_by_Display = Resample_by\n", + "\n", + "from math import *\n", + "for Frequency in range(1, SampleRate):\n", + "\tResult = (1200 / log(2)) * log(Frequency / SampleRate * 2)\n", + "\tif round(Result) == Resample_by:\n", + "\t\tif Resample_by:\n", + "\t\t\tFrequency *= 2\n", + "\t\telse:\n", + "\t\t\tFrequency = SampleRate\n", + "\t\tprint(f\"{SampleRate} Hz {Sign}{Resample_by_Display} cents โ‰ˆ {Frequency} Hz\")\n", + "\t\tbreak" + ], + "metadata": { + "id": "", + "cellView": "form" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "44100 Hz - 50 cents โ‰ˆ 42834 Hz\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "gYRXEkCeHtg1" + }, + "source": [ + "# ๐Ÿ•’ **Time**" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "", + "cellView": "form" + }, + "source": [ + "#@title ## Length of beat and bar. (`4/4`)\n", + "BPM = 135.000 #@param {type:\"number\"}\n", + "\n", + "print(f\"\"\"\n", + "Length of one beat:\\t60 รท {BPM} โ‰ˆ {str(round(60 / BPM, 5))} s\n", + "Length of one bar:\\t240 รท {BPM} โ‰ˆ {str(round(240 / BPM, 5))} s\n", + "\"\"\"[1:-1])" + ], + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Length of one beat:\t60 รท 120 โ‰ˆ 0.5 s\n", + "Length of one bar:\t240 รท 120 โ‰ˆ 2.0 s\n" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/Notebooks/General/Media/Audio/Unisonizer.ipynb b/Notebooks/General/Media/Audio/Unisonizer.ipynb new file mode 100644 index 0000000..2615f38 --- /dev/null +++ b/Notebooks/General/Media/Audio/Unisonizer.ipynb @@ -0,0 +1,158 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "Unisonizer", + "provenance": [], + "collapsed_sections": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + } + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "" + }, + "source": [ + "Upload as many files as You want.\n", + "Notebook will automatically create exclusive folders for them. ๐Ÿ“‚\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "cellView": "form", + "id": "" + }, + "source": [ + "#@title โ† Install modules. **(Required for the first time usage!)**\n", + "%%capture\n", + "!rm -rf sample_data\n", + "!python -m pip install py7zr pydub" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "", + "cellView": "form" + }, + "source": [ + "#@title โ† Remove ALL files. This action is irreversible!\n", + "#@markdown - **Required to restart processing!**\n", + "%%capture\n", + "%cd /content\n", + "!rm -rf *" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "", + "cellView": "form" + }, + "source": [ + "#@title โ† Upload files and Unisonize!\n", + "import os\n", + "from py7zr import *\n", + "from pydub import *\n", + "from IPython.display import *\n", + "from datetime import datetime\n", + "from google.colab import files\n", + "from itertools import zip_longest\n", + "\n", + "#---#\n", + "\n", + "__author__ = \"kubinka0505\"\n", + "__credits__ = __author__\n", + "__version__ = \"1.0\"\n", + "__date__ = \"07.02.2021\"\n", + " \n", + "#---#\n", + "\n", + "Format = \"WAV\" #@param [\"MP3\", \"OGG\", \"WAV\", \"FLAC\"]\n", + "Invert_Phase_for_Even_Files = False #@param {type:\"boolean\"}\n", + "\n", + "#@markdown - After processing files will be packed to `Audio.7z` archive and **downloaded automatically**.\n", + "\n", + "#---#\n", + "\n", + "os.chdir(\"/content/\")\n", + "\n", + "__Time = \"\".join(list(filter(lambda s:s.isdigit(),str(datetime.now()).split(\" \")[1].split(\".\")[0])))\n", + "ArchiveName = \"Audio_{0}.7z\".format(__Time)\n", + "AfterName = \"_stereo\"\n", + "\n", + "if os.listdir() == [\".config\", \".ipynb_checkpoints\"]: Files = files.upload()\n", + "\n", + "Files = sorted([x for x in os.listdir() if x.endswith(\".{0}\".format(Format.lower()))], key = str)\n", + "Files_Sorted = [[y, x] for x, y in zip_longest(Files[1::2], Files[::2])]\n", + "\n", + "# Create folder for each uploaded file\n", + "for _Files in Files_Sorted:\n", + "\tFolderName = _Files[0].split(\".\")[0]\n", + "\tos.mkdir(FolderName)\n", + "\tos.rename(_Files[0], \"{0}/{1}\".format(FolderName, _Files[0]))\n", + "\tos.rename(_Files[1], \"{0}/{1}\".format(FolderName, _Files[1]))\n", + "\n", + "Folders = sorted(next(os.walk(\".\"))[1], key = str)[2:]\n", + "\n", + "# Modify each audio file in previously created folders\n", + "for Folder in Folders:\n", + "\tos.chdir(\"/content/{0}\".format(Folder))\n", + "\n", + "\tFiles__ = os.listdir()\n", + "\n", + "\tName = \"{0}{1}.{2}\".format(Files__[0].split(\".\")[0], AfterName, Format.lower())\n", + "\n", + "\t#---#\n", + "\n", + "\tprint(\"\\r\", end = \"Processing {0}...\".format(Folder))\n", + "\tLeft = AudioSegment.from_file(Files__[0])\n", + "\tRight = AudioSegment.from_file(Files__[1])\n", + "\tif Invert_Phase_for_Even_Files == True: Right = Right.invert_phase()\n", + "\n", + "\tLeft = Left.pan(-1)\n", + "\tRight = Right.pan(1)\n", + "\n", + "\tLeft = Left.normalize(headroom = 0)\n", + "\tRight = Right.normalize(headroom = 0)\n", + "\n", + "\tMulti = Left.overlay(Right)\n", + "\tMulti = Multi.normalize(headroom = 0)\n", + "\n", + "\tMulti.export(Name, format = Format)\n", + "\n", + "\t# Move modified file and remove uploaded files\n", + "\tos.remove(Files__[0])\n", + "\tos.remove(Files__[1])\n", + "\tos.rename(\"{0}/{1}\".format(os.getcwd(), Name), \"{0}/{1}\".format(os.path.realpath(\"..\"), Name))\n", + "\tos.rmdir(os.getcwd())\n", + "\tos.chdir(\"..\")\n", + "\n", + "os.chdir(\"/content/\")\n", + "with SevenZipFile(\n", + "\tArchiveName,\n", + "\t\"w\",\n", + "\tfilters = [{\"id\": FILTER_LZMA2, \"preset\": PRESET_DEFAULT}]\n", + "\t) as Archive:\n", + "\t\tfor x in os.listdir():\n", + "\t\t\tif x.endswith(Format.lower()):\n", + "\t\t\t\tArchive.write(x)\n", + "\n", + "if len(os.listdir()) != 2: files.download(ArchiveName)" + ], + "execution_count": null, + "outputs": [] + } + ] +} diff --git a/Notebooks/General/Media/Visual/Mixed/Hybrid_Image_Video_Cropper/Vertical.ipynb b/Notebooks/General/Media/Visual/Mixed/Hybrid_Image_Video_Cropper/Vertical.ipynb new file mode 100644 index 0000000..9a62ddc --- /dev/null +++ b/Notebooks/General/Media/Visual/Mixed/Hybrid_Image_Video_Cropper/Vertical.ipynb @@ -0,0 +1,233 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "Hybrid Image / Video Cropper [Vertical]", + "provenance": [], + "collapsed_sections": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "code", + "metadata": { + "id": "", + "cellView": "form" + }, + "outputs": [], + "source": [ + "#@title # **1.** Upload files and setup code\n", + "Static_Image_URL = \"\" #@param {type: \"string\"}\n", + "Audio_Top_URL = \"\" #@param {type: \"string\"}\n", + "Audio_Bottom_URL = \"\" #@param {type: \"string\"}\n", + "#@markdown โ„น๏ธ Leave empty for manual upload.\n", + "\n", + "#-=-=-=-#\n", + "\n", + "!pip install ffpb mutagen -q\n", + "\n", + "import os\n", + "from zipfile import *\n", + "from PIL import Image as IMG\n", + "from base64 import b64encode\n", + "from requests import Session\n", + "from shutil import copyfileobj\n", + "from google.colab import files\n", + "from mutagen import File as mFile\n", + "from IPython.display import display, HTML\n", + "\n", + "#-=-=-=-#\n", + "\n", + "!rm -rf *\n", + "Error = lambda exc: SystemExit(exc[0].upper() + exc[1:] + \".\")\n", + "\n", + "session = Session()\n", + "session.headers.update(\n", + "\t{\n", + "\t\t\"User-Agent\":\n", + "\t\t\"Mozilla/5.0 (Windows NT 10.0; Win32; x32) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36\"\n", + "\t}\n", + ")\n", + "get = session.get\n", + "\n", + "def Clamp(Number: float, Minimum: float, Maximum: float) -> float:\n", + "\t\"\"\"Limits `Number` in range (`Minimum`, `Maximum`).\"\"\"\n", + "\treturn max(min(Maximum, Number), Minimum)\n", + "\n", + "def Download(URL: str, Verbose: bool = True) -> str:\n", + "\t\"\"\"Downloads the URL to local directory.\"\"\"\n", + "\tURL = URL.split(\"#\")[0].split(\"?\")[0].split(\"&\")[0]\n", + "\tFile_Name = URL.split(\"/\")[-1]\n", + "\t#-=-=-=-#\n", + "\ttry:\n", + "\t\twith get(URL, stream = 1) as Site:\n", + "\t\t\tif Site.ok:\n", + "\t\t\t\twith open(File_Name, \"wb\") as File:\n", + "\t\t\t\t\tif Verbose:\n", + "\t\t\t\t\t\tprint(f\"Downloading {File_Name}...\")\n", + "\t\t\t\t\tcopyfileobj(Site.raw, File)\n", + "\t\t\telse:\n", + "\t\t\t\traise Error(f\"URL returned status code {Site.stats_code} - {Site.reason.title()}\")\n", + "\texcept OSError:\n", + "\t\traise Error(\"Invalid URL\")\n", + "\t#-=-=-=-#\n", + "\treturn File_Name\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Files_Upload_Dict = {\n", + "\t\"Static_Image\": Static_Image_URL,\n", + "\t\"Audio_Top\": Audio_Top_URL,\n", + "\t\"Audio_Bottom\": Audio_Bottom_URL\n", + "}\n", + "\n", + "for Key, Value in Files_Upload_Dict.items():\n", + "\tif \"Top\" in Key:\n", + "\t\tif not Value:\n", + "\t\t\tprint()\n", + "\t#-=-=-=-#\n", + "\tif Value:\n", + "\t\texec(f'{Key} = Download(\"{Value}\")')\n", + "\telse:\n", + "\t\tprint(f'Upload {\" \".join(Key.split(\"_\")).upper()}...')\n", + "\t\ttry:\n", + "\t\t\texec(f\"{Key} = list(files.upload().keys())[-1]\")\n", + "\t\texcept:\n", + "\t\t\traise Error(\"File selection aborted\")\n", + "\texec(f'{Key} = {Key}.split(os.sep)[-1]')\n", + "\n", + "IMG_File = Static_Image\n", + "SND_Top = Audio_Top\n", + "SND_Bottom = Audio_Bottom\n", + "\n", + "#-=-=-=-#\n", + "\n", + "print(\"\\nUploaded successfully!\")" + ] + }, + { + "cell_type": "code", + "source": [ + "#@title # **2.** Encode\n", + "#@markdown ## Video ๐Ÿ“น\n", + "Preview_Width = 250 #@param {type: \"slider\", min: 75, max: 500, step: 1}\n", + "Preview_Width = str(Preview_Width)\n", + "\n", + "#@markdown ---\n", + "#@markdown ## Audio ๐Ÿ”Š\n", + "Top_Gain = -2.5 #@param {type: \"slider\", min: -5, max: 5, step: 0.1}\n", + "Inverse_Positions = False #@param {type: \"boolean\"}\n", + "\n", + "Top_Gain = str(Top_Gain)\n", + "if Inverse_Positions:\n", + "\tSND1 = SND_Top\n", + "\tSND2 = SND_Bottom\n", + "\t#-=-=-=-#\n", + "\tSND_Top = SND2\n", + "\tSND_Bottom = SND1\n", + "\t#-=-=-=-#\n", + "\tdel SND1, SND2\n", + "\n", + "#-=-=-=-#\n", + "\n", + "Video = \".\".join(IMG_File.split(os.sep)[-1].replace(\" \", \"_\").split(\".\")[:-1])\n", + "\n", + "env = os.environ\n", + "env[\"IMG\"] = IMG_File\n", + "\n", + "Minimum_Bitrate = 16 * 6\n", + "for Key, Value in {\"Top\": 1, \"Bottom\": 2}.items():\n", + "\tSND = \"SND_\" + Key\n", + "\n", + "\t_AF = \"AF_\" + Key\n", + "\t_Box = \"Box_\" + Key\n", + "\t_Gain = \"Gain_\" + Key\n", + "\t_Bitrate = \"Bitrate_\" + Key\n", + "\t_Duration = \"Duration_\" + Key\n", + "\t_Video = \"Video_\" + Key\n", + "\n", + "\t#-=-=-=-#\n", + "\n", + "\ttry:\n", + "\t\texec(f'{_AF} = mFile({SND})')\n", + "\t\tenv[SND] = eval(SND)\n", + "\texcept:\n", + "\t\traise Error(\"Files not found\")\n", + "\tenv[_Bitrate] = str(eval(\n", + "\t\tf\"Clamp({_AF}.info.bitrate // 1000, Minimum_Bitrate, Minimum_Bitrate * 4)\"\n", + "\t\t)\n", + "\t)\n", + "\tenv[_Box] = \"iw:ih/2:0:0\" if Key == \"Top\" else \"iw:ih/2:0:ih/2\"\n", + "\tenv[_Gain] = Top_Gain if Key == \"Top\" else \"0\"\n", + "\tenv[_Bitrate] += \"k\"\n", + "\tenv[_Duration] = str(eval(f\"{_AF}.info.length\"))\n", + "\tenv[_Video] = Video + f\"_{Value}.mp4\"\n", + "\tprint(f\"Encoding {Key.lower()} video...\")\n", + "\n", + "\t#-=-=-=-#\n", + "\n", + "\t!ffpb -y -strict 2 -loop 1 -ss 0 -i \"{IMG_File}\" -i \"{env[SND]}\" \\\n", + "\t-movflags faststart \\\n", + "\t-vf \"pad=ceil(iw/2)*2:ceil(ih/2)*2,crop={env[_Box]}\" \\\n", + "\t-af \"volume={env[_Gain]}dB\" \\\n", + "\t-pix_fmt yuv420p -tune stillimage -sws_flags lanczos \\\n", + "\t-c:v libx264 -c:a aac -b:a {env[_Bitrate]} -to {env[_Duration]} \"{env[_Video]}\"\n", + "\t\n", + "\t#-=-=-=-#\n", + "\n", + "\tprint()\n", + "\n", + "#-=-=-=-#\n", + "\n", + "\n", + "display(\n", + "\tHTML(\"\"\"\n", + "\t\t
\n", + "\t\t
\n", + "\t\t\t\n", + "\t\t\t\n", + "\t\t
\n", + "\t\t
\n", + "\t\"\"\".format(\n", + "\t\t\"data:video/mp4;base64,\" + b64encode(open(f\"{Video}_1.mp4\", \"rb\").read()).decode(),\n", + "\t\t\"data:video/mp4;base64,\" + b64encode(open(f\"{Video}_2.mp4\", \"rb\").read()).decode(),\n", + "\t\tPreview_Width\n", + "\t\t,)\n", + "\t)\n", + ")\n", + "\n", + "#-=-=-=-#\n", + "\n", + "os.chdir(\"/content/\")\n", + "print(\"Downloading archive...\")\n", + "Archive_Name = f\"{Video}_SBS.zip\"\n", + "Archive = ZipFile(Archive_Name, \"w\", 14)\n", + "for Number in [1, 2]:\n", + "\tArchive.write(f\"{Video}_{str(Number)}.mp4\")\n", + "\n", + "files.download(Archive_Name)" + ], + "metadata": { + "id": "", + "cellView": "form" + }, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Notebooks/General/Media/Visual/Video/Simple_Video_Re-Encoder.ipynb b/Notebooks/General/Media/Visual/Video/Simple_Video_Re-Encoder.ipynb new file mode 100644 index 0000000..78684d0 --- /dev/null +++ b/Notebooks/General/Media/Visual/Video/Simple_Video_Re-Encoder.ipynb @@ -0,0 +1,221 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "Simple Video Re-Encoder", + "provenance": [], + "collapsed_sections": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "" + }, + "source": [ + "# *Simple Video Re-Encoder*\n", + "Made with `FFmpeg`" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "", + "cellView": "form" + }, + "source": [ + "#@title # โฎ Upload and process video\n", + "#@markdown ##### ...after filling the forms below โฌ‡๏ธ\n", + "#@markdown ---\n", + "\n", + "#@markdown ## `File ๐Ÿ“`\n", + "URL = \"\" #@param {type:\"string\"}\n", + "Keep_Metadata = False #@param {type:\"boolean\"}\n", + "Output_Preview_Volume = 7.5 #@param {type:\"slider\", min:0.1, max:50, step:0.1}\n", + "#@markdown ## `Audio ๐Ÿ”Š`\n", + "Channels = \"Copy\" #@param [\"Mono\", \"Stereo\", \"Copy\"]\n", + "Bitrate_kbps = \"320\" #@param ['320', '256', '224', '192', '160', '128', '96']\n", + "Samplerate_Hz = \"Copy\" #@param [\"48 000\", \"44 100\", \"32 000\", \"Copy\"]\n", + "#@markdown ## `Video ๐ŸŽฅ`\n", + "Bitrate_mbps = \"Copy\" #@param [\"10\", \"9\", \"8\", \"7\", \"6\", \"5\", \"4\", \"3\", \"2\", \"Copy\"]\n", + "Output_Format_and_Codec = \"MP4 (x264)\" #@param [\"MP4 (x264)\", \"WEBM (VP9)\"]\n", + "#@markdown ---\n", + "#@markdown ## Notes โš ๏ธ\n", + "#@markdown - All previous files are removed on each new upload.\n", + "#@markdown - `Copy` statement means inheritance of original attribute of uploaded file.\n", + "\n", + "URL = URL.split(\"?\")[0].split(\"#\")[0]\n", + "Keep_Metadata = \"-map 0 -map_metadata 0:s:0 \" if not Keep_Metadata else \"\"\n", + "Output_Preview_Volume /= 100\n", + "Audio_Channels = (\"-ac \" + (\"1\" if Channels == \"Mono\" else \"2\")) if not Channels == \"Copy\" else \"\"\n", + "Audio_Bitrate = \"-b:a \" + str(Bitrate_kbps) + \"k\"\n", + "Samplerate = (\"-ar \" + Samplerate_Hz.replace(\" \", \"\")) if not Samplerate_Hz == \"Copy\" else \"\"\n", + "Video_Bitrate = (\"-b:v \" + str(int(Bitrate_mbps) * 1000) + \"k\") if not Bitrate_mbps == \"Copy\" else \"\"\n", + "Output_Format_and_Codec = [Param.lower() for Param in Output_Format_and_Codec.split(\" \")]\n", + "Output_Format = Output_Format_and_Codec[0]\n", + "Video_Codec = \"-c:v \" + (\"lib\" if Output_Format == \"mp4\" else \"\") + Output_Format_and_Codec[1][1:-1]\n", + "\n", + "#---#\n", + "\n", + "from re import sub\n", + "from time import time\n", + "from shutil import rmtree\n", + "from os import *; del open\n", + "from datetime import timedelta\n", + "from google.colab import files\n", + "from base64 import b64encode as b64\n", + "from requests import get, exceptions\n", + "from IPython.display import display, HTML\n", + "\n", + "#---#\n", + "\n", + "__author__\t\t\t\t= \"kubinka0505\"\n", + "__copyright__\t\t= __author__\n", + "__credits__\t\t\t\t= __author__\n", + "__version__\t\t\t\t= \"1.0\"\n", + "__date__\t\t\t\t\t= \"08.08.2021\"\n", + "__status__\t\t\t\t= \"Mature\"\n", + "__license__\t\t\t\t= \"GPL V3\"\n", + "\n", + "#---#\n", + "\n", + "chdir(\"/content/\")\n", + "CWD = getcwd()\n", + "chdir(\"..\")\n", + "\n", + "for Command in [rmtree, mkdir, chdir]:\n", + "\tCommand(CWD)\n", + "\n", + "#---#\n", + "\n", + "def File_Size(Size: bytes):\n", + "\tfor Unit in ['B', 'KB', 'MB', 'GB', 'TB', 'PB']:\n", + "\t\tif Size < 1024. or Unit == \"PB\": \n", + "\t\t\tbreak\n", + "\t\tSize /= 1024.\n", + "\treturn \"{0} {1}\".format(round(Size, 2), Unit)\n", + "\n", + "class Styles():\n", + "\t\"\"\"Formatted Prints.\"\"\"\n", + "\tLightRed\t= \"\\33[31m\"\n", + "\tBlue\t\t\t= \"\\33[34m\"\n", + "\tRed\t\t\t\t= \"\\33[91m\"\n", + "\tGreen\t\t\t= \"\\33[92m\"\n", + "\tYellow\t\t= \"\\33[93m\"\n", + "\tCyan\t\t\t= \"\\33[96m\"\n", + "\tBold\t\t\t= \"\\33[1m\"\n", + "\tUnderline\t= \"\\33[4m\"\n", + "\tReset\t\t\t= \"\\33[0m\"\n", + "\n", + "Allowed_Formats = [\"AVI\", \"MKV\", \"MOV\", \"MP4\", \"WEBM\"]\n", + "\n", + "#---#\n", + "\n", + "if not URL:\n", + "\ttry:\n", + "\t\tFile = [Key for Key in files.upload().keys()][0]\n", + "\t\tprint()\n", + "\texcept (TypeError, IndexError, KeyboardInterrupt):\n", + "\t\traise SystemExit(\"File upload aborted.\")\n", + "else:\n", + "\tprint(\"Uploading from {0}URL{1}...\".format(\n", + "\t\tStyles.Yellow, Styles.Reset\n", + "\t\t)\n", + "\t)\n", + "\t\n", + "\tFile = URL.split(\"/\")[-1]\n", + "\twith open(File, \"wb\") as File_:\n", + "\t\ttry:\n", + "\t\t\tRequest = get(URL)\n", + "\t\texcept exceptions.MissingSchema:\n", + "\t\t\t\traise SystemExit(\"Invalid URL.\")\n", + "\t\tif Request.status_code == 200:\n", + "\t\t\tFile_.write(Request.content)\n", + "\t\telse:\n", + "\t\t\traise SystemExit(\"Cannot import URL - {2}{0}{3} ({2}{1}{3})\".format(\n", + "\t\t\t\tRequest.status_code, Request.reason, Styles.Red, Styles.Reset)\n", + "\t\t\t)\n", + "try:\n", + "\tIn = path.abspath(File)\n", + "\tIn_NEW = sub(\"[^\\w\\-_\\. ]\", \"_\", In.split(\"/\")[-1]).replace(\" \", \"_\")\n", + "\trename(In, In_NEW)\n", + "\tIn = path.abspath(In_NEW)\n", + "\n", + "\tOut = In.split(\".\")[0] + \"_new.\" + Output_Format\n", + "\n", + "\tif not In.split(\".\")[-1].upper() in Allowed_Formats:\n", + "\t\tchmod(In, 0o777)\n", + "\t\tremove(In)\n", + "\t\tprint(\"{2}{0}{3}: Uploaded file is not a video!\\nAllowed formats: {1}\".format(\n", + "\t\t\tTypeError.__class__.__name__ + \"{1}, {0}\".join(Allowed_Formats).format(\n", + "\t\t\t\tStyles.Red, Styles.Reset\n", + "\t\t\t),\n", + "\t\t\tStyles.Red, Styles.Reset\n", + "\t\t\t)\n", + "\t\t)\n", + "\n", + "\t#---#\n", + "\n", + "\tenviron[\"IN\"] = In\n", + "\tenviron[\"OUT\"] = Out\n", + "\tenviron[\"AC\"] = Audio_Channels\n", + "\tenviron[\"BA\"] = Audio_Bitrate\n", + "\tenviron[\"AR\"] = Samplerate\n", + "\tenviron[\"BV\"] = Video_Bitrate\n", + "\tenviron[\"CV\"] = Video_Codec\n", + "\tenviron[\"MD\"] = Keep_Metadata\n", + "\n", + "\tprint(\"Re-encoding...\")\n", + "\t__STA_TIME = time()\n", + "\t!ffmpeg -i \"$IN\" $BV $CV $AC $AR $BA $MD \"$OUT\" -y -hide_banner -loglevel warning\n", + "\n", + "\t#---#\n", + "\n", + "\tSize_IN = path.getsize(In)\n", + "\tSize_OUT = path.getsize(Out)\n", + "\tPercentage = round(\n", + "\t\t\t100 - (\n", + "\t\t\t\tfloat(str(Size_OUT).split(\" \")[0]) / float(str(Size_IN).split(\" \")[0])\n", + "\t\t\t) * 100, 3\n", + "\t\t) if not Size_IN == Size_OUT else \"0.00\"\n", + "\tprint(\"\"\"\n", + "\tSize changed by:\\t{4}{2}%{8}\n", + "\tBase file size:\\t\\t{5}{0}{8}\n", + "\tNew file size:\\t\\t{6}{1}{8}\n", + "\n", + "\tWork time: {7}{3}{8}\\n\"\"\".replace(\"\\n\t\", \"\\n\").format(\n", + "\t\tFile_Size(Size_IN), File_Size(Size_OUT), Percentage,\n", + "\t\tstr(timedelta(seconds = -__STA_TIME + time()))[2:-3],\n", + "\t\tStyles.Cyan, Styles.LightRed, Styles.Green, Styles.Blue, Styles.Reset\n", + "\t\t)\n", + "\t)\n", + "\n", + "\tB64 = \"data:video/{0};base64,\".format(Output_Format) + b64(open(Out, \"rb\").read()).decode()\n", + "\n", + "\tdisplay(\n", + "\t\tHTML(\n", + "\t\t\t\"\"\"

\"\"\".format(\n", + "\t\t\t\tB64, Output_Format, Output_Preview_Volume)\n", + "\t\t\t)\n", + "\t\t)\n", + "\n", + "\tprint()\n", + "\tfiles.download(Out)\n", + "except Exception as Error:\n", + "\tprint(Error.__class__.__name__ + \": \" + Error)" + ], + "execution_count": null, + "outputs": [] + } + ] +} diff --git a/Notebooks/General/Text/Inkscape_HTML_Nodes_Delimiter/Notebook.ipynb b/Notebooks/General/Text/Inkscape_HTML_Nodes_Delimiter/Notebook.ipynb new file mode 100644 index 0000000..e4dad49 --- /dev/null +++ b/Notebooks/General/Text/Inkscape_HTML_Nodes_Delimiter/Notebook.ipynb @@ -0,0 +1,141 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "Inkscape HTML Nodes Delimiter", + "provenance": [], + "collapsed_sections": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "code", + "metadata": { + "id": "", + "cellView": "form" + }, + "source": [ + "#@title ## โฐ Open **`HTML`** webpage file\n", + "\n", + "from zipfile import *\n", + "from shutil import rmtree\n", + "from sys import *; del path\n", + "from os import *; del open\n", + "from google.colab import files\n", + "\n", + "CWD = \"/content/\"\n", + "rmtree(CWD)\n", + "mkdir(CWD)\n", + "chdir(CWD)\n", + "\n", + "#---#\n", + "\n", + "__author__ = \"kubinka0505\"\n", + "__credits__ = __author__\n", + "__version__ = \"1.0\"\n", + "__date__ = \"02.08.2021\"\n", + "\n", + "#---#\n", + "\n", + "def Folder_Size():\n", + "\t\"\"\"Calculates folder size recursively\"\"\"\n", + "\tSize = 0\n", + "\tfor Root, Dirs, Files in walk(\".\"):\n", + "\t\tfor File in Files:\n", + "\t\t\tPath = path.join(Root, File)\n", + "\t\t\tif not path.islink(Path):\n", + "\t\t\t\tSize += path.getsize(Path)\n", + "\treturn Size\n", + "\n", + "def File_Size(Bytes: float) -> str:\n", + "\t\"\"\"Returns human-readable file size\"\"\"\n", + "\tfor Unit in [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\"]:\n", + "\t\tif Bytes < 1024.: break\n", + "\t\tBytes /= 1024.\n", + "\treturn \"{0} {1}\".format(round(Bytes, 2), Unit)\n", + "\n", + "#---#\n", + "\n", + "try:\n", + "\ttry: files.upload()\n", + "\texcept KeyboardInterrupt: raise Exception\n", + "\n", + "\tFile = next(walk(\".\"))[2][0]\n", + "\n", + "\tif File: File = open(path.abspath(File), encoding = \"U8\")\n", + "\telse: raise Exception\n", + "except:\n", + "\traise IndexError(\"No file given!\")\n", + "\n", + "Folder_Name = File.name.split(\".\")[0] + \"_Nodes\"\n", + "\n", + "#---#\n", + "\n", + "Content\t= File.read()\n", + "Content\t= Content.replace(\"\\t\", \"\")\n", + "Begin\t= Content.find(\"ctx.moveTo(\")\n", + "Content\t= Content[Begin:].split(\"ctx.fill(\")[0].strip().split(\"\\n\")\n", + "\n", + "#---#\n", + "\n", + "Formats = (\"HTM\", \"HTML\")\n", + "if not File.name.upper().endswith(Formats):\n", + "\ttry:\n", + "\t\traise OSError(\"Only single simple webpages format files are supported ({0})\".format(\n", + "\t\t\t\", \".join(Formats).strip()\n", + "\t\t)\n", + "\t)\n", + "\texcept Exception as Error:\n", + "\t\traise SystemExit(\"{0}: {1}\".format(Error.__class__.__name__, Error))\n", + "\n", + "for Line in Content:\n", + "\tif \"ctx.bezier\" in Line:\n", + "\t\ttry:\n", + "\t\t\traise AttributeError(\"SVG file contains bezier curves\")\n", + "\t\texcept Exception as Error:\n", + "\t\t\texit(\"{0}: {1}\".format(Error.__class__.__name__, Error))\n", + "\n", + "try: mkdir(Folder_Name)\n", + "except FileExistsError: pass\n", + "chdir(Folder_Name)\n", + "\n", + "#---#\n", + "\n", + "X = \"\\n\".join([Line.split(\", \")[1].split(\");\")[0] for Line in Content])\n", + "X += \"{0}{1}{0}\".format(\"\\n\", X.split(\"\\n\")[0])\n", + "\n", + "Y = \"\\n\".join([Line.split(\"(\")[1].split(\",\")[0] for Line in Content])\n", + "Y += \"{0}{1}{0}\".format(\"\\n\", Y.split(\"\\n\")[0])\n", + "\n", + "open(\"X.txt\", \"w\", encoding = \"U8\").write(X)\n", + "open(\"Y.txt\", \"w\", encoding = \"U8\").write(Y)\n", + "\n", + "#---#\n", + "\n", + "print(\"\\nSuccessfully saved {0} nodes ({1})\".format(\n", + "\tlen([Line for Line in Content]),\n", + "\tFile_Size(Folder_Size())\n", + "\t)\n", + ")\n", + "\n", + "#---#\n", + "\n", + "print(\"Creating archive...\")\n", + "Archive_Name = path.abspath(Folder_Name + \".zip\")\n", + "Archive = ZipFile(Archive_Name, \"w\", ZIP_LZMA)\n", + "[Archive.write(File) for File in next(walk(\".\"))[2]]\n", + "files.download(Archive_Name)" + ], + "execution_count": null, + "outputs": [] + } + ] +} diff --git a/Notebooks/General/Text/Inkscape_HTML_Nodes_Delimiter/Standalone.pyw b/Notebooks/General/Text/Inkscape_HTML_Nodes_Delimiter/Standalone.pyw new file mode 100644 index 0000000..eda60b6 --- /dev/null +++ b/Notebooks/General/Text/Inkscape_HTML_Nodes_Delimiter/Standalone.pyw @@ -0,0 +1,133 @@ +"""Script delimiting Inkscape's HTML node points +Can be used as both CLI and GUI""" +from sys import *; del path +from os import *; del open +from subprocess import call +from tkinter import Tk, messagebox as msgbox, filedialog as fd +chdir(path.abspath(path.dirname(__file__))) + +#---# + +__author__ = "kubinka0505" +__credits__ = __author__ +__version__ = "1.0" +__date__ = "02.08.2021" + +#---# + +root = Tk() +root.withdraw() + +#---# + +def Folder_Size(): + """Calculates folder size recursively""" + Size = 0 + for Root, Dirs, Files in walk("."): + for File in Files: + Path = path.join(Root, File) + if not path.islink(Path): + Size += path.getsize(Path) + return Size + +def File_Size(Bytes: float) -> str: + """Returns human-readable file size""" + for Unit in ["B", "KB", "MB", "GB"]: + if Bytes < 1024.: break + Bytes /= 1024. + return "{0} {1}".format(round(Bytes, 2), Unit) + +#---# + +try: + try: + File = argv[1] + except IndexError: + File = fd.askopenfilename( + initialdir = getcwd(), + filetypes = [ + ("Hypertext Markup Language Files", "*.html *htm"), + ("All Files", "*.*") + ] + ) + if File: + File = open(path.abspath(File), encoding = "U8") + else: + raise IndexError +except IndexError: + exit("No file given!") + +Folder_Name = File.name.split(".")[0] + "_Nodes" + +#---# + +Content = File.read() +Content = Content.replace("\t", "") +Begin = Content.find("ctx.moveTo(") +Content = Content[Begin:].split("ctx.fill(")[0].strip().split("\n") + +#---# + +Formats = ("HTM", "HTML") +if not File.name.upper().endswith(Formats): + try: + raise OSError("Only single simple webpages format files are supported ({0})".format( + ", ".join(Formats).strip() + ) + ) + except Exception as Error: + msgbox.showerror( + title = Error.__class__.__name__, + message = Error + ) + exit("{0}: {1}".format(Error.__class__.__name__, Error)) + +for Line in Content: + if "ctx.bezier" in Line: + try: + raise AttributeError("SVG file contains bezier curves") + except Exception as Error: + msgbox.showerror( + title = Error.__class__.__name__, + message = Error + ) + exit("{0}: {1}".format(Error.__class__.__name__, Error)) + +try: + mkdir(Folder_Name) +except FileExistsError: + pass +chdir(Folder_Name) + +#---# + +X = "\n".join([Line.split(", ")[1].split(");")[0] for Line in Content]) +X += "{0}{1}{0}".format("\n", X.split("\n")[0]) + +Y = "\n".join([Line.split("(")[1].split(",")[0] for Line in Content]) +Y += "{0}{1}{0}".format("\n", Y.split("\n")[0]) + +open("X.txt", "w", encoding = "U8").write(X) +open("Y.txt", "w", encoding = "U8").write(Y) + +#---# + +Message = "Successfully {0} nodes ({1})\n\nDo You want to open containing folder?".format( + len([Line for Line in Content]), + File_Size(Folder_Size()) + ) + +print(Message.split("\n")[0] + "\a") +Message = msgbox.showinfo( + title = "Success", + message = Message +) + +#---# + +Command = "nautilus" +if platform.startswith("win"): + Command = "start /max" + +if Message == "ok": + call(Command + " .", shell = True) diff --git a/ReadMe.md b/ReadMe.md new file mode 100644 index 0000000..46219f6 --- /dev/null +++ b/ReadMe.md @@ -0,0 +1,29 @@ +

+ Colab Notebooks ๐Ÿ“ +

+ +

+ ใ€€ +

+ +--- + +## General + +| Name | Description | URL | +|:---:|:---:|:---:| +| `Hybrid Image / Video Cropper` (Vertical) | Crops the image into two horizontal pieces and maps a different sound file to each, resulting with two videos. | [](https://colab.research.google.com/github/kubinka0505/colab-notebooks/blob/master/Notebooks/General/Media/Visual/Mixed/Hybrid_Image_Video_Cropper/Vertical.ipynb) | +| `Inkscape HTML Nodes Delimiter` | Extracts simple coordinates of Inkscape's HTML files and saves it as two files.
Its main purpose is easing work with [vectorscope arts creations](https://www.youtube.com/watch?v=aLJeInPJ9oo), but perhaps not only. | [](https://colab.research.google.com/github/kubinka0505/colab-notebooks/blob/master/Notebooks/General/Text/Inkscape_HTML_Nodes_Delimiter/Notebook.ipynb)
[](https://colab.research.google.com/github/kubinka0505/colab-notebooks/blob/master/Notebooks/General/Text/Inkscape_HTML_Nodes_Delimiter/Standalone.pyw) | +| `Music Calculators` | Calculators for various music functions related to pitch and time.| [](https://colab.research.google.com/github/kubinka0505/colab-notebooks/blob/master/Notebooks/General/Math/Music/Calculators.ipynb) | +| `Simple Video Re-Encoder` | Simple *yet* detailed video re-encoder with advanced configuration. | [](https://colab.research.google.com/github/kubinka0505/colab-notebooks/blob/master/Notebooks/General/Media/Visual/Video/Simple_Video_Re-Encoder.ipynb) | +| `Unisonizer` | Pans pairs of files on max opposite values.
**`WAV` files recommended!** | [](https://colab.research.google.com/github/kubinka0505/colab-notebooks/blob/master/Notebooks/General/Media/Audio/Unisonizer.ipynb) + +## AI +| Name | Description | URL | +|:---:|:---:|:---:| +| `Stable Diffusion WebUI` | Clear and user-friendly [`Stable-Diffusion-WebUI`](https://github.com/AUTOMATIC1111/stable-diffusion-webui) wrapper with useful websites, models selector, custom configuration and more. | [](https://colab.research.google.com/github/kubinka0505/colab-notebooks/blob/master/Notebooks/AI/Visual/Generate/Stable-Diffusion-WebUI/Stable-Diffusion_WebUI.ipynb) | +| `Audio Separation` - `MDX23C` | User-friendly wrapper for the [jarredou](https://github.com/jarredou)'s [fork](https://github.com/jarredou/MVSEP-MDX23-Colab_v2) of [ZFTurbo](https://github.com/ZFTurbo)'s [MDX23C](https://github.com/ZFTurbo/MVSEP-MDX23-music-separation-model) audio separation model. | [](https://colab.research.google.com/github/kubinka0505/colab-notebooks/blob/master/Notebooks/AI/Audio/Separate/MDX23C.ipynb) | +| `Audio Separation` - `Drumsep` | Customized [Drumsep](https://github.com/inagoy/drumsep) notebook by [inagoy](https://github.com/inagoy). | [](https://colab.research.google.com/github/kubinka0505/colab-notebooks/blob/master/Notebooks/AI/Audio/Separate/Drumsep.ipynb) | +| `Audio Generation` - `AudioCraft` | User-friendly wrapper for the Meta's [`AudioCraft`](https://github.com/facebookresearch/audiocraft) audio generation models. | [](https://colab.research.google.com/github/kubinka0505/colab-notebooks/blob/master/Notebooks/AI/Audio/Generate/AudioCraft.ipynb) | +| `Audio Upscale` - `HiFi GAN BWE` | Customized [`HiFi GAN BWE`](https://github.com/brentspell/hifi-gan-bwe) notebook by [brentspell](https://github.com/brentspell). | [](https://colab.research.google.com/github/kubinka0505/colab-notebooks/blob/master/Notebooks/AI/Audio/Upscale/HiFi_GAN_BWE.ipynb) | +| `Speech Cloning` - `Coqui XTTS` | Compact implementation of the [camenduru](https://github.com/camenduru)'s [`coqui-XTTS-colab.`](https://github.com/camenduru/coqui-XTTS-colab) Gradio app. | [](https://colab.research.google.com/github/kubinka0505/colab-notebooks/blob/master/Notebooks/AI/Audio/_Speech/Clone/Coqui_XTTS.ipynb) | \ No newline at end of file