Add genereate prview of podcast. Add preview creator dialog. Add video dialog. Add icons. Fixes and more fixes. Refactoring. Update ui.

This commit is contained in:
Jarosław Wieczorek 2021-01-23 16:28:23 +01:00
parent d2d782f4fe
commit a998105d03
33 changed files with 95787 additions and 84449 deletions

View File

@ -12,6 +12,8 @@ ffmpeg = "*"
pip = "*"
ffmpeg-python = "*"
pydub = "*"
sound = "*"
pysignal = "*"
[dev-packages]

116
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "b9153460b4a961fc9063b87ddac6e4c7bf8748bfaefcefc26f2401e340ae7b1e"
"sha256": "97d779996cd5a22333bb688b9bf3ef013963d64876f4def420e6651d98165e23"
},
"pipfile-spec": 6,
"requires": {
@ -16,6 +16,47 @@
]
},
"default": {
"cffi": {
"hashes": [
"sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e",
"sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d",
"sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a",
"sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec",
"sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362",
"sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668",
"sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c",
"sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b",
"sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06",
"sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698",
"sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2",
"sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c",
"sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7",
"sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009",
"sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03",
"sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b",
"sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909",
"sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53",
"sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35",
"sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26",
"sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b",
"sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01",
"sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb",
"sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293",
"sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd",
"sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d",
"sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3",
"sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d",
"sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e",
"sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca",
"sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d",
"sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775",
"sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375",
"sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b",
"sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b",
"sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f"
],
"version": "==1.14.4"
},
"click": {
"hashes": [
"sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a",
@ -24,6 +65,14 @@
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==7.1.2"
},
"darr": {
"hashes": [
"sha256:2fdcfbfb23d9b78cdbdc8eacaf53b2fbc80f4aa398c96fa279c4b2676fe25e6d",
"sha256:3a57cdf75f0deba2ae03820f4f01747925bf8dac100a3fd9c3c90c56dfad2261"
],
"markers": "python_version >= '3.6'",
"version": "==0.2.2"
},
"ffmpeg": {
"hashes": [
"sha256:6931692c890ff21d39938433c2189747815dca0c60ddc7f9bb97f199dba0b5b9"
@ -116,6 +165,46 @@
],
"version": "==0.6.1"
},
"numpy": {
"hashes": [
"sha256:012426a41bc9ab63bb158635aecccc7610e3eff5d31d1eb43bc099debc979d94",
"sha256:06fab248a088e439402141ea04f0fffb203723148f6ee791e9c75b3e9e82f080",
"sha256:0eef32ca3132a48e43f6a0f5a82cb508f22ce5a3d6f67a8329c81c8e226d3f6e",
"sha256:1ded4fce9cfaaf24e7a0ab51b7a87be9038ea1ace7f34b841fe3b6894c721d1c",
"sha256:2e55195bc1c6b705bfd8ad6f288b38b11b1af32f3c8289d6c50d47f950c12e76",
"sha256:2ea52bd92ab9f768cc64a4c3ef8f4b2580a17af0a5436f6126b08efbd1838371",
"sha256:36674959eed6957e61f11c912f71e78857a8d0604171dfd9ce9ad5cbf41c511c",
"sha256:384ec0463d1c2671170901994aeb6dce126de0a95ccc3976c43b0038a37329c2",
"sha256:39b70c19ec771805081578cc936bbe95336798b7edf4732ed102e7a43ec5c07a",
"sha256:400580cbd3cff6ffa6293df2278c75aef2d58d8d93d3c5614cd67981dae68ceb",
"sha256:43d4c81d5ffdff6bae58d66a3cd7f54a7acd9a0e7b18d97abb255defc09e3140",
"sha256:50a4a0ad0111cc1b71fa32dedd05fa239f7fb5a43a40663269bb5dc7877cfd28",
"sha256:603aa0706be710eea8884af807b1b3bc9fb2e49b9f4da439e76000f3b3c6ff0f",
"sha256:6149a185cece5ee78d1d196938b2a8f9d09f5a5ebfbba66969302a778d5ddd1d",
"sha256:759e4095edc3c1b3ac031f34d9459fa781777a93ccc633a472a5468587a190ff",
"sha256:7fb43004bce0ca31d8f13a6eb5e943fa73371381e53f7074ed21a4cb786c32f8",
"sha256:811daee36a58dc79cf3d8bdd4a490e4277d0e4b7d103a001a4e73ddb48e7e6aa",
"sha256:8b5e972b43c8fc27d56550b4120fe6257fdc15f9301914380b27f74856299fea",
"sha256:99abf4f353c3d1a0c7a5f27699482c987cf663b1eac20db59b8c7b061eabd7fc",
"sha256:a0d53e51a6cb6f0d9082decb7a4cb6dfb33055308c4c44f53103c073f649af73",
"sha256:a12ff4c8ddfee61f90a1633a4c4afd3f7bcb32b11c52026c92a12e1325922d0d",
"sha256:a4646724fba402aa7504cd48b4b50e783296b5e10a524c7a6da62e4a8ac9698d",
"sha256:a76f502430dd98d7546e1ea2250a7360c065a5fdea52b2dffe8ae7180909b6f4",
"sha256:a9d17f2be3b427fbb2bce61e596cf555d6f8a56c222bd2ca148baeeb5e5c783c",
"sha256:ab83f24d5c52d60dbc8cd0528759532736b56db58adaa7b5f1f76ad551416a1e",
"sha256:aeb9ed923be74e659984e321f609b9ba54a48354bfd168d21a2b072ed1e833ea",
"sha256:c843b3f50d1ab7361ca4f0b3639bf691569493a56808a0b0c54a051d260b7dbd",
"sha256:cae865b1cae1ec2663d8ea56ef6ff185bad091a5e33ebbadd98de2cfa3fa668f",
"sha256:cc6bd4fd593cb261332568485e20a0712883cf631f6f5e8e86a52caa8b2b50ff",
"sha256:cf2402002d3d9f91c8b01e66fbb436a4ed01c6498fffed0e4c7566da1d40ee1e",
"sha256:d051ec1c64b85ecc69531e1137bb9751c6830772ee5c1c426dbcfe98ef5788d7",
"sha256:d6631f2e867676b13026e2846180e2c13c1e11289d67da08d71cacb2cd93d4aa",
"sha256:dbd18bcf4889b720ba13a27ec2f2aac1981bd41203b3a3b27ba7a33f88ae4827",
"sha256:df609c82f18c5b9f6cb97271f03315ff0dbe481a2a02e56aeb1b1a985ce38e60"
],
"markers": "python_version >= '3.6'",
"version": "==1.19.5"
},
"packaging": {
"hashes": [
"sha256:24e0da08660a87484d1602c30bb4902d74816b6985b93de36926f5bc95741858",
@ -140,6 +229,14 @@
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.6.0"
},
"pycparser": {
"hashes": [
"sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
"sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.20"
},
"pydocstyle": {
"hashes": [
"sha256:19b86fa8617ed916776a11cd8bc0197e5b9856d5433b777f51a3defe13075325",
@ -225,6 +322,23 @@
],
"version": "==2.0.0"
},
"sound": {
"hashes": [
"sha256:bc5baa8cf11152bdeda1197b6390608d874d8c917f7542b7c06485a952340ee3"
],
"index": "pypi",
"version": "==0.1.0"
},
"soundfile": {
"hashes": [
"sha256:2d17e0a6fc2af0d6c1d868bafa5ec80aae6e186a97fec8db07ad6af29842fbc7",
"sha256:4555438c2c4f02b39fea2ed40f6ddeda88a80cd1ee9dd129be4d5f5134698cc2",
"sha256:490cff42650733d1832728b937fe99fa1802896f5ef4d61bcf78cf7ebecb107b",
"sha256:5e342ee293b896d31da67617fe65d0bdca217af193991b0cb6052353b1e0e506",
"sha256:b361d4ac1519a2e516cabafa6bf7e93492f999f35d7d25350cd87fdc3e5cb27e"
],
"version": "==0.10.3.post1"
},
"toml": {
"hashes": [
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",

View File

@ -1,13 +1,7 @@
#!/bin/bash
tmp_dir=$1
number_of_files=$2
audio=$3
audio2=$4
tmp_video_dir=$1
audio=$2
output_dir=$3
output_file=$4
if [ $number_of_files != "2" ]
then
ffmpeg -i $tmp_dir/video/video.mp4 -i $audio -ac 1 -tune stillimage ./out/video-and-audio.mp4 -y
else
ffmpeg -i $tmp_dir/video/video.mp4 -i $audio -ac 1 -tune stillimage $tmp_dir/video/video_sound_one.mp4 -y
ffmpeg -i $tmp_dir/video/video_sound_one.mp4 -i $audio2 -ac 1 -tune stillimage ./out/video-and-audio.mp4 -y
fi
ffmpeg -y -i $tmp_video_dir/video.mp4 -i $audio -ac 1 -tune stillimage "$output_dir$output_file"

View File

@ -1,5 +1,4 @@
#!/bin/bash
tmp_dir=$1
tmp_video_dir=$2
tmp_video_dir=$1
ffmpeg -y -f concat -safe 0 -i demuxer.txt -r 30 -tune stillimage -vsync vfr -pix_fmt yuv420p $tmp_video_dir/video.mp4

View File

@ -6,9 +6,9 @@ file_2=$4
if [ $number_of_files != "2" ]
then
ffmpeg -i $file_1 -map_channel 0.0.0 $tmp_dir/left.wav -map_channel 0.0.1 $tmp_dir/right.wav
ffmpeg -i $file_1 -map_channel 0.0.0 $tmp_dir/left.wav -map_channel 0.0.1 $tmp_dir/right.wav -y
else
ffmpeg -i $file_1 -map_channel 0.0.0 $tmp_dir/left.wav
ffmpeg -i $file_2 -map_channel 0.0.1 $tmp_dir/right.wav
ffmpeg -i $file_1 -map_channel 0.0.0 $tmp_dir/left.wav -y
ffmpeg -i $file_2 -map_channel 0.0.1 $tmp_dir/right.wav -y
fi

View File

@ -1,10 +1,11 @@
import math
from find_loudness import process_find_loudness
graph_density = 8000
graph_density = 44100
threshold_at_point = 1
inertia_s = 0.3
inertia_samples = inertia_s * graph_density
out_demuxer = 'demuxer.txt'
def set_up_threshold(new_value: int):
@ -64,8 +65,7 @@ def mode_to_string(mode):
def run(tmp_dir):
"""Main method to run generating demuxer.txt"""
global inertia_samples
out_demuxer = 'demuxer.txt'
global inertia_samples, out_demuxer
with open(out_demuxer, 'w') as demuxer:
# Execute process_find_loudness for left and right side
@ -84,9 +84,9 @@ def run(tmp_dir):
print("RIGHT:", right_loudness)
merged = [*left_loudness, *right_loudness]
print(merged)
# print(merged)
sorted_list = sorted(merged, key=lambda x: x['position_start'])
print(sorted_list)
# print(sorted_list)
demuxer.write(F"file {tmp_dir}/pics/none.png\n")
last_point = 0

View File

@ -1,4 +1,8 @@
<RCC>
<qresource prefix="font">
<file>src/gui/fonts/Raleway/Raleway-Medium.ttf</file>
</qresource>
<qresource prefix="left">
<file>src/gui/images/left.png</file>
</qresource>
@ -33,6 +37,15 @@
<file>src/gui/images/icons/import.png</file>
</qresource>
<qresource prefix="video-icons">
<file>src/gui/images/icons/control.png</file>
<file>src/gui/images/icons/control-pause.png</file>
<file>src/gui/images/icons/control-skip.png</file>
<file>src/gui/images/icons/control-skip-180.png</file>
<file>src/gui/images/icons/control-stop-square.png</file>
<file>src/gui/images/icons/speaker-volume.png</file>
</qresource>
<qresource prefix="favicon">
<file>src/gui/images/icons/32x32.png</file>
<file>src/gui/images/icons/45x45.png</file>

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,93 @@
Copyright 2010 The Raleway Project Authors (impallari@gmail.com), with Reserved Font Name "Raleway".
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View File

@ -0,0 +1,81 @@
Raleway Variable Font
=====================
This download contains Raleway as both variable fonts and static fonts.
Raleway is a variable font with this axis:
wght
This means all the styles are contained in these files:
Raleway-VariableFont_wght.ttf
Raleway-Italic-VariableFont_wght.ttf
If your app fully supports variable fonts, you can now pick intermediate styles
that arent available as static fonts. Not all apps support variable fonts, and
in those cases you can use the static font files for Raleway:
static/Raleway-Thin.ttf
static/Raleway-ExtraLight.ttf
static/Raleway-Light.ttf
static/Raleway-Regular.ttf
static/Raleway-Medium.ttf
static/Raleway-SemiBold.ttf
static/Raleway-Bold.ttf
static/Raleway-ExtraBold.ttf
static/Raleway-Black.ttf
static/Raleway-ThinItalic.ttf
static/Raleway-ExtraLightItalic.ttf
static/Raleway-LightItalic.ttf
static/Raleway-Italic.ttf
static/Raleway-MediumItalic.ttf
static/Raleway-SemiBoldItalic.ttf
static/Raleway-BoldItalic.ttf
static/Raleway-ExtraBoldItalic.ttf
static/Raleway-BlackItalic.ttf
Get started
-----------
1. Install the font files you want to use
2. Use your app's font picker to view the font family and all the
available styles
Learn more about variable fonts
-------------------------------
https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts
https://variablefonts.typenetwork.com
https://medium.com/variable-fonts
In desktop apps
https://theblog.adobe.com/can-variable-fonts-illustrator-cc
https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts
Online
https://developers.google.com/fonts/docs/getting_started
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide
https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts
Installing fonts
MacOS: https://support.apple.com/en-us/HT201749
Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux
Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows
Android Apps
https://developers.google.com/fonts/docs/android
https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts
License
-------
Please read the full license text (OFL.txt) to understand the permissions,
restrictions and requirements for usage, redistribution, and modification.
You can use them freely in your products & projects - print or digital,
commercial or otherwise. However, you can't sell the fonts on their own.
This isn't legal advice, please consider consulting a lawyer and see the full
license for all details.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

BIN
src/gui/images/icons/control.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

View File

@ -10,6 +10,12 @@
<height>807</height>
</rect>
</property>
<property name="maximumSize">
<size>
<width>800</width>
<height>16777215</height>
</size>
</property>
<property name="windowTitle">
<string>MagicPodcast</string>
</property>
@ -185,8 +191,8 @@
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>150</height>
<width>400</width>
<height>16777215</height>
</size>
</property>
<property name="frameShape">
@ -222,7 +228,7 @@
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<width>400</width>
<height>35</height>
</size>
</property>
@ -271,8 +277,8 @@
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>150</height>
<width>400</width>
<height>16777215</height>
</size>
</property>
<property name="frameShape">
@ -308,7 +314,7 @@
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<width>400</width>
<height>35</height>
</size>
</property>
@ -361,8 +367,8 @@
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>150</height>
<width>400</width>
<height>16777215</height>
</size>
</property>
<property name="frameShape">
@ -401,7 +407,7 @@
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<width>400</width>
<height>35</height>
</size>
</property>
@ -450,8 +456,8 @@
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>150</height>
<width>400</width>
<height>16777215</height>
</size>
</property>
<property name="frameShape">
@ -487,7 +493,7 @@
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<width>400</width>
<height>35</height>
</size>
</property>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PreviewDialog</class>
<widget class="QDialog" name="PreviewDialog">
<class>PreviewCreatorDialog</class>
<widget class="QDialog" name="PreviewCreatorDialog">
<property name="windowModality">
<enum>Qt::NonModal</enum>
</property>
@ -9,8 +9,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>779</width>
<height>356</height>
<width>584</width>
<height>422</height>
</rect>
</property>
<property name="windowTitle">
@ -22,17 +22,40 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QVBoxLayout" name="v_layout_1"/>
<layout class="QVBoxLayout" name="playlist_v_layout">
<item>
<widget class="QListView" name="playlistView">
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="showDropIndicator" stdset="0">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DropOnly</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::CopyAction</enum>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="uniformItemSizes">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="h_layout_range_values">
<layout class="QHBoxLayout" name="range_values_h_layout">
<item>
<widget class="QLabel" name="left_label">
<property name="text">
@ -41,7 +64,7 @@
</widget>
</item>
<item>
<widget class="QLineEdit" name="left_range">
<widget class="QLineEdit" name="left_range_line_edit">
<property name="inputMethodHints">
<set>Qt::ImhPreferNumbers|Qt::ImhTime</set>
</property>
@ -55,7 +78,7 @@
</widget>
</item>
<item>
<widget class="QLineEdit" name="right_range">
<widget class="QLineEdit" name="right_range_line_edit">
<property name="inputMethodHints">
<set>Qt::ImhPreferNumbers|Qt::ImhTime</set>
</property>
@ -71,29 +94,18 @@
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<widget class="QLabel" name="log_label">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="play_button">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="stop_button">
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
</layout>
<widget class="QProgressBar" name="progress_bar">
<property name="value">
<number>0</number>
</property>
</widget>
</item>
</layout>
</widget>

View File

@ -0,0 +1,164 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>VideoPlayerDialog</class>
<widget class="QDialog" name="VideoPlayerDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>640</width>
<height>480</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QVBoxLayout" name="video_v_layout"/>
</item>
<item>
<layout class="QHBoxLayout" name="time_h_layout">
<item>
<widget class="QLabel" name="current_time_label">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>0:00</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="time_slider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="total_time_label">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>0:00</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="buttons_h_layout">
<item>
<widget class="QPushButton" name="previous_button">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../resources.qrc">
<normaloff>:/video-icons/src/gui/images/icons/control-skip-180.png</normaloff>:/video-icons/src/gui/images/icons/control-skip-180.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="play_button">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../resources.qrc">
<normaloff>:/video-icons/src/gui/images/icons/control.png</normaloff>:/video-icons/src/gui/images/icons/control.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pause_button">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../resources.qrc">
<normaloff>:/video-icons/src/gui/images/icons/control-pause.png</normaloff>:/video-icons/src/gui/images/icons/control-pause.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="stop_button">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../resources.qrc">
<normaloff>:/video-icons/src/gui/images/icons/control-stop-square.png</normaloff>:/video-icons/src/gui/images/icons/control-stop-square.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="next_button">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../resources.qrc">
<normaloff>:/video-icons/src/gui/images/icons/control-skip.png</normaloff>:/video-icons/src/gui/images/icons/control-skip.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="h_spacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="volume_label">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../resources.qrc">:/video-icons/src/gui/images/icons/speaker-volume.png</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="volume_slider">
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="../../../resources.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -2,21 +2,24 @@ import os
import shutil
import subprocess
import tempfile
from datetime import datetime
from pathlib import Path
from pydub.utils import mediainfo
from pydub.audio_segment import AudioSegment
# import resources_rc
from PyQt5.QtCore import Qt
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QMainWindow, QLabel, QFileDialog, QDialog, QDialogButtonBox, QVBoxLayout, QApplication
from PyQt5.QtWidgets import QMainWindow, QLabel, QFileDialog, QDialog, QDialogButtonBox,\
QVBoxLayout, QApplication
from src.python.classes.settings_dialog import SettingsDialog
from src.python.ui.mainwindow_ui import Ui_MainWindow
from src.python.classes.translate import Translator
from src.python.classes.preview_dialog import PreviewDialog
from src.python.classes.preview_creator_dialog import PreviewCreatorDialog
import generate_demuxer
@ -25,6 +28,7 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
"""
MainWindow Class
"""
podcast_preview_crated_signal = pyqtSignal(str)
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent=parent)
@ -34,10 +38,11 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
self.lang = 'pl'
self.translator.load_lang(self.lang)
self.setupUi(self)
self.setup_logic()
self.setup_detail()
self.output_dir = './out/'
self.retranslateUi(self.window())
self.aresample = "8000"
self.aresample = "44100"
self.image_extensions = ['.jpg', '.png']
self.audio_extensions = ['.mp3', '.wav']
@ -48,15 +53,18 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
title='Process generowania podcastu',
msg='Sprawdzanie poprawności danych'
)
self.preview_creator_dialog = PreviewCreatorDialog(self)
self.tmp_working_directory = tempfile.TemporaryDirectory()
self.log_label.hide()
self.setup_detail()
self.setup_logic()
self.test_data(option=2)
def setup_logic(self):
"""Connect ui elements with methods."""
self.action_settings.triggered.connect(self.open_setting_dialog)
self.button_generate.clicked.connect(self.generate_video_podcast)
self.button_preview.clicked.connect(self.preview_video_podcast)
self.button_preview.clicked.connect(self.show_preview_creator_dialog)
self.button_audio_1.clicked.connect(lambda: self.open_audio_import(audio_number=1))
self.button_audio_2.clicked.connect(lambda: self.open_audio_import(audio_number=2))
self.button_select_avatar_1.clicked.connect(lambda: self.open_image_import(image_number=1))
@ -67,6 +75,8 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
self.connected_channels_status = self.check_box_connected_channels.checkState()
self.check_box_connected_channels.stateChanged.connect(self.channels_connected)
self.threshold_slider.valueChanged.connect(self.update_lcd_threshold)
self.preview_creator_dialog.preview_generate_signal.connect(self.generate_video_podcast)
self.podcast_preview_crated_signal.connect(self.preview_creator_dialog.add_element_to_list)
def on_progress_change(self, value):
"""Update progress bar value"""
@ -247,50 +257,30 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
self.line_edit_audio_2.setDisabled(False)
self.line_edit_audio_1.setPlaceholderText("Plik audio 1 rozmówcy")
def preview_video_podcast(self):
"""Preview Video Podcast"""
def show_preview_creator_dialog(self):
"""Preview Podcast Creator"""
total_time = 0
try:
threshold_value, connected_channels, audio_files, image_files, total_time = self.collect_data_files()
if not self.check_box_connected_channels.isChecked():
audio_files = [self.line_edit_audio_1.text(), self.line_edit_audio_2.text()]
print(f"End time: {total_time}")
if not all(self.check_file(x, self.audio_extensions) for x in audio_files):
return -1
self.preview_creator_dialog.total_time_changed(total_time=int(total_time))
self.preview_creator_dialog.show()
self.line_edit_audio_1.setProperty(
'duration', mediainfo(self.line_edit_audio_1.text())['duration'])
except Exception as err:
print(err)
return -1
self.line_edit_audio_2.setProperty(
'duration', mediainfo(self.line_edit_audio_2.text())['duration'])
def collect_data_files(self):
""" Collect data from ui."""
demuxer_file = Path('./demuxer.txt')
if demuxer_file.is_file():
shutil.rmtree(demuxer_file, ignore_errors=True)
if not Path(self.tmp_working_directory.name).is_dir():
self.tmp_working_directory = tempfile.TemporaryDirectory()
audio_1 = float(self.line_edit_audio_1.property('duration'))
print(audio_1)
audio_2 = float(self.line_edit_audio_2.property('duration'))
print(f"[*] File duration audio_1: {audio_1}")
print(f"[*] File duration audio_2: {audio_2}")
end_time = audio_1 if audio_1 >= audio_2 else audio_2
preview_dialog = PreviewDialog(parent=self, start_time=0, end_time=end_time)
else:
audio_files = [self.line_edit_audio_1.text()]
if not all(self.check_file(x, self.audio_extensions) for x in audio_files):
return -1
self.line_edit_audio_1.setProperty(
'duration', mediainfo(self.line_edit_audio_1.text())['duration'])
end_time = float(self.line_edit_audio_1.property('duration'))
print(f"[*] File duration audio_2: {end_time}")
preview_dialog = PreviewDialog(parent=self, start_time=0, end_time=end_time)
preview_dialog.exec_()
def generate_video_podcast(self, start=None, end=None):
"""Generate podcast based on values from UI."""
self.progress_bar.setValue(0)
threshold_value = int(self.threshold_lcd.value())
generate_demuxer.set_up_threshold(threshold_value)
connected_channels = self.check_box_connected_channels.isChecked()
print(F"Channels connected: {connected_channels}")
# Setup images
@ -304,7 +294,7 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
for image_path in image_files.values():
if not self.check_file(image_path, self.image_extensions):
self.create_custom_dialog(title='Błąd!', msg="Tworzenie podcastu zostało przerwane.")
return -1
raise FileNotFoundError
audio_files = []
if not connected_channels:
@ -315,121 +305,192 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
audio_files.append({'file': self.line_edit_audio_1.text()})
for audio_path in audio_files:
print(audio_path)
if not Path(audio_path['file']).is_file():
if not self.check_file(audio_path['file'], self.audio_extensions):
self.create_custom_dialog(title='Błąd!', msg="Tworzenie podcastu zostało przerwane.")
return -1
raise FileNotFoundError
# Split name and extension of the file
for dictionary in audio_files:
dictionary['ext'] = dictionary['file'].rsplit('.')[-1]
self.progress_bar.setValue(10)
with tempfile.TemporaryDirectory() as tmp_dir_name:
tmp_dir_name = './tmp_dir' + tmp_dir_name
#os.mkdir('./tmp_dir/tmp')
os.mkdir(tmp_dir_name)
self.log_label.show()
self.log_label.setText(f'[*] Create temporary directory: {tmp_dir_name}')
tmp_out_dir = tmp_dir_name + "/out"
pics_dir = tmp_dir_name + "/pics"
audio_dir = tmp_dir_name + "/audio"
video_dir = tmp_dir_name + "/video"
self.preview_creator_dialog.log_label.show()
self.log_label.setText(f'[*] Create temporary directory: {self.tmp_working_directory}')
self.progress_bar.setValue(15)
self.log_label.setText(f"[!] Create tmp out dir: {tmp_out_dir}")
os.mkdir(tmp_out_dir)
self.tmp_out_dir = self.tmp_working_directory.name + "/out"
self.pics_dir = self.tmp_working_directory.name + "/pics"
self.audio_dir = self.tmp_working_directory.name + "/audio"
self.video_dir = self.tmp_working_directory.name + "/video"
self.log_label.setText(f"[*] Create pics dir: {pics_dir}")
os.mkdir(pics_dir)
# self.progress_bar.setValue(15)
self.log_label.setText(f"[!] Create tmp out dir: {self.tmp_out_dir}")
self.log_label.setText(f"[*] Create audio dir: {audio_dir}")
os.mkdir(audio_dir)
if not Path(self.tmp_out_dir).is_dir():
os.mkdir(self.tmp_out_dir)
self.log_label.setText(f"[*] Create video dir: {video_dir}")
os.mkdir(video_dir)
self.log_label.setText(f"[*] Create pics dir: {self.pics_dir}")
if not Path(self.pics_dir).is_dir():
os.mkdir(self.pics_dir)
self.log_label.setText(f"[*] Copy images to {pics_dir}")
shutil.copy(image_files['both'], pics_dir + "/both.png")
shutil.copy(image_files['none'], pics_dir + "/none.png")
shutil.copy(image_files['left'], pics_dir + "/left.png")
shutil.copy(image_files['right'], pics_dir + "/right.png")
self.log_label.setText(f"[*] Create audio dir: {self.audio_dir}")
if not Path(self.audio_dir).is_dir():
os.mkdir(self.audio_dir)
self.progress_bar.setValue(20)
self.log_label.setText(f"[*] Copy audio to {audio_dir}")
if not connected_channels:
audio_files[0]['tmp'] = audio_dir + "/left_channel" + "." + audio_files[0]['ext']
audio_files[1]['tmp'] = audio_dir + "/right_channel" + "." + audio_files[1]['ext']
self.log_label.setText(f"[*] Create video dir: {self.video_dir}")
if not Path(self.video_dir).is_dir():
os.mkdir(self.video_dir)
audio_files[0]['duration'] = mediainfo(audio_files[0]['file'])['duration']
audio_files[1]['duration'] = mediainfo(audio_files[1]['file'])['duration']
self.log_label.setText(f"[*] Copy images to {self.pics_dir}")
shutil.copy(image_files['both'], self.pics_dir + "/both.png")
shutil.copy(image_files['none'], self.pics_dir + "/none.png")
shutil.copy(image_files['left'], self.pics_dir + "/left.png")
shutil.copy(image_files['right'], self.pics_dir + "/right.png")
shutil.copy(audio_files[0]['file'], audio_files[0]['tmp'])
shutil.copy(audio_files[1]['file'], audio_files[1]['tmp'])
# self.progress_bar.setValue(20)
self.log_label.setText(f"[*] Copy audio to {self.audio_dir}")
else:
audio_files[0]['tmp'] = audio_dir + "/both_channel" + "." + audio_files[0]['ext']
audio_files[0]['duration'] = mediainfo(audio_files[0]['file'])['duration']
shutil.copy(audio_files[0]['file'], audio_files[0]['tmp'])
total_time = 0
if not connected_channels:
audio_files[0]['tmp'] = self.audio_dir + "/left_channel" + "." + audio_files[0]['ext']
audio_files[1]['tmp'] = self.audio_dir + "/right_channel" + "." + audio_files[1]['ext']
print(f'[*] Images in {pics_dir}: {os.listdir(pics_dir)}')
print(f'[*] Audo files in {audio_dir}: {os.listdir(audio_dir)}')
for num, audio in enumerate(audio_files):
audio['duration'] = float(mediainfo(audio['file'])['duration'])
shutil.copy(audio['file'], audio['tmp'])
total_time = audio['duration'] if total_time < audio['duration'] else total_time
print(f"[*] File duration audio {num}: {audio['duration']}")
self.progress_bar.setValue(25)
subprocess.check_output(["echo", tmp_dir_name]).decode('utf-8')
else:
for num, audio in enumerate(audio_files):
audio['duration'] = float(mediainfo(audio['file'])['duration'])
audio['tmp'] = self.audio_dir + "/both_channel" + "." + audio['ext']
shutil.copy(audio['file'], audio['tmp'])
total_time = audio['duration'] if total_time < audio['duration'] else total_time
print(f"[*] File duration audio {num}: {audio['duration']}")
if connected_channels:
# Split channels
number_of_files = "1"
self.log_label.setText("Split audio file 1/5")
print(subprocess.check_output([
"bash", "bash_commands/split_channels_to_two_ways.sh",
audio_dir, number_of_files, audio_files[0]['tmp']
]))
else:
print(F"DUARTION {audio_files[0]['duration'], audio_files[1]['duration']}")
if float(audio_files[0]['duration']) > float(audio_files[1]['duration']):
print("LEFT")
print(f'[*] Images in {self.pics_dir}: {os.listdir(self.pics_dir)}')
print(f'[*] Audo files in {self.audio_dir}: {os.listdir(self.audio_dir)}')
else:
print("RIGHT")
# self.progress_bar.setValue(25)
number_of_files = "2"
self.log_label.setText("Copy audio files 1/5")
print(subprocess.check_output([
"bash", "bash_commands/split_channels_to_two_ways.sh",
audio_dir, number_of_files, audio_files[0]['tmp'], audio_files[1]['tmp']
]))
return threshold_value, connected_channels, audio_files, image_files, total_time
self.progress_bar.setValue(30)
self.log_label.setText(f"Create raw files 2/5")
subprocess.check_output(['bash',
'bash_commands/create_raw_files.sh',
audio_dir, self.aresample])
def generate_video_podcast(self, output_file_name="video-and-audio.mp4", start=None, end=None):
"""
Method to generate video podcast based on collected data from ui.
self.progress_bar.setValue(60)
self.log_label.setText(f"Create demuxer 3/5")
generate_demuxer.run(tmp_dir=tmp_dir_name)
:param start: Sets the start of the recording to the set second.
:param end: Sets the end of the recording to the set second.
:param output_file_name: Output name of podcast (default = video-and-audio.mp4)
If you are generating an entire podcast leave the default value in start and end arg,
otherwise the recording will be cut to the set values.
:return:
"""
if not output_file_name:
output_file_name = str(datetime.timestamp(datetime.utcnow())) + '_output.mp4'
threshold_value = None
connected_channels = None
audio_files = None
image_files = None
total_time = None
try:
threshold_value, connected_channels, audio_files, image_files, total_time = self.collect_data_files()
print(audio_files)
except FileNotFoundError:
return -1
"""Generate podcast based on values from UI."""
self.progress_bar.setValue(0)
self.progress_bar.show()
if start is not None and end is not None:
for audio in audio_files:
print("Get fragment of audio files")
data = AudioSegment.from_file(audio['tmp'], format=audio['ext'])[start*1000:end*1000]
print(F"Frame rate of data:", data.frame_rate)
total_time = int(end)
data.export(out_f=audio['tmp'], format=audio['ext'])
audio['duration'] = float(mediainfo(audio['tmp'])['duration'])
if connected_channels:
# Split channels
number_of_files = "1"
self.log_label.setText("Split audio file 1/5")
subprocess.check_output([
"bash", "bash_commands/split_channels_to_two_ways.sh",
self.audio_dir, number_of_files, audio_files[0]['tmp']
])
else:
print(F"DUARTION {audio_files[0]['duration'], audio_files[1]['duration']}")
number_of_files = "2"
self.log_label.setText("Copy audio files 1/5")
subprocess.check_output([
"bash", "bash_commands/split_channels_to_two_ways.sh",
self.audio_dir, number_of_files, audio_files[0]['tmp'], audio_files[1]['tmp']
])
self.progress_bar.setValue(30)
self.log_label.setText(f"Create raw files 2/5")
subprocess.check_output(['bash',
'bash_commands/create_raw_files.sh',
self.audio_dir, self.aresample])
self.progress_bar.setValue(60)
self.log_label.setText(f"Create demuxer 3/5")
generate_demuxer.run(tmp_dir=self.tmp_working_directory.name)
self.log_label.setText(f"Create video 4/5")
subprocess.check_output(
['bash', 'bash_commands/generate_video_by_demuxer.sh', self.video_dir])
self.progress_bar.setValue(75)
self.log_label.setText(f"Create final podcast 5/5")
if connected_channels:
self.log_label.setText(f"Create video 4/5")
subprocess.check_output(
['bash', 'bash_commands/generate_video_by_demuxer.sh', tmp_dir_name, video_dir])
['bash', 'bash_commands/connect_sound.sh', self.video_dir, audio_files[0]['tmp'], self.output_dir, output_file_name])
self.progress_bar.setValue(100)
else:
left_channel = None
right_channel = None
stereo = None
self.progress_bar.setValue(75)
self.log_label.setText(f"Create final podcast 5/5")
if connected_channels:
subprocess.check_output(
['bash', 'bash_commands/connect_sound.sh', tmp_dir_name, "1", audio_files[0]['file']])
self.progress_bar.setValue(100)
if audio_files[0]['tmp'].endswith('.mp3'):
print(1)
left_channel = AudioSegment.from_mp3(audio_files[0]['tmp']).set_channels(1)
else:
print("IAM HEEEEERERERERERER")
subprocess.check_output(
['bash', 'bash_commands/connect_sound.sh', tmp_dir_name, "2", audio_files[0]['file'], audio_files[1]['file']])
self.progress_bar.setValue(100)
left_channel = AudioSegment.from_wav(audio_files[0]['tmp']).set_channels(1)
dialog_done = self.create_custom_dialog(title="Informacja", msg="Zakończono generowanie podcastu.")
dialog_done.exec_()
self.progress_bar.setValue(0)
self.log_label.setText("")
self.log_label.hide()
if audio_files[1]['tmp'].endswith('.mp3'):
print(3)
right_channel = AudioSegment.from_mp3(audio_files[1]['tmp']).set_channels(1)
else:
print(4)
right_channel = AudioSegment.from_wav(audio_files[1]['tmp']).set_channels(1)
stereo = AudioSegment.from_mono_audiosegments(left_channel, right_channel)
stereo.export(self.audio_dir + '/channels.wav', format="wav")
print(F"{['bash', 'bash_commands/connect_sound.sh', self.video_dir, self.audio_dir + '/channels.wav', self.output_dir, output_file_name]}")
subprocess.check_output(
['bash', 'bash_commands/connect_sound.sh', self.video_dir, self.audio_dir + '/channels.wav', self.output_dir, output_file_name])
self.progress_bar.setValue(100)
if start is not None:
print(F"Emit signal podcast_preview_created with path: {self.output_dir + output_file_name}")
self.podcast_preview_crated_signal.emit(self.output_dir + output_file_name)
dialog_done = self.create_custom_dialog(title="Informacja", msg=F"Zakończono generowanie podcastu:\n{self.output_dir + output_file_name}")
dialog_done.exec_()
self.progress_bar.setValue(0)
self.log_label.setText("")
self.log_label.hide()

View File

@ -0,0 +1,164 @@
from pathlib import Path
from datetime import datetime
from PyQt5.QtCore import pyqtSignal, QUrl, QAbstractListModel, Qt, QFile, QFileInfo
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent, QMediaPlaylist
from src.python.classes.range_slider import QRangeSlider
from src.python.classes.video_player_dialog import VideoPlayerDialog, hhmmss
from src.python.ui.preview_creator_dialog_ui import Ui_PreviewCreatorDialog
from PyQt5.QtWidgets import QDialog
class PlaylistModel(QAbstractListModel):
"""
PlayListModel
"""
def __init__(self, playlist, *args, **kwargs):
super(PlaylistModel, self).__init__(*args, **kwargs)
self.playlist = playlist
def data(self, index, role):
"""
:param index:
:param role:
:return:
"""
if role == Qt.DisplayRole:
media = self.playlist.media(index.row())
return media.canonicalUrl().fileName()
def rowCount(self, index):
"""
Count number of rows
:param index:
:return:
"""
return self.playlist.mediaCount()
class PreviewCreatorDialog(QDialog, Ui_PreviewCreatorDialog):
"""
Dialog to show preview of podcast.
"""
preview_generate_signal = pyqtSignal(str, int, int)
play_signal = pyqtSignal(str)
def __init__(self, parent=None):
super(PreviewCreatorDialog, self).__init__(parent=parent)
self.setupUi(self)
# Create range slider
self.range_slider = QRangeSlider()
self.playlist_v_layout.addWidget(self.range_slider)
self.range_slider.c.range_changed.connect(self.update_line_edit_range_values)
self.left_range_line_edit.setText(str(self.range_slider.first_position))
self.right_range_line_edit.setText(str(self.range_slider.second_position))
self.create_preview_button.clicked.connect(self.generate_preview)
# Video dialog with video output
self.video_dialog = VideoPlayerDialog()
# Create playlist
self.playlist = QMediaPlaylist()
# Assignment list to player
self.video_dialog.player.setPlaylist(self.playlist)
# Create model of list from list
self.model = PlaylistModel(self.playlist)
self.playlistView.setModel(self.model)
self.playlist.currentIndexChanged.connect(self.playlist_position_changed)
selection_model = self.playlistView.selectionModel()
selection_model.selectionChanged.connect(self.playlist_selection_changed)
self.playlistView.doubleClicked.connect(self.open_dialog)
self.play_signal.connect(self.video_dialog.player.play)
self.setAcceptDrops(True)
def open_dialog(self):
""" Open video dialog """
if self.video_dialog.isHidden():
self.video_dialog.show()
self.video_dialog.player.setPlaylist(self.playlist)
def playlist_selection_changed(self, ix):
"""
Change selection on playlist in player
:param ix: index
"""
# We receive a QItemSelection from selectionChanged.
i = ix.indexes()[0].row()
self.playlist.setCurrentIndex(i)
self.video_dialog.player.playlist().setCurrentIndex(i)
def playlist_position_changed(self, i):
"""
Change podcast preview on playlist in playlistView
:param i: index
"""
if i > -1:
ix = self.model.index(i)
self.playlistView.setCurrentIndex(ix)
def add_element_to_list(self, path):
"""
Put items to playlist widget.
:param path:
"""
self.playlist.addMedia(QMediaContent(
QUrl.fromLocalFile(QFileInfo(path).absoluteFilePath()))
)
self.model.layoutChanged.emit()
# self.play_signal.emit(path)
def dragEnterEvent(self, e):
if e.mimeData().hasUrls():
e.acceptProposedAction()
def dropEvent(self, e):
"""
:param e: DropEvent from playlist
"""
for url in e.mimeData().urls():
self.playlist.addMedia(
QMediaContent(url)
)
self.model.layoutChanged.emit()
# If not playing, seeking to first of newly added + play.
if self.video_dialog.player.state() != QMediaPlayer.PlayingState:
i = self.playlist.mediaCount() - len(e.mimeData().urls())
self.playlist.setCurrentIndex(i)
# self.video_dialog.player.play()
def generate_preview(self):
"""Send singal to generate preview"""
generated_name = 'previews/' + str(datetime.timestamp(datetime.utcnow())) + '_preview.mp4'
print(F"signal emit {generated_name, int(self.range_slider.first_position), int(self.range_slider.second_position)}")
self.preview_generate_signal.emit(
generated_name, int(self.range_slider.first_position), int(self.range_slider.second_position))
def update_line_edit_range_values(self, x, y):
"""Update values."""
if x == 1:
self.left_range_line_edit.setText(str(y))
elif x == 2:
self.right_range_line_edit.setText(str(y))
def total_time_changed(self, total_time):
"""
:param total_time: time of fragment podcast
:return:
"""
self.range_slider.setRange(0, total_time)
self.range_slider.setRangeLimit(0, total_time)
self.left_range_line_edit.setText(str(self.range_slider.first_position))
self.right_range_line_edit.setText(str(self.range_slider.second_position))

View File

@ -1,106 +0,0 @@
from pathlib import Path
from PyQt5.QtMultimedia import QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from src.python.classes.range_slider import QRangeSlider
from src.python.ui.preview_dialog_ui import Ui_PreviewDialog
from PyQt5.QtWidgets import QDialog, QStyle
class PreviewDialog(QDialog, Ui_PreviewDialog):
"""
Dialog to show preview of podcast.
"""
def __init__(self, parent=None, start_time=0, end_time=15):
super(PreviewDialog, self).__init__(parent=parent)
self.setupUi(self)
self.mediaPlayer = QMediaPlayer(parent=self, flags=QMediaPlayer.VideoSurface)
self.video_widget = QVideoWidget()
self.range_slider = QRangeSlider()
self.v_layout_1.addWidget(self.video_widget)
self.v_layout_1.addWidget(self.range_slider)
self.range_slider.setRangeLimit(minimum=int(start_time), maximum=int(end_time))
self.range_slider.setRange(start=int(start_time), end=int(end_time))
self.range_slider.c.range_changed.connect(self.update_line_edit_values)
self.left_range.setText(str(self.range_slider.first_position))
self.right_range.setText(str(self.range_slider.second_position))
def update_line_edit_values(self, x, y):
"""Update values."""
if x == 1:
self.left_range.setText(str(y))
elif x == 2:
self.right_range.setText(str(y))
def get_audio_files(self):
"""Load time of audio files"""
audio_files = []
if not self.connected_channels_status:
audio_files.append({'file': self.line_edit_audio_1.text()})
audio_files.append({'file': self.line_edit_audio_2.text()})
else:
audio_files.append({'file': self.line_edit_audio_1.text()})
for audio_path in audio_files:
if not Path(audio_path['file']).is_file():
if not self.check_file(audio_path['file'], self.audio_extensions):
self.create_custom_dialog(title='Błąd!', msg="Tworzenie podcastu zostało przerwane.")
return -1
return audio_files
def setup_video_logic(self):
"""
Setup connections to events
"""
self.mediaPlayer.setVideoOutput(self.video_widget)
self.mediaPlayer.stateChanged.connect(self.media_state_changed)
self.mediaPlayer.positionChanged.connect(self.position_changed)
self.mediaPlayer.durationChanged.connect(self.duration_changed)
self.create_preview_button.connect(self.generate_podcast_preview)
def media_state_changed(self, state):
"""
:param state:
"""
if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
self.playButton.setIcon(
self.style().standardIcon(QStyle.SP_MediaPause))
else:
self.playButton.setIcon(
self.style().standardIcon(QStyle.SP_MediaPlay))
def position_changed(self):
"""
Position Changed
"""
if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
self.mediaPlayer.pause()
else:
self.mediaPlayer.play()
def play(self):
"""
Play
"""
if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
self.mediaPlayer.pause()
else:
self.mediaPlayer.play()
def duration_changed(self, duration):
"""
:param duration:
:return:
"""
self.positionSlider.setRange(0, duration)

View File

@ -23,6 +23,8 @@ class QRangeSlider(QAbstractSlider):
self.opt = QStyleOptionSlider()
self.opt.minimum = 0
self.opt.maximum = 100
self.opt.singleStep = 0.1
self.minimum_between = 1
self.setTickPosition(QSlider.TicksAbove)
self.setTickInterval(1)
@ -30,10 +32,6 @@ class QRangeSlider(QAbstractSlider):
self.setSizePolicy(
QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed, QSizePolicy.Slider)
)
self.c.range_changed.connect(self.handle_emit)
def handle_emit(self, x, y):
print(x, y)
def setRangeLimit(self, minimum: int, maximum: int):
"""Set new range limit."""
@ -49,6 +47,10 @@ class QRangeSlider(QAbstractSlider):
"""Get selected current range."""
return self.first_position, self.second_position
def checkMinBetweenRange(self, first_position: int, second_position: int):
"""Check min.range between first and last handler higher than minimal."""
return True if int(second_position) - int(first_position) >= self.minimum_between else False
def setTickPosition(self, position: QSlider.TickPosition):
"""Set tick position."""
self.opt.tickPosition = position
@ -71,7 +73,6 @@ class QRangeSlider(QAbstractSlider):
self.style().drawComplexControl(QStyle.CC_Slider, self.opt, painter)
# Draw INTERVAL
color = self.palette().color(QPalette.Highlight)
color.setAlpha(160)
painter.setBrush(QBrush(color))
@ -105,7 +106,6 @@ class QRangeSlider(QAbstractSlider):
painter.drawRect(selection)
# Draw first handle
self.opt.subControls = QStyle.SC_SliderHandle
self.opt.sliderPosition = self.first_position
self.style().drawComplexControl(QStyle.CC_Slider, self.opt, painter)
@ -116,6 +116,7 @@ class QRangeSlider(QAbstractSlider):
def mousePressEvent(self, event: QMouseEvent):
"""Handle mouse press event."""
# print(self.first_position, self.second_position)
self.opt.sliderPosition = self.first_position
self._first_sc = self.style().hitTestComplexControl(
QStyle.CC_Slider, self.opt, event.pos(), self
@ -134,15 +135,17 @@ class QRangeSlider(QAbstractSlider):
0, distance, event.pos().x(), self.rect().width()
)
# Set position of first handler
if self._first_sc == QStyle.SC_SliderHandle:
if pos <= self.second_position:
if pos <= self.second_position and self.checkMinBetweenRange(pos, self.second_position):
self.first_position = pos
self.c.range_changed.emit(1, pos)
self.update()
return
# Set position of secound handler
if self._second_sc == QStyle.SC_SliderHandle:
if pos >= self.first_position:
if pos >= self.first_position and self.checkMinBetweenRange(self.first_position, pos):
self.second_position = pos
self.c.range_changed.emit(2, pos)
self.update()
@ -150,17 +153,17 @@ class QRangeSlider(QAbstractSlider):
def sizeHint(self):
""" Override sizeHint """
SliderLength = 84
TickSpace = 5
slider_length = 84
tick_space = 5
w = SliderLength
w = slider_length
h = self.style().pixelMetric(QStyle.PM_SliderThickness, self.opt, self)
if (
self.opt.tickPosition & QSlider.TicksAbove
or self.opt.tickPosition & QSlider.TicksBelow
):
h += TickSpace
h += tick_space
return (
self.style()

View File

@ -0,0 +1,87 @@
from PyQt5.QtCore import QUrl
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import QDialog, QFileDialog
from src.python.ui.video_player_dialog_ui import Ui_VideoPlayerDialog
def hhmmss(ms):
"""
:param ms: milliseconds
:return: time
"""
# s = 1000
# m = 60000
# h = 360000
h, r = divmod(ms, 36000)
m, r = divmod(r, 60000)
s, _ = divmod(r, 1000)
return ("%d:%02d:%02d" % (h, m, s)) if h else ("%d:%02d" % (m, s))
class VideoPlayerDialog(QDialog, Ui_VideoPlayerDialog):
"""
Class to create Video Player in Dialog window.
"""
def __init__(self, parent=None):
super(VideoPlayerDialog, self).__init__(parent=parent)
self.setupUi(self)
# Media player
self.player = QMediaPlayer()
# self.player.error.connect(self.error_alert)
# self.open_button.clicked.connect(self.open_file)
self.videoWidget = QVideoWidget()
self.player.setVideoOutput(self.videoWidget)
self.video_v_layout.addWidget(self.videoWidget)
self.player.durationChanged.connect(self.update_duration)
self.player.positionChanged.connect(self.update_position)
# Connect control buttons/slides for media player.
self.play_button.pressed.connect(self.player.play)
self.pause_button.pressed.connect(self.player.pause)
self.stop_button.pressed.connect(self.stop_event)
self.volume_slider.valueChanged.connect(self.player.setVolume)
self.time_slider.valueChanged.connect(self.player.setPosition)
# self.previous_button.pressed.connect(self.player.playlist().previous)
# self.next_button.pressed.connect(self.player.playlist().next)
def update_duration(self, duration):
"""
:param duration:
"""
print("[VideoPlayer] Update duration")
print("!", duration)
print("?", self.player.duration())
self.time_slider.setMaximum(duration)
if duration >= 0:
self.total_time_label.setText(hhmmss(duration))
def stop_event(self):
self.update_position(0)
self.player.stop()
def update_position(self, position):
"""
:param position:
"""
print("[VideoPlayer] Update position")
if position >= 0:
self.current_time_label.setText(hhmmss(position))
# Disable the events to prevent updating triggering a setPosition event (can cause stuttering).
self.time_slider.blockSignals(True)
self.time_slider.setValue(position)
self.time_slider.blockSignals(False)
def closeEvent(self, event):
print("[VideoPlayer] Hide")
self.hide()
self.update_position(0)
self.player.stop()
event.ignore()

View File

@ -15,6 +15,7 @@ class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(554, 807)
MainWindow.setMaximumSize(QtCore.QSize(800, 16777215))
self.central_widget = QtWidgets.QWidget(MainWindow)
self.central_widget.setMinimumSize(QtCore.QSize(0, 0))
self.central_widget.setObjectName("central_widget")
@ -97,7 +98,7 @@ class Ui_MainWindow(object):
sizePolicy.setHeightForWidth(self.preview_label_avatar_1.sizePolicy().hasHeightForWidth())
self.preview_label_avatar_1.setSizePolicy(sizePolicy)
self.preview_label_avatar_1.setMinimumSize(QtCore.QSize(0, 150))
self.preview_label_avatar_1.setMaximumSize(QtCore.QSize(300, 150))
self.preview_label_avatar_1.setMaximumSize(QtCore.QSize(400, 16777215))
self.preview_label_avatar_1.setFrameShape(QtWidgets.QFrame.Box)
self.preview_label_avatar_1.setScaledContents(True)
self.preview_label_avatar_1.setAlignment(QtCore.Qt.AlignCenter)
@ -111,7 +112,7 @@ class Ui_MainWindow(object):
sizePolicy.setHeightForWidth(self.button_select_avatar_1.sizePolicy().hasHeightForWidth())
self.button_select_avatar_1.setSizePolicy(sizePolicy)
self.button_select_avatar_1.setMinimumSize(QtCore.QSize(200, 35))
self.button_select_avatar_1.setMaximumSize(QtCore.QSize(16777215, 35))
self.button_select_avatar_1.setMaximumSize(QtCore.QSize(400, 35))
self.button_select_avatar_1.setIcon(icon)
self.button_select_avatar_1.setObjectName("button_select_avatar_1")
self.w_layout_avatar_1.addWidget(self.button_select_avatar_1)
@ -127,7 +128,7 @@ class Ui_MainWindow(object):
sizePolicy.setHeightForWidth(self.preview_label_avatar_2.sizePolicy().hasHeightForWidth())
self.preview_label_avatar_2.setSizePolicy(sizePolicy)
self.preview_label_avatar_2.setMinimumSize(QtCore.QSize(0, 150))
self.preview_label_avatar_2.setMaximumSize(QtCore.QSize(300, 150))
self.preview_label_avatar_2.setMaximumSize(QtCore.QSize(400, 16777215))
self.preview_label_avatar_2.setFrameShape(QtWidgets.QFrame.Box)
self.preview_label_avatar_2.setScaledContents(True)
self.preview_label_avatar_2.setAlignment(QtCore.Qt.AlignCenter)
@ -141,7 +142,7 @@ class Ui_MainWindow(object):
sizePolicy.setHeightForWidth(self.button_select_avatar_2.sizePolicy().hasHeightForWidth())
self.button_select_avatar_2.setSizePolicy(sizePolicy)
self.button_select_avatar_2.setMinimumSize(QtCore.QSize(200, 35))
self.button_select_avatar_2.setMaximumSize(QtCore.QSize(16777215, 35))
self.button_select_avatar_2.setMaximumSize(QtCore.QSize(400, 35))
self.button_select_avatar_2.setIcon(icon)
self.button_select_avatar_2.setObjectName("button_select_avatar_2")
self.w_layout_avatar_2.addWidget(self.button_select_avatar_2)
@ -160,7 +161,7 @@ class Ui_MainWindow(object):
sizePolicy.setHeightForWidth(self.preview_label_avatar_3.sizePolicy().hasHeightForWidth())
self.preview_label_avatar_3.setSizePolicy(sizePolicy)
self.preview_label_avatar_3.setMinimumSize(QtCore.QSize(0, 150))
self.preview_label_avatar_3.setMaximumSize(QtCore.QSize(300, 150))
self.preview_label_avatar_3.setMaximumSize(QtCore.QSize(400, 16777215))
self.preview_label_avatar_3.setFrameShape(QtWidgets.QFrame.Box)
self.preview_label_avatar_3.setTextFormat(QtCore.Qt.RichText)
self.preview_label_avatar_3.setScaledContents(True)
@ -175,7 +176,7 @@ class Ui_MainWindow(object):
sizePolicy.setHeightForWidth(self.button_select_avatar_3.sizePolicy().hasHeightForWidth())
self.button_select_avatar_3.setSizePolicy(sizePolicy)
self.button_select_avatar_3.setMinimumSize(QtCore.QSize(200, 35))
self.button_select_avatar_3.setMaximumSize(QtCore.QSize(16777215, 35))
self.button_select_avatar_3.setMaximumSize(QtCore.QSize(400, 35))
self.button_select_avatar_3.setIcon(icon)
self.button_select_avatar_3.setObjectName("button_select_avatar_3")
self.w_layout_avatar_3.addWidget(self.button_select_avatar_3)
@ -191,7 +192,7 @@ class Ui_MainWindow(object):
sizePolicy.setHeightForWidth(self.preview_label_avatar_4.sizePolicy().hasHeightForWidth())
self.preview_label_avatar_4.setSizePolicy(sizePolicy)
self.preview_label_avatar_4.setMinimumSize(QtCore.QSize(0, 150))
self.preview_label_avatar_4.setMaximumSize(QtCore.QSize(300, 150))
self.preview_label_avatar_4.setMaximumSize(QtCore.QSize(400, 16777215))
self.preview_label_avatar_4.setFrameShape(QtWidgets.QFrame.Box)
self.preview_label_avatar_4.setScaledContents(True)
self.preview_label_avatar_4.setAlignment(QtCore.Qt.AlignCenter)
@ -205,7 +206,7 @@ class Ui_MainWindow(object):
sizePolicy.setHeightForWidth(self.button_select_avatar_4.sizePolicy().hasHeightForWidth())
self.button_select_avatar_4.setSizePolicy(sizePolicy)
self.button_select_avatar_4.setMinimumSize(QtCore.QSize(200, 35))
self.button_select_avatar_4.setMaximumSize(QtCore.QSize(16777215, 35))
self.button_select_avatar_4.setMaximumSize(QtCore.QSize(400, 35))
self.button_select_avatar_4.setIcon(icon)
self.button_select_avatar_4.setObjectName("button_select_avatar_4")
self.w_layout_avatar_4.addWidget(self.button_select_avatar_4)

View File

@ -0,0 +1,89 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './src/gui/ui/preview_creator_dialog.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_PreviewCreatorDialog(object):
def setupUi(self, PreviewCreatorDialog):
PreviewCreatorDialog.setObjectName("PreviewCreatorDialog")
PreviewCreatorDialog.setWindowModality(QtCore.Qt.NonModal)
PreviewCreatorDialog.resize(584, 422)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/icons/src/gui/images/icons/preview.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
PreviewCreatorDialog.setWindowIcon(icon)
self.verticalLayout = QtWidgets.QVBoxLayout(PreviewCreatorDialog)
self.verticalLayout.setObjectName("verticalLayout")
self.playlist_v_layout = QtWidgets.QVBoxLayout()
self.playlist_v_layout.setObjectName("playlist_v_layout")
self.playlistView = QtWidgets.QListView(PreviewCreatorDialog)
self.playlistView.setAcceptDrops(True)
self.playlistView.setProperty("showDropIndicator", True)
self.playlistView.setDragDropMode(QtWidgets.QAbstractItemView.DropOnly)
self.playlistView.setDefaultDropAction(QtCore.Qt.CopyAction)
self.playlistView.setAlternatingRowColors(True)
self.playlistView.setUniformItemSizes(True)
self.playlistView.setObjectName("playlistView")
self.playlist_v_layout.addWidget(self.playlistView)
self.verticalLayout.addLayout(self.playlist_v_layout)
self.line = QtWidgets.QFrame(PreviewCreatorDialog)
self.line.setFrameShape(QtWidgets.QFrame.HLine)
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line.setObjectName("line")
self.verticalLayout.addWidget(self.line)
self.range_values_h_layout = QtWidgets.QHBoxLayout()
self.range_values_h_layout.setObjectName("range_values_h_layout")
self.left_label = QtWidgets.QLabel(PreviewCreatorDialog)
self.left_label.setObjectName("left_label")
self.range_values_h_layout.addWidget(self.left_label)
self.left_range_line_edit = QtWidgets.QLineEdit(PreviewCreatorDialog)
self.left_range_line_edit.setInputMethodHints(QtCore.Qt.ImhPreferNumbers|QtCore.Qt.ImhTime)
self.left_range_line_edit.setObjectName("left_range_line_edit")
self.range_values_h_layout.addWidget(self.left_range_line_edit)
self.right_label = QtWidgets.QLabel(PreviewCreatorDialog)
self.right_label.setObjectName("right_label")
self.range_values_h_layout.addWidget(self.right_label)
self.right_range_line_edit = QtWidgets.QLineEdit(PreviewCreatorDialog)
self.right_range_line_edit.setInputMethodHints(QtCore.Qt.ImhPreferNumbers|QtCore.Qt.ImhTime)
self.right_range_line_edit.setObjectName("right_range_line_edit")
self.range_values_h_layout.addWidget(self.right_range_line_edit)
self.create_preview_button = QtWidgets.QPushButton(PreviewCreatorDialog)
self.create_preview_button.setObjectName("create_preview_button")
self.range_values_h_layout.addWidget(self.create_preview_button)
self.verticalLayout.addLayout(self.range_values_h_layout)
self.log_label = QtWidgets.QLabel(PreviewCreatorDialog)
self.log_label.setObjectName("log_label")
self.verticalLayout.addWidget(self.log_label)
self.progress_bar = QtWidgets.QProgressBar(PreviewCreatorDialog)
self.progress_bar.setProperty("value", 0)
self.progress_bar.setObjectName("progress_bar")
self.verticalLayout.addWidget(self.progress_bar)
self.retranslateUi(PreviewCreatorDialog)
QtCore.QMetaObject.connectSlotsByName(PreviewCreatorDialog)
def retranslateUi(self, PreviewCreatorDialog):
_translate = QtCore.QCoreApplication.translate
PreviewCreatorDialog.setWindowTitle(_translate("PreviewCreatorDialog", "MagicPodcast - preview podcast"))
self.left_label.setText(_translate("PreviewCreatorDialog", "Czas rozpoczęcia:"))
self.right_label.setText(_translate("PreviewCreatorDialog", "Czas zakończenia:"))
self.create_preview_button.setText(_translate("PreviewCreatorDialog", "Utwórz podgląd"))
self.log_label.setText(_translate("PreviewCreatorDialog", "TextLabel"))
import resources_rc
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
PreviewCreatorDialog = QtWidgets.QDialog()
ui = Ui_PreviewCreatorDialog()
ui.setupUi(PreviewCreatorDialog)
PreviewCreatorDialog.show()
sys.exit(app.exec_())

View File

@ -1,88 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './src/gui/ui/preview_dialog.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_PreviewDialog(object):
def setupUi(self, PreviewDialog):
PreviewDialog.setObjectName("PreviewDialog")
PreviewDialog.setWindowModality(QtCore.Qt.NonModal)
PreviewDialog.resize(779, 356)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/icons/src/gui/images/icons/preview.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
PreviewDialog.setWindowIcon(icon)
self.verticalLayout = QtWidgets.QVBoxLayout(PreviewDialog)
self.verticalLayout.setObjectName("verticalLayout")
self.v_layout_1 = QtWidgets.QVBoxLayout()
self.v_layout_1.setObjectName("v_layout_1")
self.verticalLayout.addLayout(self.v_layout_1)
self.line_2 = QtWidgets.QFrame(PreviewDialog)
self.line_2.setFrameShape(QtWidgets.QFrame.HLine)
self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_2.setObjectName("line_2")
self.verticalLayout.addWidget(self.line_2)
self.h_layout_range_values = QtWidgets.QHBoxLayout()
self.h_layout_range_values.setObjectName("h_layout_range_values")
self.left_label = QtWidgets.QLabel(PreviewDialog)
self.left_label.setObjectName("left_label")
self.h_layout_range_values.addWidget(self.left_label)
self.left_range = QtWidgets.QLineEdit(PreviewDialog)
self.left_range.setInputMethodHints(QtCore.Qt.ImhPreferNumbers|QtCore.Qt.ImhTime)
self.left_range.setObjectName("left_range")
self.h_layout_range_values.addWidget(self.left_range)
self.right_label = QtWidgets.QLabel(PreviewDialog)
self.right_label.setObjectName("right_label")
self.h_layout_range_values.addWidget(self.right_label)
self.right_range = QtWidgets.QLineEdit(PreviewDialog)
self.right_range.setInputMethodHints(QtCore.Qt.ImhPreferNumbers|QtCore.Qt.ImhTime)
self.right_range.setObjectName("right_range")
self.h_layout_range_values.addWidget(self.right_range)
self.create_preview_button = QtWidgets.QPushButton(PreviewDialog)
self.create_preview_button.setObjectName("create_preview_button")
self.h_layout_range_values.addWidget(self.create_preview_button)
self.verticalLayout.addLayout(self.h_layout_range_values)
self.line = QtWidgets.QFrame(PreviewDialog)
self.line.setFrameShape(QtWidgets.QFrame.HLine)
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line.setObjectName("line")
self.verticalLayout.addWidget(self.line)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.play_button = QtWidgets.QPushButton(PreviewDialog)
self.play_button.setObjectName("play_button")
self.horizontalLayout.addWidget(self.play_button)
self.stop_button = QtWidgets.QPushButton(PreviewDialog)
self.stop_button.setObjectName("stop_button")
self.horizontalLayout.addWidget(self.stop_button)
self.verticalLayout.addLayout(self.horizontalLayout)
self.retranslateUi(PreviewDialog)
QtCore.QMetaObject.connectSlotsByName(PreviewDialog)
def retranslateUi(self, PreviewDialog):
_translate = QtCore.QCoreApplication.translate
PreviewDialog.setWindowTitle(_translate("PreviewDialog", "MagicPodcast - preview podcast"))
self.left_label.setText(_translate("PreviewDialog", "Czas rozpoczęcia:"))
self.right_label.setText(_translate("PreviewDialog", "Czas zakończenia:"))
self.create_preview_button.setText(_translate("PreviewDialog", "Utwórz podgląd"))
self.play_button.setText(_translate("PreviewDialog", "Start"))
self.stop_button.setText(_translate("PreviewDialog", "Stop"))
import resources_rc
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
PreviewDialog = QtWidgets.QDialog()
ui = Ui_PreviewDialog()
ui.setupUi(PreviewDialog)
PreviewDialog.show()
sys.exit(app.exec_())

View File

@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './src/gui/ui/video_player_dialog.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_VideoPlayerDialog(object):
def setupUi(self, VideoPlayerDialog):
VideoPlayerDialog.setObjectName("VideoPlayerDialog")
VideoPlayerDialog.resize(640, 480)
self.verticalLayout = QtWidgets.QVBoxLayout(VideoPlayerDialog)
self.verticalLayout.setObjectName("verticalLayout")
self.video_v_layout = QtWidgets.QVBoxLayout()
self.video_v_layout.setObjectName("video_v_layout")
self.verticalLayout.addLayout(self.video_v_layout)
self.time_h_layout = QtWidgets.QHBoxLayout()
self.time_h_layout.setObjectName("time_h_layout")
self.current_time_label = QtWidgets.QLabel(VideoPlayerDialog)
self.current_time_label.setMinimumSize(QtCore.QSize(80, 0))
self.current_time_label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.current_time_label.setObjectName("current_time_label")
self.time_h_layout.addWidget(self.current_time_label)
self.time_slider = QtWidgets.QSlider(VideoPlayerDialog)
self.time_slider.setOrientation(QtCore.Qt.Horizontal)
self.time_slider.setObjectName("time_slider")
self.time_h_layout.addWidget(self.time_slider)
self.total_time_label = QtWidgets.QLabel(VideoPlayerDialog)
self.total_time_label.setMinimumSize(QtCore.QSize(80, 0))
self.total_time_label.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
self.total_time_label.setObjectName("total_time_label")
self.time_h_layout.addWidget(self.total_time_label)
self.verticalLayout.addLayout(self.time_h_layout)
self.buttons_h_layout = QtWidgets.QHBoxLayout()
self.buttons_h_layout.setObjectName("buttons_h_layout")
self.previous_button = QtWidgets.QPushButton(VideoPlayerDialog)
self.previous_button.setText("")
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/video-icons/src/gui/images/icons/control-skip-180.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.previous_button.setIcon(icon)
self.previous_button.setObjectName("previous_button")
self.buttons_h_layout.addWidget(self.previous_button)
self.play_button = QtWidgets.QPushButton(VideoPlayerDialog)
self.play_button.setText("")
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(":/video-icons/src/gui/images/icons/control.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.play_button.setIcon(icon1)
self.play_button.setObjectName("play_button")
self.buttons_h_layout.addWidget(self.play_button)
self.pause_button = QtWidgets.QPushButton(VideoPlayerDialog)
self.pause_button.setText("")
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(":/video-icons/src/gui/images/icons/control-pause.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.pause_button.setIcon(icon2)
self.pause_button.setObjectName("pause_button")
self.buttons_h_layout.addWidget(self.pause_button)
self.stop_button = QtWidgets.QPushButton(VideoPlayerDialog)
self.stop_button.setText("")
icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap(":/video-icons/src/gui/images/icons/control-stop-square.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.stop_button.setIcon(icon3)
self.stop_button.setObjectName("stop_button")
self.buttons_h_layout.addWidget(self.stop_button)
self.next_button = QtWidgets.QPushButton(VideoPlayerDialog)
self.next_button.setText("")
icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap(":/video-icons/src/gui/images/icons/control-skip.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.next_button.setIcon(icon4)
self.next_button.setObjectName("next_button")
self.buttons_h_layout.addWidget(self.next_button)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.buttons_h_layout.addItem(spacerItem)
self.volume_label = QtWidgets.QLabel(VideoPlayerDialog)
self.volume_label.setText("")
self.volume_label.setPixmap(QtGui.QPixmap(":/video-icons/src/gui/images/icons/speaker-volume.png"))
self.volume_label.setObjectName("volume_label")
self.buttons_h_layout.addWidget(self.volume_label)
self.volume_slider = QtWidgets.QSlider(VideoPlayerDialog)
self.volume_slider.setMaximum(100)
self.volume_slider.setProperty("value", 100)
self.volume_slider.setOrientation(QtCore.Qt.Horizontal)
self.volume_slider.setObjectName("volume_slider")
self.buttons_h_layout.addWidget(self.volume_slider)
self.verticalLayout.addLayout(self.buttons_h_layout)
self.retranslateUi(VideoPlayerDialog)
QtCore.QMetaObject.connectSlotsByName(VideoPlayerDialog)
def retranslateUi(self, VideoPlayerDialog):
_translate = QtCore.QCoreApplication.translate
VideoPlayerDialog.setWindowTitle(_translate("VideoPlayerDialog", "Dialog"))
self.current_time_label.setText(_translate("VideoPlayerDialog", "0:00"))
self.total_time_label.setText(_translate("VideoPlayerDialog", "0:00"))
import resources_rc
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
VideoPlayerDialog = QtWidgets.QDialog()
ui = Ui_VideoPlayerDialog()
ui.setupUi(VideoPlayerDialog)
VideoPlayerDialog.show()
sys.exit(app.exec_())