Merge branch 'master' into develop
2
Pipfile
@ -12,6 +12,8 @@ ffmpeg = "*"
|
||||
pip = "*"
|
||||
ffmpeg-python = "*"
|
||||
pydub = "*"
|
||||
sound = "*"
|
||||
pysignal = "*"
|
||||
|
||||
[dev-packages]
|
||||
|
||||
|
116
Pipfile.lock
generated
@ -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",
|
||||
|
@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
tmp_dir=$1
|
||||
tmp_video_dir=$1
|
||||
audio=$2
|
||||
output_dir=$3
|
||||
output_file=$4
|
||||
|
||||
ffmpeg -i $tmp_dir/video/video.mp4 -i $audio -ac 1 -tune stillimage ./out/video-and-audio.mp4 -y
|
||||
ffmpeg -y -i $tmp_video_dir/video.mp4 -i $audio -ac 1 -tune stillimage "$output_dir$output_file"
|
@ -5,4 +5,4 @@ aresample=$2
|
||||
ffmpeg -i $tmp_dir/left.wav -ac 1 -filter:a aresample=$aresample -map 0:a -c:a pcm_u8 -f data - > $tmp_dir/leftraw &
|
||||
ffmpeg -i $tmp_dir/right.wav -ac 1 -filter:a aresample=$aresample -map 0:a -c:a pcm_u8 -f data - > $tmp_dir/rightraw &
|
||||
|
||||
wait;
|
||||
wait;
|
@ -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
|
@ -1,5 +1,14 @@
|
||||
#!/bin/bash
|
||||
tmp_dir=$1
|
||||
both_channels=$2
|
||||
number_of_files=$2
|
||||
file_1=$3
|
||||
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 -y
|
||||
else
|
||||
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
|
||||
|
||||
ffmpeg -i $both_channels -map_channel 0.0.0 $tmp_dir/left.wav -map_channel 0.0.1 $tmp_dir/right.wav
|
@ -1,11 +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):
|
||||
@ -53,11 +53,11 @@ def new_mode(m, s):
|
||||
|
||||
def mode_to_string(mode):
|
||||
"""Convert mode type to string"""
|
||||
if mode['left'] and mode['right']:
|
||||
if mode['left'] is True and mode['right'] is True:
|
||||
return 'both'
|
||||
elif mode['left']:
|
||||
elif mode['left'] is True:
|
||||
return 'left'
|
||||
elif mode['right']:
|
||||
elif mode['right'] is True:
|
||||
return 'right'
|
||||
else:
|
||||
return "none"
|
||||
@ -65,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
|
||||
@ -75,16 +74,19 @@ def run(tmp_dir):
|
||||
threshold_at_point=threshold_at_point,
|
||||
inertia_samples=inertia_samples,
|
||||
label="left")
|
||||
print("LEFT:", left_loudness)
|
||||
|
||||
right_loudness = process_find_loudness(
|
||||
tmp_dir + "/audio/rightraw",
|
||||
threshold_at_point=threshold_at_point,
|
||||
inertia_samples=inertia_samples,
|
||||
label="right")
|
||||
print("RIGHT:", right_loudness)
|
||||
|
||||
merged = [*left_loudness, *right_loudness]
|
||||
# print(merged)
|
||||
sorted_list = sorted(merged, key=lambda x: x['position_start'])
|
||||
|
||||
# print(sorted_list)
|
||||
demuxer.write(F"file {tmp_dir}/pics/none.png\n")
|
||||
|
||||
last_point = 0
|
||||
|
2528
package-lock.json
generated
18
package.json
@ -1,18 +0,0 @@
|
||||
{
|
||||
"name": "vizualizer",
|
||||
"version": "1.0.0",
|
||||
"description": "ffmpeg -i odcinek1-kuba.wav -ac 1 -filter:a aresample=8000 -map 0:a -c:a pcm_s16le -f data - | hexdump",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/node": "^14.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"editly": "^0.3.0",
|
||||
"yargs": "^16.2.0"
|
||||
}
|
||||
}
|
@ -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,9 +37,18 @@
|
||||
<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>src/gui/images/icons/60x60.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
</RCC>
|
||||
|
178615
resources_rc.py
93
src/gui/fonts/Raleway/OFL.txt
Normal 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.
|
81
src/gui/fonts/Raleway/README.txt
Normal 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 aren’t 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.
|
BIN
src/gui/fonts/Raleway/Raleway-Italic-VariableFont_wght.ttf
Normal file
BIN
src/gui/fonts/Raleway/Raleway-Medium.ttf
Normal file
BIN
src/gui/fonts/Raleway/Raleway-VariableFont_wght.ttf
Normal file
BIN
src/gui/images/icons/application-image.png
Executable file
After Width: | Height: | Size: 544 B |
BIN
src/gui/images/icons/control-pause.png
Executable file
After Width: | Height: | Size: 427 B |
BIN
src/gui/images/icons/control-skip-180.png
Executable file
After Width: | Height: | Size: 577 B |
BIN
src/gui/images/icons/control-skip.png
Executable file
After Width: | Height: | Size: 572 B |
BIN
src/gui/images/icons/control-stop-square.png
Executable file
After Width: | Height: | Size: 411 B |
BIN
src/gui/images/icons/control.png
Executable file
After Width: | Height: | Size: 470 B |
BIN
src/gui/images/icons/speaker-volume.png
Executable file
After Width: | Height: | Size: 566 B |
@ -7,9 +7,15 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>554</width>
|
||||
<height>745</height>
|
||||
<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>
|
||||
@ -621,6 +627,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="log_label">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>h_line</zorder>
|
||||
<zorder>h_line_2</zorder>
|
||||
@ -629,6 +642,7 @@
|
||||
<zorder>v_spacer_1</zorder>
|
||||
<zorder>check_box_connected_channels</zorder>
|
||||
<zorder>progress_bar</zorder>
|
||||
<zorder>log_label</zorder>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menu_bar">
|
||||
<property name="geometry">
|
||||
|
@ -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>
|
164
src/gui/ui/video_player_dialog.ui
Normal 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>
|
@ -2,20 +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
|
||||
|
||||
@ -24,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)
|
||||
@ -33,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']
|
||||
@ -47,13 +53,18 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
|
||||
title='Process generowania podcastu',
|
||||
msg='Sprawdzanie poprawności danych'
|
||||
)
|
||||
self.test_data()
|
||||
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))
|
||||
@ -64,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"""
|
||||
@ -82,9 +95,14 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
|
||||
self.line_edit_name_1.setDisabled(True)
|
||||
self.line_edit_name_2.setDisabled(True)
|
||||
|
||||
def test_data(self):
|
||||
def test_data(self, option=1):
|
||||
"""Test data."""
|
||||
self.line_edit_audio_1.setText('./src/sounds/oba_kanały.mp3')
|
||||
if option == 2:
|
||||
self.check_box_connected_channels.setChecked(False)
|
||||
self.line_edit_audio_1.setText('./src/sounds/lewy_kanal.mp3')
|
||||
self.line_edit_audio_2.setText('./src/sounds/prawy_kanal.mp3')
|
||||
else:
|
||||
self.line_edit_audio_1.setText('./src/sounds/oba_kanały.mp3')
|
||||
pixmap1 = QPixmap('./src/gui/images/both.png')
|
||||
scaled_pixmap1 = pixmap1.scaled(pixmap1.size(), Qt.KeepAspectRatio)
|
||||
self.preview_label_avatar_1.setPixmap(scaled_pixmap1)
|
||||
@ -239,51 +257,32 @@ 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
|
||||
image_files = {
|
||||
'both': self.preview_label_avatar_1.property('path'),
|
||||
@ -295,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:
|
||||
@ -306,97 +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:
|
||||
self.preview_creator_dialog.log_label.show()
|
||||
self.log_label.setText(f'[*] Create temporary directory: {self.tmp_working_directory}')
|
||||
|
||||
print(tmp_dir_name)
|
||||
print(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.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.progress_bar.setValue(15)
|
||||
print(F"[!] Create tmp out dir: {tmp_out_dir}")
|
||||
os.mkdir(tmp_out_dir)
|
||||
# self.progress_bar.setValue(15)
|
||||
self.log_label.setText(f"[!] Create tmp out dir: {self.tmp_out_dir}")
|
||||
|
||||
print(f'[*] Create pics dir: {pics_dir}')
|
||||
os.mkdir(pics_dir)
|
||||
if not Path(self.tmp_out_dir).is_dir():
|
||||
os.mkdir(self.tmp_out_dir)
|
||||
|
||||
print(f'[*] Create audio dir: {audio_dir}')
|
||||
os.mkdir(audio_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)
|
||||
|
||||
print(f'[*] Create video dir: {video_dir}\n')
|
||||
os.mkdir(video_dir)
|
||||
self.log_label.setText(f"[*] Create audio dir: {self.audio_dir}")
|
||||
if not Path(self.audio_dir).is_dir():
|
||||
os.mkdir(self.audio_dir)
|
||||
|
||||
print(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 video dir: {self.video_dir}")
|
||||
if not Path(self.video_dir).is_dir():
|
||||
os.mkdir(self.video_dir)
|
||||
|
||||
self.progress_bar.setValue(20)
|
||||
print(f'[*] Copy audio to {audio_dir}\n')
|
||||
if not self.check_box_connected_channels.isChecked():
|
||||
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"[*] 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}")
|
||||
|
||||
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']
|
||||
|
||||
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']}")
|
||||
|
||||
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']}")
|
||||
|
||||
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)}')
|
||||
|
||||
# self.progress_bar.setValue(25)
|
||||
|
||||
return threshold_value, connected_channels, audio_files, image_files, total_time
|
||||
|
||||
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.
|
||||
|
||||
: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:
|
||||
|
||||
subprocess.check_output(
|
||||
['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
|
||||
|
||||
if audio_files[0]['tmp'].endswith('.mp3'):
|
||||
print(1)
|
||||
left_channel = AudioSegment.from_mp3(audio_files[0]['tmp']).set_channels(1)
|
||||
else:
|
||||
left_channel = AudioSegment.from_wav(audio_files[0]['tmp']).set_channels(1)
|
||||
|
||||
if audio_files[1]['tmp'].endswith('.mp3'):
|
||||
print(3)
|
||||
right_channel = AudioSegment.from_mp3(audio_files[1]['tmp']).set_channels(1)
|
||||
|
||||
else:
|
||||
audio_files[0]['tmp'] = audio_dir + "/both_channel" + "." + audio_files[0]['ext']
|
||||
shutil.copy(audio_files[0]['file'], audio_files[0]['tmp'])
|
||||
print(4)
|
||||
right_channel = AudioSegment.from_wav(audio_files[1]['tmp']).set_channels(1)
|
||||
|
||||
print(f'[*] Images in {pics_dir}: {os.listdir(pics_dir)}')
|
||||
print(f'[*] Audo files in {audio_dir}: {os.listdir(audio_dir)}')
|
||||
stereo = AudioSegment.from_mono_audiosegments(left_channel, right_channel)
|
||||
stereo.export(self.audio_dir + '/channels.wav', format="wav")
|
||||
|
||||
self.progress_bar.setValue(25)
|
||||
subprocess.check_output(["echo", tmp_dir_name]).decode('utf-8')
|
||||
|
||||
if connected_channels:
|
||||
# Split channels
|
||||
print("[-] Split channels - start:")
|
||||
subprocess.check_output(["bash",
|
||||
"bash_commands/split_channels_to_two_ways.sh",
|
||||
audio_dir,
|
||||
audio_files[0]['tmp']])
|
||||
print("[+] Split channels - done")
|
||||
|
||||
self.progress_bar.setValue(30)
|
||||
print("[-] Create raw files - start:")
|
||||
subprocess.check_output(['bash',
|
||||
'bash_commands/create_raw_files.sh',
|
||||
audio_dir, self.aresample])
|
||||
print("[+] Create raw files - done")
|
||||
|
||||
self.progress_bar.setValue(60)
|
||||
print("[-] Create demuxer - start:")
|
||||
generate_demuxer.run(tmp_dir=tmp_dir_name)
|
||||
print("[+] Create demuxer - done")
|
||||
|
||||
print('[-] Create video - start:')
|
||||
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/generate_video_by_demuxer.sh', tmp_dir_name, video_dir])
|
||||
print('[+] Create video - done')
|
||||
['bash', 'bash_commands/connect_sound.sh', self.video_dir, self.audio_dir + '/channels.wav', self.output_dir, output_file_name])
|
||||
|
||||
self.progress_bar.setValue(75)
|
||||
# while True: pass
|
||||
print('[-] Create final podcast - start:')
|
||||
subprocess.check_output(
|
||||
['bash', 'bash_commands/connect_sound.sh', tmp_dir_name, audio_files[0]['file']])
|
||||
print('[+] Create final podcast - done')
|
||||
self.progress_bar.setValue(100)
|
||||
|
||||
dialog_done = self.create_custom_dialog(title="Informacja", msg="Zakończono generowanie podcastu.")
|
||||
dialog_done.exec_()
|
||||
self.progress_bar.setValue(0)
|
||||
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()
|
||||
|
164
src/python/classes/preview_creator_dialog.py
Normal 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))
|
@ -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)
|
@ -4,6 +4,7 @@ from PyQt5.QtWidgets import QApplication, QAbstractSlider, QSizePolicy, QSlider,
|
||||
|
||||
|
||||
class Communicate(QObject):
|
||||
"""Class to connect classes by signals"""
|
||||
range_changed = pyqtSignal(int, int)
|
||||
|
||||
|
||||
@ -22,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)
|
||||
@ -29,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."""
|
||||
@ -48,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
|
||||
@ -70,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))
|
||||
@ -104,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)
|
||||
@ -115,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
|
||||
@ -133,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()
|
||||
@ -149,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()
|
||||
|
87
src/python/classes/video_player_dialog.py
Normal 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()
|
@ -14,7 +14,8 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
MainWindow.setObjectName("MainWindow")
|
||||
MainWindow.resize(554, 745)
|
||||
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)
|
||||
@ -265,12 +266,17 @@ class Ui_MainWindow(object):
|
||||
self.progress_bar.setProperty("value", 24)
|
||||
self.progress_bar.setObjectName("progress_bar")
|
||||
self.verticalLayout.addWidget(self.progress_bar)
|
||||
self.log_label = QtWidgets.QLabel(self.central_widget)
|
||||
self.log_label.setText("")
|
||||
self.log_label.setObjectName("log_label")
|
||||
self.verticalLayout.addWidget(self.log_label)
|
||||
self.h_line.raise_()
|
||||
self.h_line_2.raise_()
|
||||
self.threshold_slider.raise_()
|
||||
self.h_line_3.raise_()
|
||||
self.check_box_connected_channels.raise_()
|
||||
self.progress_bar.raise_()
|
||||
self.log_label.raise_()
|
||||
MainWindow.setCentralWidget(self.central_widget)
|
||||
self.menu_bar = QtWidgets.QMenuBar(MainWindow)
|
||||
self.menu_bar.setGeometry(QtCore.QRect(0, 0, 554, 32))
|
||||
|
89
src/python/ui/preview_creator_dialog_ui.py
Normal 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_())
|
@ -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_())
|
110
src/python/ui/video_player_dialog_ui.py
Normal 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_())
|
@ -1,14 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"sourceMap": true,
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"allowJs": false,
|
||||
"strictNullChecks": true,
|
||||
"esModuleInterop": true,
|
||||
"outDir": "build"
|
||||
}
|
||||
}
|
26
window.ts
@ -1,26 +0,0 @@
|
||||
export default class Window {
|
||||
length: number;
|
||||
buffer: number[] = [];
|
||||
constructor(length: number) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
push(element: number) {
|
||||
if (this.buffer.length == this.length) {
|
||||
this.buffer.shift();
|
||||
}
|
||||
this.buffer.push(element);
|
||||
}
|
||||
|
||||
sum() {
|
||||
return this.buffer.reduce((a, b) => a + b, 0);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.buffer = [];
|
||||
}
|
||||
|
||||
isFull() {
|
||||
return this.buffer.length == this.length;
|
||||
}
|
||||
}
|