401 Commits

Author SHA1 Message Date
Akash Bora
a964ecf891 added new UI for python version
Now python users can also enjoy the easy UI
2022-07-18 17:35:46 +05:30
Akash Bora
7933558b15 Delete Python Version directory 2022-07-18 17:25:32 +05:30
Akash Bora
ce394fcd90 Delete test 2022-07-18 17:14:46 +05:30
Akash Bora
2150cd6019 Add files via upload 2022-07-18 17:14:33 +05:30
Akash Bora
b368dfc9c7 Create test 2022-07-18 17:13:06 +05:30
Akash Bora
816d1150bd Removed older versions 2022-07-18 17:04:47 +05:30
Akash Bora
1d45e22e55 Update Readme.md 2022-07-02 13:36:10 +05:30
Akash Bora
9755263e6e Update Readme.md 2022-07-02 13:35:09 +05:30
Akash Bora
8e4ddc83e9 Update Readme.md 2022-06-24 12:12:25 +05:30
Akash Bora
cfdb269b1e Update Readme.md 2022-06-20 20:01:05 +05:30
Akash Bora
6c4823fe81 Update Readme.md 2022-06-20 19:58:17 +05:30
Akash Bora
2e45e67162 Update Readme.md 2022-06-19 23:31:53 +05:30
Akash Bora
f7c62a5944 Update Readme.md 2022-06-19 23:26:41 +05:30
Akash Bora
18b043f4be Update Readme.md 2022-06-19 23:24:51 +05:30
Akash Bora
684f036fc7 Update Readme.md 2022-06-19 23:23:04 +05:30
Akash Bora
4897db579b Delete Demos.md 2022-06-19 23:20:28 +05:30
Akash Bora
420ff634a6 Update Readme.md 2022-06-19 23:18:58 +05:30
Akash Bora
2dda202bf2 Update Readme.md 2022-06-19 23:09:52 +05:30
Akash Bora
5e0183ccdc Update Readme.md 2022-06-19 23:05:34 +05:30
Akash Bora
f4dddd98be Update Readme.md 2022-06-19 22:44:52 +05:30
Akash Bora
3ce6cfdbc7 Update Readme.md 2022-06-19 22:44:08 +05:30
Akash Bora
6ef19a1abc Update Demos.md 2022-06-11 15:51:35 +05:30
Akash Bora
e9506e15d9 Update Demos.md 2022-06-10 20:08:16 +05:30
Akash Bora
ad210e74d5 Update Demos.md 2022-06-10 20:07:42 +05:30
Akash Bora
227edad13b Update Readme.md 2022-05-25 13:21:24 +05:30
Akash Bora
c815190585 Update Demos.md 2022-05-21 11:37:55 +05:30
Akash Bora
95181d47ca Update Readme.md 2022-05-16 13:32:48 +05:30
Akash Bora
7e4d5f7de2 Update Demos.md 2022-05-16 13:23:24 +05:30
Akash Bora
a22762a278 Update Demos.md 2022-05-16 13:18:56 +05:30
Akash Bora
4c079e9082 Update Readme.md 2022-05-16 12:56:30 +05:30
Akash Bora
68729edfce Update Readme.md 2022-05-15 13:58:11 +05:30
Akash Bora
e7deabc4f9 Update Readme.md 2022-05-15 13:55:00 +05:30
Akash Bora
0d55f2e986 Update LICENSE 2022-05-15 12:33:42 +05:30
Akash Bora
32fef121c2 Update Readme.md 2022-05-15 12:33:05 +05:30
Akash Bora
5698e82263 Update Readme.md 2022-05-15 12:32:29 +05:30
Akash Bora
4eff80cb69 Update Readme.md 2022-05-14 15:08:39 +05:30
Akash Bora
b010bbbcf7 Update ReadmeforPython.txt 2022-05-14 14:13:15 +05:30
Akash Bora
17ad34dc0b Update Readme.md 2022-05-14 14:03:06 +05:30
Akash Bora
e3d0d4b7fd Delete Datamosher Pro.py 2022-05-14 13:53:49 +05:30
Akash Bora
742d2e2d07 Add files via upload 2022-05-14 13:53:10 +05:30
Akash Bora
eb17df87a9 Update Readme.md 2022-05-14 13:43:57 +05:30
Akash Bora
b998857839 Update Readme.md 2022-05-14 13:43:29 +05:30
Akash Bora
b2e1c09d9f Update Readme.md 2022-05-14 13:39:37 +05:30
Akash Bora
80eb097737 Update Readme.md 2022-05-14 13:38:47 +05:30
Akash Bora
ab0210218a Update Demos.md 2022-05-08 21:29:49 +05:30
Akash Bora
6a59545302 Update Demos.md 2022-05-08 19:36:51 +05:30
Akash Bora
f3cf028196 Update Readme.md 2022-05-03 12:36:13 +05:30
Akash Bora
cc61e38c44 Update Demos.md 2022-05-03 12:33:05 +05:30
Akash Bora
ef73387c3f Update Demos.md 2022-05-03 12:18:42 +05:30
Akash Bora
245b677b36 Update Demos.md 2022-05-02 19:37:03 +05:30
Akash Bora
3d73ad05e2 Update Readme.md 2022-04-30 16:30:29 +05:30
Akash Bora
d3f1decbc1 Update Demos.md 2022-04-26 14:29:37 +05:30
Akash Bora
13f136ece5 Update Demos.md 2022-04-26 13:09:20 +05:30
Akash Bora
dfab621710 Update Demos.md 2022-04-26 13:07:19 +05:30
Akash Bora
391d5320ca Update Readme.md 2022-04-26 11:54:37 +05:30
Akash Bora
b771ce2b8f Update Readme.md 2022-04-26 11:51:06 +05:30
Akash Bora
f5cfb2499a Update Readme.md 2022-04-26 11:34:59 +05:30
Akash Bora
969d2d4a57 Add files via upload 2022-04-26 11:32:38 +05:30
Akash Bora
69afe9c5d3 Delete Datamosher Pro.py 2022-04-26 11:31:35 +05:30
Akash Bora
6d745b8c06 Add files via upload 2022-04-26 11:28:56 +05:30
Akash Bora
4d91f7751a Delete Datamosher Pro.py 2022-04-26 11:25:41 +05:30
Akash Bora
f42675f9d2 Update Demos.md 2022-04-25 19:04:01 +05:30
Akash Bora
b1f1b895c5 Update Readme.md 2022-04-23 13:58:20 +05:30
Akash Bora
fbd9bdafc2 Update Demos.md 2022-04-23 13:57:01 +05:30
Akash Bora
f2681f2618 Update Demos.md 2022-04-22 20:34:02 +05:30
Akash Bora
61972e7c57 Update Readme.md 2022-04-22 18:27:09 +05:30
Akash Bora
ce2b1ae6bd Update Readme.md 2022-04-22 18:26:56 +05:30
Akash Bora
1f17293186 Update Readme.md 2022-04-22 18:26:19 +05:30
Akash Bora
3d9caefb43 Update Datamosher Pro.py 2022-04-22 16:03:19 +05:30
Akash Bora
83375c7434 Update Readme.md 2022-04-22 13:35:44 +05:30
Akash Bora
93880013fa Update Readme.md 2022-04-21 14:32:47 +05:30
Akash Bora
f2d234ec11 Update Demos.md 2022-04-21 14:31:39 +05:30
Akash Bora
e6c55b9044 Update Demos.md 2022-04-20 14:30:38 +05:30
Akash Bora
9327dd8d97 Update Demos.md 2022-04-19 21:53:43 +05:30
Akash Bora
74d7be4780 Update Readme.md 2022-03-30 16:22:14 +05:30
Akash Bora
34a09f838a Update Readme.md 2022-03-30 14:57:16 +05:30
Akash Bora
909f58cc7d Update Readme.md 2022-03-30 14:51:00 +05:30
Akash Bora
2eaed8f637 Update Readme.md 2022-03-30 09:19:28 +05:30
Akash Bora
60ae44dda2 Update Readme.md 2022-03-30 09:18:43 +05:30
Akash Bora
09665d4de3 Update Readme.md 2022-03-30 09:08:14 +05:30
Akash Bora
2e54e9c591 Update Readme.md 2022-03-30 09:05:33 +05:30
Akash Bora
ca0ccf77a1 Update Readme.md 2022-03-30 09:05:18 +05:30
Akash Bora
24ff4160c3 Update Readme.md 2022-03-29 16:54:13 +05:30
Akash Bora
78c9ef647e Update Demos.md 2022-03-29 16:48:37 +05:30
Akash Bora
cf6f49037e Update Demos.md 2022-03-28 15:30:11 +05:30
Akash Bora
98f40a5911 Update Readme.md 2022-03-27 18:22:29 +05:30
Akash Bora
f6958a7e9b Update Readme.md 2022-03-27 18:15:07 +05:30
Akash Bora
e05a97d6e3 Update Readme.md 2022-03-27 18:12:35 +05:30
Akash Bora
598289a895 Update Demos.md 2022-03-27 17:35:40 +05:30
Akash Bora
73544c5b3f Update Readme.md 2022-03-25 19:06:56 +05:30
Akash Bora
9414d2b946 Update Demos.md 2022-03-25 18:58:45 +05:30
Akash Bora
e0ffc33e26 Update Readme.md 2022-03-25 15:35:07 +05:30
Akash Bora
4546ecee13 Update Demos.md 2022-03-22 21:06:39 +05:30
Akash Bora
7e06b2f124 Update Demos.md 2022-03-22 21:06:04 +05:30
Akash Bora
2d09c8bac8 Update ReadmeforPython.txt 2022-03-22 16:36:14 +05:30
Akash Bora
9e8dd3d285 Update Readme.md 2022-03-22 16:11:52 +05:30
Akash Bora
e65d30f2a5 Add files via upload 2022-03-22 15:56:40 +05:30
Akash Bora
497a9f7d99 Delete Datamosher Pro v1.6.1.py 2022-03-22 15:56:21 +05:30
Akash Bora
1ed2d4aab5 Update Demos.md 2022-03-21 21:40:03 +05:30
Akash Bora
3bde81d967 Update Demos.md 2022-03-21 21:39:00 +05:30
Akash Bora
6f30e45057 Update Readme.md 2022-03-15 21:46:33 +05:30
Akash Bora
73e2b59ff2 Update ReadmeforPython.txt 2022-03-14 18:24:30 +05:30
Akash Bora
c5629a73e2 Update Readme.md 2022-03-14 18:15:02 +05:30
Akash Bora
ea51fd9900 Update Readme.md 2022-03-14 17:56:39 +05:30
Akash Bora
5989c8653f Update Readme.md 2022-03-14 17:55:40 +05:30
Akash Bora
3b3de85fa2 Update ReadmeforPython.txt 2022-03-14 17:45:53 +05:30
Akash Bora
b440b215de Update Readme.txt 2022-03-14 17:42:11 +05:30
Akash Bora
74a9bf8336 Add files via upload 2022-03-14 17:37:35 +05:30
Akash Bora
a1a54dbf7e Delete Datamosher Pro v1.6.1.py 2022-03-14 17:33:31 +05:30
Akash Bora
b552c1ce54 Delete ffglitch.7z 2022-03-14 16:56:58 +05:30
Akash Bora
21ca9e6fea Update Readme.txt 2022-03-14 16:47:36 +05:30
Akash Bora
d53a745704 Update Readme.md 2022-03-14 16:43:11 +05:30
Akash Bora
a36f132bbf Update Datamosher Pro v1.6.1.py 2022-03-14 16:41:57 +05:30
Akash Bora
2ecd7a8162 Update Readme.md 2022-03-14 16:27:45 +05:30
Akash Bora
725f9d74e4 Update Demos.md 2022-03-14 16:11:46 +05:30
Akash Bora
1d1d5998a8 Update Demos.md 2022-03-14 16:08:51 +05:30
Akash Bora
5184fc62bc Update Demos.md 2022-03-14 16:08:27 +05:30
Akash Bora
7921cdb4ab Update Demos.md 2022-03-14 16:07:23 +05:30
Akash Bora
7dd5d4b746 Create Demos.md 2022-03-14 16:05:12 +05:30
Akash Bora
80c206a5e0 Update Readme.md 2022-02-04 17:06:27 +05:30
Akash Bora
68907f3685 Update LICENSE 2022-02-02 20:25:27 +05:30
Akash Bora
4de266155a Update Readme.md 2022-02-02 20:24:57 +05:30
Akash Bora
c8a6506875 Update Readme.md 2022-02-01 21:07:22 +05:30
Akash Bora
2c9749bd77 Update Readme.md 2022-01-29 18:37:21 +05:30
Akash Bora
9dccaf17b6 Update Readme.md 2022-01-29 18:36:55 +05:30
Akash Bora
663ecf03df Update Readme.md 2022-01-29 15:52:14 +05:30
Akash Bora
914d93c238 Update Readme.md 2022-01-29 15:39:42 +05:30
Akash Bora
dced83ea8a Update Readme.md 2022-01-29 15:39:29 +05:30
Akash Bora
38ea10e4ac Update Readme.md 2022-01-29 15:39:10 +05:30
Akash Bora
55e0d418e3 Update Readme.md 2022-01-29 15:39:01 +05:30
Akash Bora
67303a840f Update Readme.md 2022-01-29 15:38:17 +05:30
Akash Bora
1d6b6e8cdd Update Readme.md 2022-01-29 15:37:48 +05:30
Akash Bora
a022842f28 Update Readme.md 2022-01-23 15:34:00 +05:30
Akash Bora
c4cf92f9e0 Update Readme.md 2022-01-23 15:33:36 +05:30
Akash Bora
0898daa4d5 Update Readme.md 2022-01-23 15:33:17 +05:30
Akash Bora
8cdc874866 Update Readme.md 2022-01-23 15:33:06 +05:30
Akash Bora
941238f4c2 Update Readme.md 2022-01-20 19:12:29 +05:30
Akash Bora
66f70f65aa Update Readme.md 2022-01-20 19:12:14 +05:30
Akash Bora
d658464ff0 Update Readme.md 2022-01-20 19:08:45 +05:30
Akash Bora
e477751d4d Update Readme.md 2022-01-20 19:08:05 +05:30
Akash Bora
6b4e16bf2b Update Readme.md 2022-01-20 19:07:42 +05:30
Akash Bora
cb84fe98c8 Update Readme.md 2022-01-20 19:06:31 +05:30
Akash Bora
b3c6e53217 Update Readme.md 2022-01-20 19:06:11 +05:30
Akash Bora
d22922cc9b Update Readme.md 2022-01-20 19:05:15 +05:30
Akash Bora
2c38299b99 Update Readme.md 2022-01-20 19:03:36 +05:30
Akash Bora
f41b8f164f Update Readme.md 2022-01-20 19:03:11 +05:30
Akash Bora
10a6ac81de Update Readme.md 2022-01-19 13:13:37 +05:30
Akash Bora
a6ed78aab2 Update Readme.md 2022-01-19 13:10:57 +05:30
Akash Bora
dd651efb44 Update Readme.md 2022-01-19 13:10:23 +05:30
Akash Bora
5c3185c8a4 Update Readme.md 2022-01-19 13:10:07 +05:30
Akash Bora
3ced022980 Update Readme.md 2022-01-18 21:59:03 +05:30
Akash Bora
bd7e2a76ef Update Readme.md 2022-01-18 21:58:37 +05:30
Akash Bora
8c5df70e86 Update Readme.md 2022-01-18 21:51:20 +05:30
Akash Bora
6667576e18 Update Readme.md 2022-01-18 21:50:37 +05:30
Akash Bora
a67bde6ddc Update Readme.md 2022-01-18 21:44:45 +05:30
Akash Bora
67e690433f Update Readme.md 2022-01-18 21:44:19 +05:30
Akash Bora
dab12e581c Update Readme.md 2022-01-18 21:41:02 +05:30
Akash Bora
12f053cc88 Update Readme.md 2022-01-18 21:40:47 +05:30
Akash Bora
2f1addb3d0 Update Readme.md 2022-01-18 21:40:30 +05:30
Akash Bora
631bc45b16 Update Readme.md 2022-01-18 21:40:19 +05:30
Akash Bora
372bad379c Update Readme.md 2022-01-18 21:39:45 +05:30
Akash Bora
e21e642363 Update Readme.md 2022-01-18 21:39:03 +05:30
Akash Bora
296ba5972a Update Readme.md 2022-01-18 21:38:30 +05:30
Akash Bora
b1903c20e3 Update Readme.md 2022-01-18 21:38:12 +05:30
Akash Bora
c4ce269ceb Update Readme.md 2022-01-18 21:38:01 +05:30
Akash Bora
1d47f11bcc Update Readme.md 2022-01-18 21:37:47 +05:30
Akash Bora
0d54c810a2 Update Readme.md 2022-01-18 21:35:26 +05:30
Akash Bora
b61235313f Update Readme.md 2022-01-18 21:35:08 +05:30
Akash Bora
38e0759c8d Update Readme.md 2022-01-18 21:34:56 +05:30
Akash Bora
fdc3ee232a Update Readme.md 2022-01-18 21:30:31 +05:30
Akash Bora
6fc14f240c Update Readme.md 2022-01-18 21:28:45 +05:30
Akash Bora
7a7e40bdc0 Update Readme.md 2022-01-18 21:28:16 +05:30
Akash Bora
1bab4ca73b Update Readme.md 2022-01-18 21:26:35 +05:30
Akash Bora
45e7191482 Update Readme.md 2022-01-18 21:15:57 +05:30
Akash Bora
2261882d4d Update Readme.md 2022-01-18 21:15:43 +05:30
Akash Bora
e0cd9ae593 Update Readme.md 2022-01-18 21:12:35 +05:30
Akash Bora
d3580a3e95 Update Readme.md 2022-01-18 21:01:34 +05:30
Akash Bora
63fa5736c7 Update Readme.md 2022-01-18 21:00:58 +05:30
Akash Bora
60129a0c58 Update Readme.md 2022-01-18 20:59:26 +05:30
Akash Bora
b839cdd0e3 Update Readme.md 2022-01-18 20:59:11 +05:30
Akash Bora
b0d9407839 Update Readme.md 2022-01-18 20:55:32 +05:30
Akash Bora
7a4a3cae3b Update Readme.md 2022-01-18 20:55:13 +05:30
Akash Bora
fb83ced395 Update Readme.md 2022-01-18 20:54:34 +05:30
Akash Bora
e5034fa829 Update Readme.md 2022-01-18 20:53:54 +05:30
Akash Bora
118c0c31cd Update Readme.md 2022-01-18 20:45:41 +05:30
Akash Bora
9b9a99ccc0 Update Readme.md 2022-01-18 20:45:24 +05:30
Akash Bora
86b52c0ade Update Readme.md 2022-01-18 20:44:54 +05:30
Akash Bora
ac7fc06c91 Update Readme.md 2022-01-18 20:43:55 +05:30
Akash Bora
65e9762904 Update Readme.md 2022-01-18 20:41:46 +05:30
Akash Bora
a62ca393bb Update Readme.md 2022-01-18 20:41:28 +05:30
Akash Bora
432444bb54 Update Readme.md 2022-01-18 20:41:06 +05:30
Akash Bora
fbe3095197 Update Readme.md 2022-01-18 20:24:04 +05:30
Akash Bora
bae79d26a2 Update Readme.md 2022-01-18 20:23:45 +05:30
Akash Bora
72db4853b1 Update Readme.md 2022-01-18 20:23:24 +05:30
Akash Bora
14d49ebf49 Update Readme.md 2022-01-18 20:23:08 +05:30
Akash Bora
242dbdf2ca Update Readme.md 2022-01-18 20:20:28 +05:30
Akash Bora
4ba7019504 Update Readme.md 2022-01-18 20:20:14 +05:30
Akash Bora
7452e5f25b Update Readme.md 2022-01-18 20:20:00 +05:30
Akash Bora
85cdf9ce83 Update Readme.md 2022-01-18 20:17:08 +05:30
Akash Bora
f318f209aa Update Readme.md 2022-01-18 20:12:39 +05:30
Akash Bora
955c4649f5 Update Readme.md 2022-01-18 20:12:26 +05:30
Akash Bora
9af1f75d09 Update Readme.md 2022-01-14 22:02:42 +05:30
Akash Bora
e37d32940d Update Readme.md 2022-01-14 22:01:57 +05:30
Akash Bora
e9645dd93f Update Readme.md 2022-01-14 19:57:00 +05:30
Akash Bora
d8c9daee78 Update Readme.md 2022-01-14 19:27:26 +05:30
Akash Bora
d9eedaa6dd Add files via upload 2022-01-14 19:26:56 +05:30
Akash Bora
4ea1a79983 Delete Datamosher Pro v1.6.py 2022-01-14 19:26:19 +05:30
Akash Bora
c00e7c6da5 Update Readme.md 2022-01-14 19:24:10 +05:30
Akash Bora
404c4daeb7 Update Readme.md 2022-01-14 19:23:48 +05:30
Akash Bora
f487b45e6c Update Readme.md 2022-01-14 19:23:28 +05:30
Akash Bora
75008bb731 Update Readme.md 2022-01-14 19:22:24 +05:30
Akash Bora
091ffce77e Update Readme.md 2022-01-14 19:22:00 +05:30
Akash Bora
0fcb9f94a3 Update Readme.md 2022-01-14 19:16:55 +05:30
Akash Bora
e8331d0cda Update Readme.md 2022-01-14 19:15:55 +05:30
Akash Bora
23ecb5dd17 Update Readme.md 2022-01-14 19:15:36 +05:30
Akash Bora
46ffc00a9b Update Readme.md 2022-01-14 19:14:55 +05:30
Akash Bora
3152afc610 Update Readme.md 2022-01-14 19:14:25 +05:30
Akash Bora
c45e9108fb Update Readme.md 2022-01-14 19:05:42 +05:30
Akash Bora
a27e4f1389 Update Readme.md 2022-01-14 16:41:16 +05:30
Akash Bora
b8a192336f Update Readme.md 2022-01-14 13:44:59 +05:30
Akash Bora
6a1247c108 Update ReadmeforPython.txt 2022-01-13 19:58:24 +05:30
Akash Bora
ece8f5b2f0 Delete Datamosher Pro v1.5.py 2022-01-13 19:58:05 +05:30
Akash Bora
721125045e Add files via upload 2022-01-13 19:57:54 +05:30
Akash Bora
690af0c2a0 Update Readme.md 2022-01-13 19:47:02 +05:30
Akash Bora
4b8f1892fa Update Readme.md 2022-01-13 19:34:29 +05:30
Akash Bora
1193b576e1 Update Readme.md 2022-01-13 19:34:14 +05:30
Akash Bora
94560f774e Update Readme.md 2022-01-13 18:23:34 +05:30
Akash Bora
63076e5312 Update Readme.md 2022-01-13 18:15:06 +05:30
Akash Bora
de0e5d19dc Update Readme.md 2022-01-13 17:33:58 +05:30
Akash Bora
777a269a39 Update Readme.md 2022-01-11 18:37:00 +05:30
Akash Bora
f47fd83c62 Update Readme.md 2022-01-11 18:36:46 +05:30
Akash Bora
43a3a8248e Update Readme.md 2022-01-11 18:36:34 +05:30
Akash Bora
89e614a106 Update Readme.md 2022-01-11 18:35:41 +05:30
Akash Bora
b0f496a9cb Update Readme.md 2022-01-11 18:22:02 +05:30
Akash Bora
3d41bd09d0 Update Readme.md 2022-01-11 18:05:39 +05:30
Akash Bora
0855485798 Update Readme.md 2022-01-11 18:05:20 +05:30
Akash Bora
0481cd8837 Update Readme.md 2022-01-11 17:53:28 +05:30
Akash Bora
4cdd5cbea0 Update Readme.md 2022-01-11 17:52:42 +05:30
Akash Bora
8dfb2f0376 Update Readme.md 2022-01-11 17:49:41 +05:30
Akash Bora
8ec7a3491c Update Readme.md 2022-01-11 17:37:01 +05:30
Akash Bora
ca201e79b1 Update Readme.md 2022-01-08 21:15:08 +05:30
Akash Bora
a315b0591e Update Readme.md 2022-01-08 18:58:11 +05:30
Akash Bora
33002cae22 Update Readme.md 2022-01-08 18:57:33 +05:30
Akash Bora
6845c5c238 Update Readme.md 2022-01-08 18:57:07 +05:30
Akash Bora
da23ee6ba9 Update Readme.md 2022-01-08 18:56:57 +05:30
Akash Bora
59a17f4e90 Update Readme.md 2022-01-08 18:56:46 +05:30
Akash Bora
f5887de50a Update Readme.md 2022-01-08 18:46:13 +05:30
Akash Bora
4fcf04b6d7 Update Readme.md 2022-01-08 18:45:33 +05:30
Akash Bora
146b5622e0 Update Readme.md 2022-01-08 18:44:30 +05:30
Akash Bora
dfb4fc123f Update Readme.md 2022-01-08 18:44:15 +05:30
Akash Bora
7f16b44b5d Update Readme.md 2022-01-08 18:23:29 +05:30
Akash Bora
c6eaa2c9ae Update Readme.md 2022-01-08 18:23:10 +05:30
Akash Bora
c393df510e Update Readme.md 2022-01-08 18:22:05 +05:30
Akash Bora
a6fa8335c4 Update Readme.md 2022-01-08 18:15:56 +05:30
Akash Bora
b042077895 Update Readme.md 2022-01-08 18:15:36 +05:30
Akash Bora
784ae26471 Update Readme.md 2022-01-08 18:03:17 +05:30
Akash Bora
2cbe7e46c2 Update Readme.md 2022-01-08 18:00:21 +05:30
Akash Bora
8dbb97b8a1 Update Readme.md 2022-01-08 17:59:43 +05:30
Akash Bora
de1b4119e8 Update Readme.md 2022-01-08 17:59:00 +05:30
Akash Bora
cdf76fc39c Update Readme.md 2022-01-08 17:57:23 +05:30
Akash Bora
888ad565a3 Update Readme.md 2022-01-08 17:56:58 +05:30
Akash Bora
c7e07c0657 Update Readme.md 2022-01-08 17:55:32 +05:30
Akash Bora
bd178ed811 Update Readme.md 2022-01-08 17:52:28 +05:30
Akash Bora
73920b751e Update Readme.md 2022-01-08 17:44:04 +05:30
Akash Bora
e068834c98 Update Readme.md 2022-01-08 17:43:06 +05:30
Akash Bora
40ee09903a Update Readme.md 2022-01-08 17:35:21 +05:30
Akash Bora
fb4e72791b Update Readme.md 2022-01-08 17:30:38 +05:30
Akash Bora
0be779eb72 Update Readme.md 2022-01-08 17:09:59 +05:30
Akash Bora
6b444f6b32 Update Readme.md 2022-01-08 17:08:53 +05:30
Akash Bora
568ecd2f6f Update Readme.md 2022-01-08 17:07:57 +05:30
Akash Bora
3fea9fd251 Update Readme.md 2022-01-08 17:07:29 +05:30
Akash Bora
13497e6898 Update Readme.md 2022-01-08 17:07:05 +05:30
Akash Bora
c84d8624cc Update Readme.md 2022-01-08 17:06:31 +05:30
Akash Bora
3d310828fb Update Readme.md 2022-01-08 12:58:33 +05:30
Akash Bora
1ccb289ced Update Readme.md 2022-01-08 12:44:38 +05:30
Akash Bora
76df62de23 Update Readme.md 2022-01-08 12:44:09 +05:30
Akash Bora
2a7fe5a557 Update Readme.md 2022-01-08 12:43:08 +05:30
Akash Bora
d4cb468c37 Update Readme.md 2022-01-08 12:04:09 +05:30
Akash Bora
ce01397a9d Update Readme.md 2022-01-03 19:04:56 +05:30
Akash Bora
45ddf02c07 Update Readme.md 2022-01-03 19:04:21 +05:30
Akash Bora
292c592b71 Update Readme.md 2022-01-03 19:03:49 +05:30
Akash Bora
ee6f6b888e Update Readme.md 2022-01-03 18:56:25 +05:30
Akash Bora
fd9c509568 Update Readme.md 2022-01-03 18:11:48 +05:30
Akash Bora
5b1b29f4d7 Update Readme.md 2022-01-03 18:11:25 +05:30
Akash Bora
76824887b3 Update Readme.md 2022-01-03 18:10:08 +05:30
Akash Bora
f6861ffaca Update Readme.md 2022-01-03 18:08:35 +05:30
Akash Bora
323039c372 Update Readme.md 2022-01-03 18:08:10 +05:30
Akash Bora
89af07fffc Update Datamosher Pro v1.5.py 2022-01-03 17:57:07 +05:30
Akash Bora
ba4482d847 Update Readme.md 2022-01-03 17:52:57 +05:30
Akash Bora
35061a45f0 Update Readme.md 2022-01-03 17:40:22 +05:30
Akash Bora
cddfd13876 Update Readme.md 2022-01-03 17:36:34 +05:30
Akash Bora
6997be3222 Update Readme.md 2022-01-03 17:36:21 +05:30
Akash Bora
4c75c57702 Update Readme.md 2022-01-03 17:36:00 +05:30
Akash Bora
889296e843 Update Readme.md 2022-01-03 17:28:58 +05:30
Akash Bora
465f1f9f70 Update Readme.md 2022-01-03 17:28:31 +05:30
Akash Bora
1a6801b8dc Update Readme.md 2022-01-03 17:26:39 +05:30
Akash Bora
fa9c3ec524 Update Readme.md 2022-01-03 17:25:21 +05:30
Akash Bora
4124085855 Update Readme.md 2022-01-03 17:24:15 +05:30
Akash Bora
5c5c08709e Update Readme.md 2022-01-03 17:22:55 +05:30
Akash Bora
9b4be683bb Update Readme.md 2022-01-03 17:21:53 +05:30
Akash Bora
e151d35141 Update Readme.md 2022-01-03 17:21:11 +05:30
Akash Bora
c304307290 Update Readme.md 2022-01-03 17:20:15 +05:30
Akash Bora
567a418565 Update Readme.md 2022-01-03 17:19:54 +05:30
Akash Bora
6adaff1c3e Update Readme.md 2022-01-03 17:18:55 +05:30
Akash Bora
e8bfa4cff1 Update Readme.md 2022-01-03 17:15:47 +05:30
Akash Bora
c71290d3f7 Update Readme.md 2022-01-03 17:15:12 +05:30
Akash Bora
5c735ab872 Update Readme.md 2022-01-03 17:14:41 +05:30
Akash Bora
ae2aa0ac22 Update Readme.md 2022-01-03 17:14:18 +05:30
Akash Bora
32a49881c8 Update Readme.md 2022-01-03 17:13:56 +05:30
Akash Bora
3b73fc1e1e Update Readme.md 2022-01-03 17:13:07 +05:30
Akash Bora
b29e3de661 Update Readme.md 2022-01-03 17:12:47 +05:30
Akash Bora
8bd8d2bfe5 Update Readme.md 2022-01-03 17:11:53 +05:30
Akash Bora
a0878a4d58 Update Readme.md 2022-01-03 17:11:39 +05:30
Akash Bora
30d5ff4a18 Update Readme.md 2022-01-03 17:11:15 +05:30
Akash Bora
b4b5017cbb Update Readme.md 2022-01-03 17:10:36 +05:30
Akash Bora
bb3b473ed4 Update Readme.md 2022-01-03 17:09:48 +05:30
Akash Bora
20cbc47dd2 Update Readme.md 2022-01-03 17:08:45 +05:30
Akash Bora
bd80ab5abd Update Readme.md 2022-01-02 17:19:05 +05:30
Akash Bora
7fbe8154b3 Update Readme.md 2022-01-02 17:18:41 +05:30
Akash Bora
e4151cb699 Update Datamosher Pro v1.5.py 2021-12-29 14:25:24 +05:30
Akash Bora
d3bbddaecd Update Readme.md 2021-12-26 22:33:14 +05:30
Akascape
0cf4780339 Delete Download it for windows-64bit 2021-12-26 18:36:40 +05:30
Akascape
6fb9b76ba6 Update and rename Download it for windows-64bit.md to Download it for windows-64bit 2021-12-26 18:36:24 +05:30
Akascape
f2ed355c28 Update Download it for windows-64bit.md 2021-12-26 18:35:45 +05:30
Akascape
9d95636384 Update and rename Download it for windows-64bit to Download it for windows-64bit.md 2021-12-26 18:34:57 +05:30
Akascape
00a046d5d6 Rename Download it for windows-64bit.txt to Download it for windows-64bit 2021-12-26 18:34:18 +05:30
Akascape
b50cf4d8a2 Rename Download it for windows-64bit to Download it for windows-64bit.txt 2021-12-26 18:34:07 +05:30
Akascape
d62e227eb2 Update Download it for windows-64bit 2021-12-26 18:33:01 +05:30
Akascape
5accc347b7 Create Download it for windows-64bit 2021-12-26 18:31:12 +05:30
Akascape
7d93d7f5be Update Readme.md 2021-12-26 18:14:01 +05:30
Akascape
133cda7f6b Update Readme.md 2021-12-26 18:13:04 +05:30
Akascape
5ab58962da Update Readme.md 2021-12-21 21:08:05 +05:30
Akascape
7f417425e8 Update Readme.md 2021-12-21 21:07:41 +05:30
Akascape
d9cc58a8be Update Readme.md 2021-12-21 21:07:00 +05:30
Akascape
718d5bbf63 Update Readme.md 2021-12-21 21:05:52 +05:30
Akascape
a26a070c25 Update Readme.md 2021-12-21 21:05:04 +05:30
Akascape
f956caefaf Update Readme.md 2021-12-21 21:04:42 +05:30
Akascape
385c8ed9b6 Update Readme.md 2021-12-21 21:03:47 +05:30
Akascape
79c2d535e1 Update Readme.md 2021-12-21 21:02:18 +05:30
Akascape
8ac13ec9e3 Update Readme.md 2021-12-21 20:31:48 +05:30
Akascape
e56ebe748c Update Readme.md 2021-12-21 20:31:17 +05:30
Akascape
7d72a63073 Update Readme.md 2021-12-21 20:04:47 +05:30
Akascape
8555a1fe29 Update Readme.md 2021-12-21 19:59:43 +05:30
Akascape
415ba0fc40 Update Readme.md 2021-12-21 19:55:14 +05:30
Akascape
b4e93ea104 Update Readme.md 2021-12-21 19:39:28 +05:30
Akascape
d46cdc86df Update Readme.md 2021-12-21 19:38:27 +05:30
Akascape
dd21904f46 Update Readme.md 2021-12-21 19:37:29 +05:30
Akascape
0090d1e8f1 Update Datamosher Pro v1.5.py 2021-12-21 19:19:24 +05:30
Akascape
b402e87f06 Update Readme.md 2021-12-21 19:18:58 +05:30
Akascape
8c93d5cd8c Update Datamosher Pro v1.5.py 2021-12-21 19:13:05 +05:30
Akascape
c52e497b3e Delete Datamosher Pro v1.4.py 2021-12-21 19:07:11 +05:30
Akascape
b394070e7a Add files via upload 2021-12-21 19:06:59 +05:30
Akascape
628054648a Delete e 2021-12-21 19:06:28 +05:30
Akascape
e8868946ba Add files via upload 2021-12-21 19:06:00 +05:30
Akascape
87898fe269 Create e 2021-12-21 19:04:58 +05:30
Akascape
0b2a54d236 Delete Python Version/ffglitch/jscripts directory 2021-12-21 19:03:16 +05:30
Akascape
4c19db188b Create E 2021-12-21 19:02:58 +05:30
Akascape
3ed4a0e746 Update Readme.txt 2021-12-10 21:12:00 +05:30
Akascape
de9ecf5539 Update Readme.md 2021-12-10 21:09:09 +05:30
Akascape
8ac2af9d2b Update Readme.md 2021-12-10 21:08:14 +05:30
Akascape
3922a6272e Update Readme.md 2021-12-10 21:02:51 +05:30
Akascape
51591d1e62 Update Readme.md 2021-12-10 21:01:26 +05:30
Akascape
9f3050ebc9 Update Readme.md 2021-12-10 20:59:28 +05:30
Akascape
5c78c3a632 Update Readme.md 2021-12-10 20:58:36 +05:30
Akascape
0b36988881 Update Readme.md 2021-12-10 20:57:17 +05:30
Akascape
52aedf2721 Update Readme.md 2021-12-10 20:56:13 +05:30
Akascape
06205faac0 Update Readme.md 2021-12-10 20:53:39 +05:30
Akascape
af89678db5 Update Readme.md 2021-12-10 20:52:39 +05:30
Akascape
a126cf68b1 Update Readme.md 2021-12-10 20:51:44 +05:30
Akascape
386c5d8973 Update Readme.md 2021-12-10 20:49:59 +05:30
Akascape
d1d0ad47dd Update Readme.md 2021-12-10 20:41:02 +05:30
Akascape
33e1278333 Update Readme.md 2021-12-10 20:40:08 +05:30
Akascape
2b854a09d2 Update Readme.md 2021-12-10 20:38:41 +05:30
Akascape
4567c8042e Update Readme.md 2021-12-10 20:37:32 +05:30
Akascape
183fb198fb Update Readme.md 2021-12-10 20:37:10 +05:30
Akascape
f4e301a6b5 Update Readme.md 2021-12-10 20:35:46 +05:30
Akascape
e670021e04 Update Readme.md 2021-12-10 20:34:31 +05:30
Akascape
c1098c960b Update Readme.md 2021-11-17 19:38:42 +05:30
Akascape
6f44d65b13 Update Readme.md 2021-11-17 19:38:24 +05:30
Akascape
f8b10aa523 Update Readme.md 2021-11-17 19:37:38 +05:30
Akascape
f865c42f98 Update Readme.md 2021-11-17 19:36:56 +05:30
Akascape
e3df5d9812 Update Readme.md 2021-11-17 19:36:32 +05:30
Akascape
f6f9848213 Update Readme.md 2021-11-17 19:36:10 +05:30
Akascape
e5574256b9 Update Readme.md 2021-11-17 19:35:49 +05:30
Akascape
648f374869 Update Readme.md 2021-11-17 19:28:03 +05:30
Akascape
f57b0959f7 Update Readme.md 2021-11-17 19:17:37 +05:30
Akascape
2de6ccfd7d Update Readme.md 2021-11-17 18:53:10 +05:30
Akascape
713b273e48 Update Readme.md 2021-11-17 18:51:51 +05:30
Akascape
7ef337c060 Update Readme.md 2021-11-17 18:50:59 +05:30
Akascape
b05dadee5e Update Readme.md 2021-11-17 18:47:51 +05:30
Akascape
8a441e96b9 Add files via upload 2021-11-17 18:37:09 +05:30
Akascape
9e623c505c Add files via upload 2021-11-17 18:36:36 +05:30
Akascape
835b537aa8 Create Readme.txt 2021-11-17 18:23:38 +05:30
Akascape
d0e6a68abb Delete Assets.txt 2021-11-17 18:21:50 +05:30
Akascape
ed79147f9f Add files via upload 2021-11-17 18:21:30 +05:30
Akascape
418e2eb89c Create Assets.txt 2021-11-17 18:20:54 +05:30
Akascape
3cf14faf8d Update ReadmeforPython.txt 2021-11-17 18:18:30 +05:30
Akascape
cf324ee4d4 Delete label.png 2021-11-17 18:17:13 +05:30
Akascape
a694f25d3a Delete icon.ico 2021-11-17 18:17:07 +05:30
Akascape
37e3b59a27 Delete button.png 2021-11-17 18:16:59 +05:30
Akascape
1609143b12 Delete Datamosher Pro v1.3.py 2021-11-17 18:16:39 +05:30
40 changed files with 2246 additions and 869 deletions

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021 Akascape
Copyright (c) 2022 Akash Bora
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

View File

@@ -0,0 +1 @@
1.8

View File

@@ -0,0 +1,154 @@
#Author: Akash Bora
import os, shutil, subprocess, random, json
from pathlib import Path
import numpy as np
DIRPATH = Path(os.path.dirname(os.path.realpath(__file__)))
ffgac=str(DIRPATH.parent.parent).replace(os.sep, '/')+"/FFglitch/ffgac"
ffedit=str(DIRPATH.parent.parent).replace(os.sep, '/')+"/FFglitch/ffedit"
def library(input_video, output, mode, extract_from="", fluidity=0, size=0, s=0, e=0, vh=0, gop=1000):
def get_vectors(input_video):
subprocess.call(f'"{ffgac}" -i "{input_video}" -an -mpv_flags +nopimb+forcemv -qscale:v 0 -g "{gop}"' +
' -vcodec mpeg2video -f rawvideo -y tmp.mpg', shell=True)
subprocess.call(f'"{ffedit}" -i tmp.mpg -f mv:0 -e tmp.json', shell=True)
os.remove('tmp.mpg')
f = open('tmp.json', 'r')
raw_data = json.load(f)
f.close()
os.remove('tmp.json')
frames = raw_data['streams'][0]['frames']
vectors = []
for frame in frames:
try:
vectors.append(frame['mv']['forward'])
except:
vectors.append([])
return vectors
def apply_vectors(vectors, input_video, output_video, method='add'):
subprocess.call(f'"{ffgac}" -i "{input_video}" -an -mpv_flags +nopimb+forcemv -qscale:v 0 -g "{gop}"' +
' -vcodec mpeg2video -f rawvideo -y tmp.mpg', shell=True)
to_add = '+' if method == 'add' else ''
script_path = 'apply_vectors.js'
script_contents = '''
var vectors = [];
var n_frames = 0;
function glitch_frame(frame) {
let fwd_mvs = frame["mv"]["forward"];
if (!fwd_mvs || !vectors[n_frames]) {
n_frames++;
return;
}
for ( let i = 0; i < fwd_mvs.length; i++ ) {
let row = fwd_mvs[i];
for ( let j = 0; j < row.length; j++ ) {
let mv = row[j];
try {
mv[0] ''' + to_add + '''= vectors[n_frames][i][j][0];
mv[1] ''' + to_add + '''= vectors[n_frames][i][j][1];
} catch {}
}
}
n_frames++;
}
'''
with open(script_path, 'w') as f:
f.write(script_contents.replace('var vectors = [];', f'var vectors = {json.dumps(vectors)};'))
subprocess.call(f'"{ffedit}" -i tmp.mpg -f mv -s "{script_path}" -o "{output_video}"', shell=True)
os.remove('apply_vectors.js')
os.remove('tmp.mpg')
def shuffle(output):
if os.path.isdir("cache"):
shutil.rmtree("cache")
os.mkdir("cache")
base=os.path.basename(input_video)
fin="cache/"+base[:-4]+".mpg"
subprocess.call(f'"{ffgac}" -i "{input_video}" -an -vcodec mpeg2video -f rawvideo -mpv_flags +nopimb -qscale:v 6 -r 30 -g "{gop}" -y "{fin}"')
os.mkdir("cache/raws")
framelist=[]
subprocess.call(f'"{ffgac}" -i "{fin}" -vcodec copy cache/raws/frames_%04d.raw')
frames=os.listdir("cache/raws")
siz=size
framelist.extend(frames)
chunked_list=[]
chunk_size=siz
for i in range(0, len(framelist), chunk_size):
chunked_list.append(framelist[i:i+chunk_size])
random.shuffle(chunked_list)
framelist.clear()
for k in frames[0:siz]:
framelist.append(k)
for i in chunked_list:
for j in i:
if not j in framelist:
framelist.append(j)
out_data = b''
for fn in framelist:
with open("cache/raws/"+fn, 'rb') as fp:
out_data += fp.read()
with open(output, 'wb+') as fp:
fp.write(out_data)
fp.close()
shutil.rmtree("cache")
def rise(output):
if os.path.isdir("cache"):
shutil.rmtree("cache")
os.mkdir("cache")
base=os.path.basename(input_video)
fin="cache/"+base[:-4]+".mpg"
qua=''
subprocess.call(f'"{ffgac}" -i "{input_video}" -an -vcodec mpeg2video -f rawvideo -mpv_flags +nopimb -qscale:v 6 -r 30 -g "{gop}" -y "{fin}"')
os.mkdir("cache/raws")
framelist=[]
subprocess.call(f'"{ffgac}" -i "{fin}" -vcodec copy cache/raws/frames_%04d.raw')
kil=e
po=s
if po==0:
po=1
frames=os.listdir("cache/raws")
for i in frames[po:(po+kil)]:
os.remove("cache/raws/"+i)
frames.clear()
frames=os.listdir("cache/raws")
framelist.extend(frames)
out_data = b''
for fn in framelist:
with open("cache/raws/"+fn, 'rb') as fp:
out_data += fp.read()
with open(output, 'wb') as fp:
fp.write(out_data)
fp.close()
shutil.rmtree("cache")
def average(frames):
if not frames:
return []
return np.mean(np.array([x for x in frames if x != []]), axis=0).tolist()
def fluid(frames):
average_length = fluidity
if average_length==1:
average_length=2
return [average(frames[i + 1 - average_length: i + 1]) for i in range(len(frames))]
def movement(frames):
for frame in frames:
if not frame:
continue
for row in frame:
for col in row:
col[vh] = 0
return frames
if(mode==1):
transfer_to=input_video
vectors = []
if extract_from:
vectors = get_vectors(extract_from)
if transfer_to == '':
with open(output, 'w') as f:
json.dump(vectors, f)
apply_vectors(vectors, transfer_to, output)
elif(mode==2):
apply_vectors(movement(get_vectors(input_video)), input_video, output, method='')
elif(mode==3):
apply_vectors(fluid(get_vectors(input_video)), input_video, output, method='')
elif(mode==4):
shuffle(output)
elif(mode==5):
rise(output)

View File

@@ -0,0 +1,15 @@
#Author: Akash Bora
import os, subprocess
from pathlib import Path
DIRPATH = Path(os.path.dirname(os.path.realpath(__file__)))
ffgac=str(DIRPATH.parent.parent).replace(os.sep, '/')+"/FFglitch/ffgac"
ffedit=str(DIRPATH.parent.parent).replace(os.sep, '/')+"/FFglitch/ffedit"
def mosh(input_video, output_video, mode, effect='', scriptfile='', gop=1000):
if mode==1:
script_path=scriptfile
elif mode==2:
script_path=str(DIRPATH).replace(os.sep, '/')+"/jscripts/"+effect+".js"
subprocess.call(f'"{ffgac}" -i "{input_video}" -an -mpv_flags +nopimb+forcemv -qscale:v 0 -b:v 20M -minrate 20M -maxrate 20M -bufsize 2M -g "{gop}"' +
' -vcodec mpeg2video -f rawvideo -y tmp.mpg', shell=True)
subprocess.call(f'"{ffedit}" -i tmp.mpg -f mv -s "{script_path}" -o "{output_video}"', shell=True)
os.remove('tmp.mpg')

View File

@@ -0,0 +1,75 @@
// dd_ring_buffer.js
// works kinda like an audio delay
// stacks the previous n frames into a buffer
// global variable holding forward motion vectors from previous frames
var prev_fwd_mvs = [ ];
// change these values to use a smaller or greater number of frames to
// perform the average of motion vectors
// try making the delay long enough to overlap an edit in the content ...
var delay = 10;
// divisor controls "feedback" ... or "feedforward" which ever is a better description ...
var feedback = 0.5; // a number between 0.000001 and .... yeah - controls how much of the buffered mv gets into the next pass
var divisor = 1.0/feedback;
function glitch_frame(frame)
{
// bail out if we have no motion vectors
let mvs = frame["mv"];
if ( !mvs )
return;
// bail out if we have no forward motion vectors
let fwd_mvs = mvs["forward"];
if ( !fwd_mvs )
return;
// update variable holding forward motion vectors from previous
// frames. note that we perform a deep copy of the clean motion
// vector values before modifying them.
let json_str = JSON.stringify(fwd_mvs);
let deep_copy = JSON.parse(json_str);
// push to the end of array
prev_fwd_mvs.push(deep_copy);
// drop values from earliest frames to always keep the same tail
// length
if ( prev_fwd_mvs.length > delay )
prev_fwd_mvs = prev_fwd_mvs.slice(1);
// bail out if we still don't have enough frames
if ( prev_fwd_mvs.length != delay )
return;
// replace all motion vectors of current frame with an average
// of the motion vectors from the previous 10 frames
for ( let i = 0; i < fwd_mvs.length; i++ )
{
// loop through all rows
let row = fwd_mvs[i];
let delay_row = prev_fwd_mvs[0][i];
let insert_row = prev_fwd_mvs[delay-1][i];
for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];
let dmv = delay_row[j];
let imv = insert_row[j];
// THIS IS WHERE THE MAGIC HAPPENS
// temp copy of the incoming vectors
let x = mv[0];
let y = mv[1];
// pull their replacements out of the buffer
mv[0] = dmv[0];
mv[1] = dmv[1];
// feedback the 'old' with the 'new' for next time
imv[0] = (dmv[0] / divisor) + x;
imv[1] = (dmv[1] / divisor) + y;
// rinse and repeat
}
}
}

View File

@@ -0,0 +1,71 @@
// dd_delay.js
// works kinda like an audio delay
// stacks the previous n frames into a buffer
// global variable holding forward motion vectors from previous frames
var prev_fwd_mvs = [ ];
// change these values to use a smaller or greater number of frames to
// perform the average of motion vectors
// try making the delay long enough to overlap an edit in the content ...
var delay = 20;
function glitch_frame(frame)
{
// bail out if we have no motion vectors
let mvs = frame["mv"];
if ( !mvs )
return;
// bail out if we have no forward motion vectors
let fwd_mvs = mvs["forward"];
if ( !fwd_mvs )
return;
// update variable holding forward motion vectors from previous
// frames. note that we perform a deep copy of the clean motion
// vector values before modifying them.
let json_str = JSON.stringify(fwd_mvs);
let deep_copy = JSON.parse(json_str);
// push to the end of array
prev_fwd_mvs.push(deep_copy);
// drop values from earliest frames to always keep the same tail
// length
if ( prev_fwd_mvs.length > delay )
prev_fwd_mvs = prev_fwd_mvs.slice(1);
// bail out if we still don't have enough frames
if ( prev_fwd_mvs.length != delay )
return;
// replace all motion vectors of current frame with an average
// of the motion vectors from the previous 10 frames
for ( let i = 0; i < fwd_mvs.length; i++ )
{
// loop through all rows
let row = fwd_mvs[i];
let delay_row = prev_fwd_mvs[0][i];
let insert_row = prev_fwd_mvs[delay-1][i];
for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];
let dmv = delay_row[j];
let imv = insert_row[j];
// THIS IS WHERE THE MAGIC HAPPENS
// temp copy of the incoming vectors
let x = mv[0];
let y = mv[1];
// pull their replacements out of the buffer
mv[0] = dmv[0];
mv[1] = dmv[1];
// feedback the 'old' with the 'new' for next time
imv[0] = x;
imv[1] = y;
// rinse and repeat
}
}
}

View File

@@ -0,0 +1,58 @@
// dd_RandomDamage(invertRandomN).js
// invert x and y component of mv for random number of frames if threshold met for frame
let threshold = 95;
var TRIGGERED = 0;
var nFrames = 10;
var frameCount = 0;
var MAGNITUDE = 20;
function glitch_frame(frame)
{
var do_or_not = Math.random() * 100;
if(do_or_not > threshold){
if(TRIGGERED > 0){
}else{
TRIGGERED = 1;
frameCount = 0;
nFrames = Math.random() * MAGNITUDE;
}
}
// only do the glitch if our random number crosses the threshold
if(TRIGGERED > 0 & frameCount <= nFrames){
frameCount++;
// bail out if we have no motion vectors
let mvs = frame["mv"];
if ( !mvs )
return;
// bail out if we have no forward motion vectors
let fwd_mvs = mvs["forward"];
if ( !fwd_mvs )
return;
var M_H = fwd_mvs.length/2;
// clear horizontal element of all motion vectors
for ( let i = 0; i < fwd_mvs.length; i++ )
{
// loop through all rows
let row = fwd_mvs[i];
var M_W = row.length/2;
for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];
// THIS IS WHERE THE MAGIC HAPPENS
// STOP XY
mv[0] = 0 - mv[0];
mv[1] = 0 - mv[1];
}
}
}else{
TRIGGERED = 0;
}
}

View File

@@ -0,0 +1,52 @@
// dd_mirror_X.js
// clean buffer :
var buffer = [ ];
var ZOOM = -20;
function glitch_frame(frame)
{
// bail out if we have no motion vectors
let mvs = frame["mv"];
if ( !mvs )
return;
// bail out if we have no forward motion vectors
let fwd_mvs = mvs["forward"];
if ( !fwd_mvs )
return;
// note that we perform a deep copy of the clean motion
// vector values before modifying them.
let json_str = JSON.stringify(fwd_mvs);
let deep_copy = JSON.parse(json_str);
// stick em in the buffer
buffer = deep_copy;
var M_H = fwd_mvs.length/2;
// VERTICALLY
for ( let i = 0; i < fwd_mvs.length; i++ )
{
// loop through all rows
let row = fwd_mvs[i];
var row2 = buffer[i];
//var row2 = fwd_mvs[(fwd_mvs.length-1)-i];
var M_W = row.length/2;
// HORIZONTALLY
for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];
var mv2 = row2[(row.length - 1) - j];
// THIS IS WHERE THE MAGIC HAPPENS
//if(i>M_W){
mv[0] = 0-mv2[0];
mv[1] = mv2[1];
//}
}
}
}

View File

@@ -0,0 +1,67 @@
// dd_MultiplySlowest_50.js
// Multiply slowest moving mv's
var LARGEST = 0;
var SOME_PERCENTAGE = 0.5;
var MULTIPLE = 10;
// global variable holding forward motion vectors from previous frames
var prev_fwd_mvs = [ ];
// change this value to use a smaller or greater number of frmes to average
var tail_length = 20;
function glitch_frame(frame)
{
LARGEST = 0;
// bail out if we have no motion vectors
let mvs = frame["mv"];
if ( !mvs )
return;
// bail out if we have no forward motion vectors
let fwd_mvs = mvs["forward"];
if ( !fwd_mvs )
return;
// 1st loop - find the fastest mv
// this ends-up in LARGEST as the square of the hypotenuse (mv[0]*mv[0]) + (mv[1]*mv[1])
let W = fwd_mvs.length;
for ( let i = 0; i < fwd_mvs.length; i++ )
{
let row = fwd_mvs[i];
// rows
let H = row.length;
for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];
// THIS IS WHERE THE MEASUREMENT HAPPENS
var this_mv = (mv[0] * mv[0])+(mv[1] * mv[1]);
if ( this_mv > LARGEST){
LARGEST = this_mv;
}
}
}
// then find those mv's which are bigger than SOME_PERCENTAGE of LARGEST
// and then replace them with the average mv from the last n frames
for ( let i = 0; i < fwd_mvs.length; i++ )
{
let row = fwd_mvs[i];
// rows
let H = row.length;
for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];
// THIS IS WHERE THE MAGIC HAPPENS
var this_mv = (mv[0] * mv[0])+(mv[1] * mv[1]);
if (this_mv < (LARGEST * SOME_PERCENTAGE)){
mv[0] = mv[0] * MULTIPLE;
mv[1] = mv[1] * MULTIPLE;
}
}
}
}

View File

@@ -0,0 +1,37 @@
// dd_sheer.js
var ZOOM = -20;
function glitch_frame(frame)
{
// bail out if we have no motion vectors
let mvs = frame["mv"];
if ( !mvs )
return;
// bail out if we have no forward motion vectors
let fwd_mvs = mvs["forward"];
if ( !fwd_mvs )
return;
var M_H = fwd_mvs.length/2;
// clear horizontal element of all motion vectors
for ( let i = 0; i < fwd_mvs.length; i++ )
{
// loop through all rows
let row = fwd_mvs[i];
var M_W = row.length/2;
for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];
// THIS IS WHERE THE MAGIC HAPPENS
//if(i>M_W){
mv[0] = mv[0] + ((i - M_W) / 100)*ZOOM;
mv[1] = mv[1] + ((j - M_H) / 100)*ZOOM;
//}
}
}
}

View File

@@ -0,0 +1,74 @@
// dd_RandomDamage(antiGrav).js
// anitgravityify if threshold met for frame
let threshold = 98;
// global variable holding forward motion vectors from previous frames
var old_mvs = [ ];
// a variable for gravity
var rt = 0;
var gravity = 0
var orig_gravity = 5;
var TRIGGERED = 0;
var frameCount = 10;
var count = 0;
function glitch_frame(frame)
{
var do_or_not = Math.random() * 100;
// only do the glitch if our random number crosses the threshold
if(do_or_not > threshold | TRIGGERED == 1){
if(TRIGGERED == 0){
gravity = orig_gravity;
TRIGGERED = 1;
rt = 0;
}
// bail out if we have no motion vectors
let mvs = frame["mv"];
if ( !mvs )
return;
// bail out if we have no forward motion vectors
let fwd_mvs = mvs["forward"];
if ( !fwd_mvs )
return;
// buffer first set of vectors. . .
if(rt == 0){
let json_str = JSON.stringify(fwd_mvs);
let deep_copy = JSON.parse(json_str);
// push to the end of array
old_mvs[0] = (deep_copy);
rt = 1;
}
// clear horizontal element of all motion vectors
for ( let i = 0; i < fwd_mvs.length; i++ )
{
// loop through all rows
let row = fwd_mvs[i];
let old_row = old_mvs[0][i];
for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];
let omv = old_row[j];
// THIS IS WHERE THE MAGIC HAPPENS
mv[0] = mv[0];
//if(mv[1] < 0){
var nmv = mv[1];
mv[1] = omv[1];
omv[1] = nmv + omv[1] + gravity;
//gravity++;
//}else{
// mv[1] = mv[1];
//}
}
}
count++;
if(count >= frameCount){
TRIGGERED = 0;
count = 0;
}
}
}

View File

@@ -0,0 +1,38 @@
// dd_zero.js
// only fuck things up if mv > movement_threshold
var movement_threshold = 3;
function glitch_frame(frame)
{
// bail out if we have no motion vectors
let mvs = frame["mv"];
if ( !mvs )
return;
// bail out if we have no forward motion vectors
let fwd_mvs = mvs["forward"];
if ( !fwd_mvs )
return;
// columns
let W = fwd_mvs.length;
for ( let i = 0; i < fwd_mvs.length; i++ )
{
let row = fwd_mvs[i];
// rows
let H = row.length;
for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];
// THIS IS WHERE THE MAGIC HAPPENS
if ( (mv[0] * mv[0])+(mv[1] * mv[1]) > movement_threshold*movement_threshold){
//mv[0] = Math.sin(i/W*Math.PI*2)*mv[0];
//mv[1] = Math.cos(j/H*Math.PI*2)*mv[1];
mv[0] = 0;//mv[0] * 10;
mv[1] = 0;//mv[1] * 10;
}
}
}
}

View File

@@ -0,0 +1,37 @@
// dd_slam_zoom_in.js
var ZOOM = 20;
function glitch_frame(frame)
{
// bail out if we have no motion vectors
let mvs = frame["mv"];
if ( !mvs )
return;
// bail out if we have no forward motion vectors
let fwd_mvs = mvs["forward"];
if ( !fwd_mvs )
return;
var M_H = fwd_mvs.length/2;
// clear horizontal element of all motion vectors
for ( let i = 0; i < fwd_mvs.length; i++ )
{
// loop through all rows
let row = fwd_mvs[i];
var M_W = row.length/2;
for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];
// THIS IS WHERE THE MAGIC HAPPENS
//if(i>M_W){
mv[0] = ((M_W - j) / 100)*ZOOM;
mv[1] = ((M_H - i) / 100)*ZOOM;
//}
}
}
}

View File

@@ -0,0 +1,68 @@
// dd_RandomDamage(progZoom).js
// progressive Zoom x and y components of mv if threshold met for frame
let threshold = 95;
var ZOOM = 0;
var doZOOM = 0;
var TRIGGERED = 0;
var nFrames = 5;
var frameCount = 0;
function glitch_frame(frame)
{
var do_or_not = Math.random() * 100;
if(do_or_not > threshold){
if(TRIGGERED > 0){
}else{
TRIGGERED = 1;
frameCount = 0;
ZOOM = 0;
}
}
// only do the glitch if our random number crosses the threshold
if(TRIGGERED > 0 & frameCount <= nFrames){
frameCount++;
ZOOM+= 10
var do_dir = Math.random() * 100;
if(do_dir > 50){
doZOOM = 0 - ZOOM;
}else{
doZOOM = ZOOM
}
// bail out if we have no motion vectors
let mvs = frame["mv"];
if ( !mvs )
return;
// bail out if we have no forward motion vectors
let fwd_mvs = mvs["forward"];
if ( !fwd_mvs )
return;
var M_H = fwd_mvs.length/2;
// clear horizontal element of all motion vectors
for ( let i = 0; i < fwd_mvs.length; i++ )
{
// loop through all rows
let row = fwd_mvs[i];
var M_W = row.length/2;
for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];
// THIS IS WHERE THE MAGIC HAPPENS
// ZOOM X & Y VECTORS
mv[0] = mv[0] + ((M_W - j) / 10)*doZOOM;
mv[1] = mv[1] + ((M_H - i) / 10)*doZOOM;
}
}
}else{
TRIGGERED = 0;
}
}

View File

@@ -0,0 +1,56 @@
// dd_RandomDamage(stopXY).js
// stop x and y component of mv for n framesif threshold met for frame
let threshold = 95;
var TRIGGERED = 0;
var nFrames = 10;
var frameCount = 0;
function glitch_frame(frame)
{
var do_or_not = Math.random() * 100;
if(do_or_not > threshold){
if(TRIGGERED > 0){
}else{
TRIGGERED = 1;
frameCount = 0;
}
}
// only do the glitch if our random number crosses the threshold
if(TRIGGERED > 0 & frameCount <= nFrames){
frameCount++;
// bail out if we have no motion vectors
let mvs = frame["mv"];
if ( !mvs )
return;
// bail out if we have no forward motion vectors
let fwd_mvs = mvs["forward"];
if ( !fwd_mvs )
return;
var M_H = fwd_mvs.length/2;
// clear horizontal element of all motion vectors
for ( let i = 0; i < fwd_mvs.length; i++ )
{
// loop through all rows
let row = fwd_mvs[i];
var M_W = row.length/2;
for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];
// THIS IS WHERE THE MAGIC HAPPENS
// STOP XY
mv[0] = 0;
mv[1] = 0;
}
}
}else{
TRIGGERED = 0;
}
}

View File

@@ -0,0 +1,29 @@
var randomness = 10;
var bias = (randomness/2);
function glitch_frame(frame)
{
// bail out if we have no motion vectors
let mvs = frame["mv"];
if ( !mvs )
return;
// bail out if we have no forward motion vectors
let fwd_mvs = mvs["forward"];
if ( !fwd_mvs )
return;
// clear horizontal element of all motion vectors
for ( let i = 0; i < fwd_mvs.length; i++ )
{
// loop through all rows
let row = fwd_mvs[i];
for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];
// THIS IS WHERE THE MAGIC HAPPENS
mv[0] = mv[0] + (Math.floor((Math.random() * randomness) -bias));
mv[1] = mv[1] + (Math.floor((Math.random() * randomness) -bias));
}
}
}

View File

@@ -0,0 +1,38 @@
// dd_zoom_in.js
var ZOOM = 20;
function glitch_frame(frame)
{
// bail out if we have no motion vectors
let mvs = frame["mv"];
if ( !mvs )
return;
// bail out if we have no forward motion vectors
let fwd_mvs = mvs["forward"];
if ( !fwd_mvs )
return;
var M_H = fwd_mvs.length/2;
// clear horizontal element of all motion vectors
for ( let i = 0; i < fwd_mvs.length; i++ )
{
// loop through all rows
let row = fwd_mvs[i];
var M_W = row.length/2;
for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];
// THIS IS WHERE THE MAGIC HAPPENS
//if(i>M_W){
mv[0] = mv[0] + ((M_W - j) / 100)*ZOOM;
mv[1] = mv[1] + ((M_H - i) / 100)*ZOOM;
//}
}
}
}

View File

@@ -0,0 +1,35 @@
#Author: Akash Bora
import subprocess
def Datamosh(filename, outf, s, e, p, fps=30):
END_FRAME_HEX = b'00dc'
I_FRAME_HEX = b'\x00\x01\xb0'
def main(filename, effect_sec_list, p_frames_mult):
mosh(effect_sec_list, p_frames_mult)
def mosh(effect_sec_list, p_frames_mult):
with open(filename, 'rb') as in_file, open(outf, 'wb') as out_file:
frames = split_file(in_file, END_FRAME_HEX)
for index, frame in enumerate(frames):
if not is_need_effect_here(index / fps, effect_sec_list):
out_file.write(frame + END_FRAME_HEX)
continue
if not is_iframe(frame):
out_file.write((frame + END_FRAME_HEX) * p_frames_mult)
def split_file(fp, marker, blocksize=4096):
buffer = b''
for block in iter(lambda: fp.read(blocksize), b''):
buffer += block
while True:
markerpos = buffer.find(marker)
if markerpos == -1:
break
yield buffer[:markerpos]
buffer = buffer[markerpos + len(marker):]
yield buffer
def is_need_effect_here(curr_sec, effect_sec_list):
return any(start < curr_sec < end for start, end in effect_sec_list)
def is_iframe(frame):
return frame[5:8] == I_FRAME_HEX
start=s
end=e
pf=p
main(filename,[(start,end)],pf)

View File

@@ -0,0 +1,64 @@
#Author: Akash Bora
from pymosh import Index
from pymosh.codec.mpeg4 import is_iframe
from itertools import islice
class library():
def glide(interval, filename, outfile):
f = Index.from_file(filename)
buf = [None]
def process_frame(frame):
if buf[0] == None or not is_iframe(frame):
buf[0] = frame
else:
frame = buf[0]
return frame
for stream in f.video:
newstream = []
newstream.append(stream[0])
ix = 0
jx = 0
for i in stream[1:]:
ix += 1
jx += 1
if ix < interval:
newstream.append(process_frame(stream[jx]))
else:
newstream.append(newstream[-1])
if ix > interval * 2:
ix = 0
stream.replace(newstream)
f.rebuild()
with open(outfile, 'wb') as out:
f.write(out)
def avi_sort(filename, outfile, mode, rev):
f = Index.from_file(filename)
for stream in f.video:
if mode==0:
sorted_stream = sorted(stream, key=len, reverse=rev)
else:
sorted_stream = sorted(stream, key=lambda s: s[len(s)-6], reverse=rev)
stream.replace(sorted_stream)
f.rebuild()
with open(outfile, 'wb') as out:
f.write(out)
def process_streams(in_filename, out_filename, mid=''):
def echo(stream, midpoint):
all_frames = list(stream)
pframes = [f for f in all_frames if not is_iframe(f)]
midpoint_idx = int(len(all_frames)*midpoint)
frames = all_frames[:midpoint_idx]
while len(frames) < len(all_frames):
frames += pframes[:(len(all_frames) - len(frames))]
return frames
mode=echo
f = Index.from_file(in_filename)
for stream in f.video:
midpoint=mid
drifted = list(mode(stream, midpoint))
stream.replace(drifted)
f.rebuild()
with open(out_filename, 'wb') as out:
f.write(out)

View File

@@ -0,0 +1,43 @@
#Author: Akash Bora
def Datamosh(filename,outfile,s,e,p,fps):
def write_frame(frame):
out_file.write(frame_start + frame)
def mosh_delta_repeat(n_repeat):
if n_repeat=="1":
n_repeat=2
repeat_frames = []
repeat_index = 0
for index, frame in enumerate(frames):
if (frame[5:8] != iframe and frame[5:8] != pframe) or not start_frame <= index < end_frame:
write_frame(frame)
continue
if len(repeat_frames) < n_repeat and frame[5:8] != iframe:
repeat_frames.append(frame)
write_frame(frame)
elif len(repeat_frames) == n_repeat:
write_frame(repeat_frames[repeat_index])
repeat_index = (repeat_index + 1) % n_repeat
else:
write_frame(frame)
start_frame = s
end_frame = e
if end_frame==1:
end_frame=1000
input_avi = filename
delta = p
in_file = open(input_avi, 'rb')
output_avi= outfile
in_file_bytes = in_file.read()
out_file = open(output_avi, 'wb')
frame_start = bytes.fromhex('30306463')
frames = in_file_bytes.split(frame_start)
out_file.write(frames[0])
frames = frames[1:]
iframe = bytes.fromhex('0001B0')
pframe = bytes.fromhex('0001B6')
n_video_frames = len([frame for frame in frames if frame[5:8] == iframe or frame[5:8] == pframe])
if end_frame < 0:
end_frame = n_video_frames
mosh_delta_repeat(delta)
in_file.close()
out_file.close()

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Kaspar RAVEL
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,234 @@
#Original Author: Kasper Ravel
#Modified by: Akash Bora
import os, re, random, struct
from itertools import chain
from itertools import repeat
def mosh(infile, outfile, m, c, n, a, f, k):
print (" _ _ ")
print ("| | | | ")
print ("| |_ ___ _ __ ___ __ _| |_ ___ ")
print ("| __/ _ \| '_ ` _ \ / _` | __/ _ \ ")
print ("| || (_) | | | | | | (_| | || (_) |")
print (" \__\___/|_| |_| |_|\__,_|\__\___/ ")
print ("Tomato Automosh v2.0")
print ("\\\\ Audio Video Interleave breaker")
print (" ")
print ("glitch tool made with love for the glitch art community <3")
print ("___________________________________")
filein = infile
mode = m
countframes = c
positframes = n
audio = a
firstframe = f
kill = k
if filein is None or os.path.exists(filein) == False:
print("> step 0/5: valid input file required!")
print("use -h to see help")
exit()
#define temp directory and files
temp_nb = random.randint(10000, 99999)
temp_dir = "temp-" + str(temp_nb)
temp_hdrl = temp_dir +"\\hdrl.bin"
temp_movi = temp_dir +"\\movi.bin"
temp_idx1 = temp_dir +"\\idx1.bin"
os.mkdir(temp_dir)
#Define constrain function for jiggle :3
def constrain(val, min_val, max_val):
return min(max_val, max(min_val, val))
######################################
### STREAM FILE INTO WORK DIR BINS ###
######################################
print("> step 1/5 : streaming into binary files")
def bstream_until_marker(bfilein, bfileout, marker=0, startpos=0):
chunk = 1024
filesize = os.path.getsize(bfilein)
if marker :
marker = str.encode(marker)
with open(bfilein,'rb') as rd:
with open(bfileout,'ab') as wr:
for pos in range(startpos, filesize, chunk):
rd.seek(pos)
buffer = rd.read(chunk)
if marker:
if buffer.find(marker) > 0 :
marker_pos = re.search(marker, buffer).start() # position is relative to buffer glitchedframes
marker_pos = marker_pos + pos # position should be absolute now
split = buffer.split(marker, 1)
wr.write(split[0])
return marker_pos
else:
wr.write(buffer)
else:
wr.write(buffer)
#make 3 files, 1 for each chunk
movi_marker_pos = bstream_until_marker(filein, temp_hdrl, "movi")
idx1_marker_pos = bstream_until_marker(filein, temp_movi, "idx1", movi_marker_pos)
bstream_until_marker(filein, temp_idx1, 0, idx1_marker_pos)
####################################
### FUN STUFF WITH VIDEO CONTENT ###
####################################
print("> step 2/5 : constructing frame index")
with open(temp_movi,'rb') as rd:
chunk = 1024
filesize = os.path.getsize(temp_movi)
frame_table = []
for pos in range(0, filesize, chunk):
rd.seek(pos)
buffer = rd.read(chunk)
#build first list with all adresses
for m in (re.finditer(b'\x30\x31\x77\x62', buffer)): # find iframes
if audio : frame_table.append([m.start() + pos, 'sound'])
for m in (re.finditer(b'\x30\x30\x64\x63', buffer)): # find b frames
frame_table.append([m.start() + pos, 'video'])
#then remember to sort the list
frame_table.sort(key=lambda tup: tup[0])
l = []
l.append([0,0, 'void'])
max_frame_size = 0
#build tuples for each frame index with frame sizes
for n in range(len(frame_table)):
if n + 1 < len(frame_table):
frame_size = frame_table[n + 1][0] - frame_table[n][0]
else:
frame_size = filesize - frame_table[n][0]
max_frame_size = max(max_frame_size, frame_size)
l.append([frame_table[n][0],frame_size, frame_table[n][1]])
########################
### TIME FOR SOME FX ###
########################
# variables that make shit work
clean = []
final = []
# keep first video frame or not
if firstframe:
for x in l:
if x[2] == 'video':
clean.append(x)
break
# clean the list by killing "big" frames
for x in l:
if x[1] <= (max_frame_size * kill) :
clean.append(x)
# FX modes
if mode == "void":
print('> step 3/5 : mode void')
final = clean
if mode == "random":
print('> step 3/5 : mode random')
final = random.sample(clean,len(clean))
if mode == "reverse":
print('> step 3/5 : mode reverse')
final = sum(zip(clean[::-1], clean[:-1]), ())
if mode == "invert":
print('> step 3/5 : mode invert')
final = sum(zip(clean[1::2], clean[::2]), ())
if mode == 'bloom':
print('> step 3/5 : mode bloom')
repeat = int(countframes)
frame = int(positframes)
## split list
lista = clean[:frame]
listb = clean[frame:]
## rejoin list with bloom
final = lista + ([clean[frame]]*repeat) + listb
if mode == 'pulse':
print('> step 3/5 : mode pulse')
pulselen = int(countframes)
pulseryt = int(positframes)
j = 0
for x in clean:
i = 0
if(j % pulselen == 0):
while i < pulselen :
final.append(x)
i = i + 1
else:
final.append(x)
j = j + 1
if mode == "jiggle":
print('> step 3/5 : mode jiggle')
#print('*needs debugging lol help thx*') # didn't pandy's branch fix this?
amount = int(positframes)
final = [clean[constrain(x+int(random.gauss(0,amount)),0,len(clean)-1)] for x in range(0,len(clean))]
if mode == "overlap":
print('> step 3/5 : mode overlap')
pulselen = int(countframes)
pulseryt = int(positframes)
clean = [clean[i:i+pulselen] for i in range(0,len(clean),pulseryt)]
final = [item for sublist in clean for item in sublist]
if mode == 'exponential':#Ask Kasper to add these modes (Note by Akash)
print('> step 3/5 : mode exponential')
print('sorry, currently not implemented. using void..')
if mode == 'swap':
print('> step 3/5 : mode swap')
print('sorry, currently not implemented. using void..')
####################################
### PUT VIDEO FILE BACK TOGETHER ###
####################################
print("> step 4/5 : putting things back together")
#name new file
fileout = outfile
#delete old file
if os.path.exists(fileout):
os.remove(fileout)
bstream_until_marker(temp_hdrl, fileout)
with open(temp_movi,'rb') as rd:
filesize = os.path.getsize(temp_movi)
with open(fileout,'ab') as wr:
wr.write(struct.pack('<4s', b'movi'))
for x in final:
if x[0] != 0 and x[1] != 0:
rd.seek(x[0])
wr.write(rd.read(x[1]))
bstream_until_marker(temp_idx1, fileout)
#remove unnecessary temporary files and folders
os.remove(temp_hdrl)
os.remove(temp_movi)
os.remove(temp_idx1)
os.rmdir(temp_dir)
print("> step 5/5 : done - final idx size : " + str(len(final)))

View File

@@ -1,812 +0,0 @@
import os
from tkinter import *
from tkinter import ttk, messagebox, filedialog
import tkinter
import sys
import random
import re
import struct
import time
import webbrowser
from itertools import chain, repeat, islice
import subprocess
import pkg_resources
#Note that this program is optimised for only windows, for other systems you have to change the ffmpeg path(line 48).
required = {'imageio', 'imageio-ffmpeg'}
installed = {pkg.key for pkg in pkg_resources.working_set}
missing = required - installed
missingset=[*missing,]
if missing:
res=messagebox.askquestion("Module Error","Some modules are not installed \n do you want to download and install them?")
if res=="yes":
for x in range(len(missingset)):
y=missingset[x]
subprocess.Popen('python -m pip install '+y)
messagebox.showinfo("Module Installed","Please restart the program!")
sys.exit()
elif res=="no":
messagebox.showerror("Error","Required modules not available!\nWithout the modules you can't use this program. Please install them first!")
sys.exit()
else:
import imageio
if os.path.isdir("pymosh"):
from pymosh import Index
from pymosh.codec.mpeg4 import is_iframe
else:
messagebox.showerror("Missing Folder!","Pymosh folder is not available! Please download it from our github page.")
sys.exit()
def resource_path0(relative_path):
base_path = getattr(
sys,
'_MEIPASS',
os.path.dirname(os.path.abspath(__file__)))
return os.path.join(base_path, relative_path)
#ffmpeg path:
python_folder=os.path.dirname(sys.executable)
path=python_folder.replace(os.sep, '/')
global resource
resource=resource_path0(path+"/Lib/site-packages/imageio_ffmpeg/binaries/ffmpeg-win64-v4.2.2.exe")
def openfile():
global file
file=tkinter.filedialog.askopenfilename(filetypes =[('Video', ['*.mp4','*.avi','*.mov','*.mkv','*wmv']),('All Files', '*.*')])
if(len(file)>1):
LocationError.config(text=file, fg="green")
OpeningFile['text']='Open Again'
OpeningFile['bg']='#D0CECE'
else:
LocationError.config(text="Choose Video To Datamosh", fg="red")
OpeningFile['text']='OPEN'
OpeningFile['bg']='#82CC6C'
def convertffmpeg(inputpath):
Wait.config(text="Converting the Video...", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
fps=30
targetformat='.avi'
outputpath=os.path.splitext(inputpath)[0]+'_datamoshed'+targetformat
subprocess.call(f'"{resource}" -loglevel error -y -i "{inputpath}" -crf 0 -bf 0 -r {fps} "{outputpath}"', shell=True)
try:
Wait.config(text="Applying Effect: Classic", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
Datamoshclassic(outputpath,inputpath)
except:
messagebox.showerror("FAILED","The video file or the input data have \n some issues!")
Wait.place_forget()
os.remove(outputpath)
datamoshbtn['state']=NORMAL
modechoices['state']=NORMAL
exportbox['state']=NORMAL
OpeningFile['state']=NORMAL
root.config(cursor="")
def convert(inputpath,targetformat):
global outputpath
try:
Wait.config(text="Converting the Video...", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
outputpath=os.path.splitext(inputpath)[0]+'_datamoshed'+targetformat
reader=imageio.get_reader(inputpath)
fps=reader.get_meta_data()['fps']
writer= imageio.get_writer(outputpath, fps=fps)
for frames in reader:
writer.append_data(frames)
#to get detailed logs of conversions, remove the comment in the next 2 lines
#print(f'Frame {frames}')
#print("Converted")
writer.close()
try:
Datamosh(outputpath)
except:
pass
except:
messagebox.showerror("FAILED","The video file or the input data have \n some issues!")
Wait.place_forget()
os.remove(outputpath)
datamoshbtn['state']=NORMAL
modechoices['state']=NORMAL
exportbox['state']=NORMAL
OpeningFile['state']=NORMAL
root.config(cursor="")
def validate():
try:
float(Countframe.get())
float(Positframe.get())
float(firstframes.get())
float(killframe.get())
x=float(killframe.get())
if x>1:
var4.set(1)
except ValueError:
messagebox.showerror("Invalid Input","Please enter some valid data")
sys.exit()
def checkexist(file):
mode = modechoices.get()
tformat=exportbox.get()
f=os.path.splitext(file)[0]
exfile=f+"_datamoshed"+"-"+mode+"_datamoshed."+tformat
if os.path.exists(exfile):
warn=messagebox.askquestion("Warning","Do you want to replace the old file?")
if warn=='yes':
os.remove(exfile)
elif warn=='no':
os.kill(checkesist())
pass
def Step1():
try:
if (len(file)>=1):
Wait.place(relx=0.5,rely=0.85,anchor='center')
root.update()
datamoshbtn['state']=DISABLED
extension=os.path.splitext(file)[1]
modechoices['state']=DISABLED
exportbox['state']=DISABLED
OpeningFile['state']=DISABLED
validate()
checkexist(file)
root.config(cursor="")
choice = modechoices.get()
if(choice==modes[7]):
if extension==".mp4":
convertffmpeg(file)
else:
targetformat=".mp4"
convert(file,targetformat)
convertffmpeg(file)
elif(choice==modes[8]) or (choice==modes[9]) or (choice==modes[11]):
pymosh_library(file)
else:
targetformat=".avi"
convert(file,targetformat)
else:
messagebox.showerror("","Please choose the video again!")
except:
datamoshbtn['state']=NORMAL
modechoices['state']=NORMAL
exportbox['state']=NORMAL
OpeningFile['state']=NORMAL
root.config(cursor="")
Wait.place_forget()
messagebox.showerror("","Please choose the video file again!")
def pymosh_library(file):
global final
outpath=os.path.dirname(file)
outx=os.path.basename(file).split('.')[0]
infile=os.path.dirname(file)+"/"+outx+"_datamoshed.avi"
if os.path.exists(infile):
os.remove(infile)
fps=30
subprocess.call(f'"{resource}" -loglevel error -y -i "{file}" -crf 0 -bf 0 -r {fps} "{infile}"', shell=True)
def glide(interval, filename, outfile):
f = Index.from_file(filename)
buf = [None]
def process_frame(frame):
if buf[0] == None or not is_iframe(frame):
buf[0] = frame
else:
frame = buf[0]
return frame
for stream in f.video:
newstream = []
newstream.append(stream[0])
ix = 0
jx = 0
for i in stream[1:]:
ix += 1
jx += 1
if ix < interval:
newstream.append(process_frame(stream[jx]))
else:
newstream.append(newstream[-1])
if ix > interval * 2:
ix = 0
stream.replace(newstream)
f.rebuild()
with open(outfile, 'wb') as out:
f.write(out)
def avi_sort(filename, outfile):
f = Index.from_file(filename)
for stream in f.video:
sorted_stream = sorted(stream, key=len, reverse=True)
stream.replace(sorted_stream)
f.rebuild()
with open(outfile, 'wb') as out:
f.write(out)
def process_streams(in_filename, out_filename, func, *args, **kwargs):
f = Index.from_file(in_filename)
for stream in f.video:
midpoint=float(firstframes.get())
if midpoint>1:
midpoint=1
drifted = list(func(stream, midpoint,*args, **kwargs))
stream.replace(drifted)
f.rebuild()
with open(out_filename, 'wb') as out:
f.write(out)
def echo(stream, midpoint):
all_frames = list(stream)
pframes = [f for f in all_frames if not is_iframe(f)]
midpoint_idx = int(len(all_frames)*midpoint)
frames = all_frames[:midpoint_idx]
while len(frames) < len(all_frames):
frames += pframes[:(len(all_frames) - len(frames))]
return frames
choice = modechoices.get()
if(choice==modes[8]):
Wait.config(text="Applying Effect: Glide", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
time.sleep(2)
interval=int(Positframe.get())
if (interval==1):
interval=2
outfile=outpath+"/"+os.path.basename(infile).split('.')[0]+"-glide.avi"
if os.path.exists(outfile):
os.remove(outfile)
glide(interval, infile, outfile)
elif (choice==modes[9]):
Wait.config(text="Applying Effect: Sort", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
time.sleep(2)
outfile=outpath+"/"+os.path.basename(infile).split('.')[0]+"-sort.avi"
if os.path.exists(outfile):
os.remove(outfile)
avi_sort(infile, outfile)
elif (choice==modes[11]):
Wait.config(text="Applying Effect: Echo", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
time.sleep(2)
outfile=outpath+"/"+os.path.basename(infile).split('.')[0]+"-echo.avi"
if os.path.exists(outfile):
os.remove(outfile)
process_streams(infile, outfile, echo)
final=outpath+"/"+os.path.basename(outfile).split('.')[0]+".mp4"
if os.path.exists(final):
os.remove(final)
subprocess.call(f'"{resource}" -loglevel error -y -i "{outfile}" "{final}"', shell=True)
export2=exportbox.get()
os.remove(infile)
export(final)
os.remove(outfile)
def Datamoshclassic(filename,mainfile):
global outf
END_FRAME_HEX = b'00dc'
I_FRAME_HEX = b'\x00\x01\xb0'
fps=30
outx=os.path.basename(filename).split('.')[0]
outpath=os.path.dirname(mainfile)
outf=outpath+"/"+outx+"-classic_datamoshed.avi"
def main2(filename, effect_sec_list, p_frames_mult):
magic(effect_sec_list, p_frames_mult)
out=outpath+"/"+outx+"-classic.mp4"
subprocess.call(f'"{resource}" -loglevel error -y -i "{outf}" "{out}"', shell=True)
os.remove(filename)
export(out)
export2=exportbox.get()
if(export2==exportchoices[0]):
pass
else:
os.remove(outf)
def magic(effect_sec_list, p_frames_mult):
with open(filename, 'rb') as in_file, open(outf, 'wb') as out_file:
frames = split_file(in_file, END_FRAME_HEX)
for index, frame in enumerate(frames):
if not is_need_effect_here(index / fps, effect_sec_list):
out_file.write(frame + END_FRAME_HEX)
continue
if not is_iframe(frame):
out_file.write((frame + END_FRAME_HEX) * p_frames_mult)
def split_file(fp, marker, blocksize=4096):
buffer = b''
for block in iter(lambda: fp.read(blocksize), b''):
buffer += block
while True:
markerpos = buffer.find(marker)
if markerpos == -1:
break
yield buffer[:markerpos]
buffer = buffer[markerpos + len(marker):]
yield buffer
def is_need_effect_here(curr_sec, effect_sec_list):
return any(start < curr_sec < end for start, end in effect_sec_list)
def is_iframe(frame):
return frame[5:8] == I_FRAME_HEX
start=float(firstframes.get())
make=float(Countframe.get())
timer=int(Positframe.get())
main2(filename,[(start,make)],timer)
def Datamosh(Inputfile):
global fileout
checkinput=os.path.splitext(file)[0]+"_datamoshed.avi"
if os.path.exists(checkinput):
filein = Inputfile
countframes = int(Countframe.get())
positframes = int(Positframe.get())
firstframe = int(firstframes.get())
choice = modechoices.get()
kill = float(killframe.get())
if(choice==modes[0]):
mode="bloom"
elif(choice==modes[1]):
mode="invert"
elif(choice==modes[2]):
mode="jiggle"
elif(choice==modes[3]):
mode="overlap"
elif(choice==modes[4]):
mode="pulse"
elif(choice==modes[5]):
mode="reverse"
elif(choice==modes[6]):
mode="random"
elif(choice==modes[10]):
mode="shake"
elif(choice==modes[12]):
mode="void"
else:
messagebox.showerror("Error!","Please select a valid mode!")
os.remove(outputpath)
Wait.place_forget()
datamoshbtn['state']=NORMAL
root.config(cursor="")
modechoices['state']=NORMAL
exportbox['state']=NORMAL
OpeningFile['state']=NORMAL
os.kill(Datamosh())
temp_nb = random.randint(10000, 99999)
temp_dir = "temp-" + str(temp_nb)
temp_hdrl = temp_dir +"/hdrl.bin"
temp_movi = temp_dir +"/movi.bin"
temp_idx1 = temp_dir +"/idx1.bin"
os.mkdir(temp_dir)
def constrain(val, min_val, max_val):
return min(max_val, max(min_val, val))
def bstream_until_marker(bfilein, bfileout, marker=0, startpos=0):
chunk = 1024
filesize = os.path.getsize(bfilein)
if marker :
marker = str.encode(marker)
with open(bfilein,'rb') as rd:
with open(bfileout,'ab') as wr:
for pos in range(startpos, filesize, chunk):
rd.seek(pos)
buffer = rd.read(chunk)
if marker:
if buffer.find(marker) > 0 :
marker_pos = re.search(marker, buffer).start()
marker_pos = marker_pos + pos
split = buffer.split(marker, 1)
wr.write(split[0])
return marker_pos
else:
wr.write(buffer)
else:
wr.write(buffer)
movi_marker_pos = bstream_until_marker(filein, temp_hdrl, "movi")
idx1_marker_pos = bstream_until_marker(filein, temp_movi, "idx1", movi_marker_pos)
bstream_until_marker(filein, temp_idx1, 0, idx1_marker_pos)
with open(temp_movi,'rb') as rd:
chunk = 1024
filesize = os.path.getsize(temp_movi)
frame_table = []
for pos in range(0, filesize, chunk):
rd.seek(pos)
buffer = rd.read(chunk)
for m in (re.finditer(b'\x30\x31\x77\x62', buffer)):
if audio : frame_table.append([m.start() + pos, 'sound'])
for m in (re.finditer(b'\x30\x30\x64\x63', buffer)):
frame_table.append([m.start() + pos, 'video'])
frame_table.sort(key=lambda tup: tup[0])
l = []
l.append([0,0, 'void'])
max_frame_size = 0
for n in range(len(frame_table)):
if n + 1 < len(frame_table):
frame_size = frame_table[n + 1][0] - frame_table[n][0]
else:
frame_size = filesize - frame_table[n][0]
max_frame_size = max(max_frame_size, frame_size)
l.append([frame_table[n][0],frame_size, frame_table[n][1]])
clean = []
final = []
if firstframe :
for x in l :
if x[2] == 'video':
clean.append(x)
break
for x in l:
if x[1] <= (max_frame_size * kill) :
clean.append(x)
if mode == "void":
final = clean
if mode == "random":
Wait.config(text="Applying Effect: Random", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
final = random.sample(clean,len(clean))
if mode == "reverse":
Wait.config(text="Applying Effect: Reverse", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
final = sum(zip(clean[::-1], clean[:-1]), ())
if mode == "invert":
Wait.config(text="Applying Effect: Invert", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
final = sum(zip(clean[1::2], clean[::2]), ())
if mode == 'bloom':
Wait.config(text="Applying Effect: Bloom", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
repeat = int(countframes)
frame = int(positframes)
lista = clean[:frame]
listb = clean[frame:]
final = lista + ([clean[frame]]*repeat) + listb
if mode == 'pulse':
Wait.config(text="Applying Effect: Pulse", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
pulselen = int(countframes)
pulseryt = int(positframes)
j = 0
for x in clean:
i = 0
if(j % pulselen == 0):
while i < pulselen :
final.append(x)
i = i + 1
else:
final.append(x)
j = j + 1
if mode == "jiggle":
Wait.config(text="Applying Effect: Jiggle", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
amount = int(positframes)
final = [clean[constrain(x+int(random.gauss(0,amount)),0,len(clean)-1)] for x in range(0,len(clean))]
if mode == "overlap":
Wait.config(text="Applying Effect: Overlap", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
pulselen = int(countframes)
pulseryt = int(positframes)
clean = [clean[i:i+pulselen] for i in range(0,len(clean),pulseryt)]
final = [item for sublist in clean for item in sublist]
if mode == "shake":
Wait.config(text="Applying Effect: Shake", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
def process_streams(in_filename, out_filename, func, *args, **kwargs):
f = Index.from_file(in_filename)
for stream in f.video:
drifted = list(func(stream, *args, **kwargs))
stream.replace(drifted)
f.rebuild()
with open(out_filename, 'wb') as out:
f.write(out)
def shake(stream):
def glitch(stream):
all_frames = iter(stream)
yield next(all_frames)
while True:
frame = next(all_frames)
if not is_iframe(frame):
yield frame
yield frame
return islice(glitch(stream), len(stream))
fileout= filein[:-4] + '-' + mode + '.avi'
process_streams(filein, fileout, shake)
fps=30
output= fileout[:-9]+"shake.mp4"
subprocess.call(f'"{resource}" -loglevel error -y -i "{fileout}" -crf 0 -bf 0 -r {fps} "{output}"', shell=True)
time.sleep(2)
os.remove(fileout)
os.remove(filein)
os.remove(temp_hdrl)
os.remove(temp_movi)
os.remove(temp_idx1)
os.rmdir(temp_dir)
export(output)
os.kill(datamosh)
time.sleep(2)
fileout= filein[:-4] + '-' + mode + '.avi'
if os.path.exists(fileout):
os.remove(fileout)
bstream_until_marker(temp_hdrl, fileout)
with open(temp_movi,'rb') as rd:
filesize = os.path.getsize(temp_movi)
with open(fileout,'ab') as wr:
wr.write(struct.pack('<4s', b'movi'))
for x in final:
if x[0] != 0 and x[1] != 0:
rd.seek(x[0])
wr.write(rd.read(x[1]))
bstream_until_marker(temp_idx1, fileout)
if os.path.exists(outputpath):
os.remove(outputpath)
else:
pass
os.remove(temp_hdrl)
os.remove(temp_movi)
os.remove(temp_idx1)
os.rmdir(temp_dir)
export(fileout)
else:
Wait.config(text="Moshed Video is Ready!", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
def export(fileout):
def removefileout():
if os.path.exists(fileout):
os.remove(fileout)
Wait.place_forget()
datamoshbtn['state']=NORMAL
modechoices['state']=NORMAL
exportbox['state']=NORMAL
OpeningFile['state']=NORMAL
root.config(cursor="")
messagebox.showinfo("DONE","Datamoshed video is ready!")
Wait.config(text="", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
else:
pass
export=exportbox.get()
if(export==exportchoices[0]):
ask=messagebox.askquestion("?","Do you want the Raw moshed version?")
if ask=='yes':
choice = modechoices.get()
if(choice==modes[7]):
Wait.config(text="Moshed Video is Ready!", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
os.remove(fileout)
messagebox.showinfo("DONE","Datamoshed video is ready!")
Wait.place_forget()
datamoshbtn['state']=NORMAL
modechoices['state']=NORMAL
exportbox['state']=NORMAL
OpeningFile['state']=NORMAL
root.config(cursor="")
else:
file2=os.path.splitext(fileout)[0]
os.rename(fileout,file2+"_datamoshed.avi")
Wait.config(text="Moshed Video is Ready!", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
messagebox.showinfo("DONE","Datamoshed video is ready!")
root.config(cursor="")
Wait.place_forget()
datamoshbtn['state']=NORMAL
modechoices['state']=NORMAL
exportbox['state']=NORMAL
OpeningFile['state']=NORMAL
elif ask=='no':
targetformat=".avi"
convert(fileout,targetformat)
removefileout()
elif(export==exportchoices[1]):
choice = modechoices.get()
if(choice==modes[7]) or (choice==modes[8]) or (choice==modes[9]):
nfile=os.path.splitext(fileout)[0]
os.rename(fileout,nfile+"_datamoshed.mp4")
Wait.config(text="Moshed Video is Ready!", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
messagebox.showinfo("DONE","Datamoshed video is ready!")
Wait.place_forget()
root.config(cursor="")
datamoshbtn['state']=NORMAL
modechoices['state']=NORMAL
exportbox['state']=NORMAL
OpeningFile['state']=NORMAL
else:
targetformat=".mp4"
convert(fileout,targetformat)
removefileout()
elif(export==exportchoices[2]):
targetformat=".gif"
convert(fileout,targetformat)
removefileout()
elif(export==exportchoices[3]):
targetformat=".mov"
convert(fileout,targetformat)
removefileout()
elif(export==exportchoices[4]):
targetformat=".mkv"
convert(fileout,targetformat)
removefileout()
elif(export==exportchoices[5]):
targetformat=".wmv"
convert(fileout,targetformat)
removefileout()
else:
messagebox.showerror("Error!","Please select a valid video format!")
os.remove(fileout)
Wait.place_forget()
datamoshbtn['state']=NORMAL
modechoices['state']=NORMAL
exportbox['state']=NORMAL
OpeningFile['state']=NORMAL
root.config(cursor="")
os.kill(Datamosh())
def toggle():
if var.get()==0:
Disableadvanced()
else:
Enableadvanced()
def Enableadvanced():
choice = modechoices.get()
if(choice==modes[8]):
var2.set(6)
var4.set(0.7)
countlabel['fg']="grey"
positlabel['fg']="green"
firstflabel['fg']="grey"
killlabel['fg']="grey"
Countframe['state']=DISABLED
Positframe['state']=NORMAL
firstframes['state']=DISABLED
killframe['state']=DISABLED
if(choice==modes[7]):
var2.set(1)
var1.set(100)
countlabel['fg']="green"
positlabel['fg']="green"
firstflabel['fg']="green"
killlabel['fg']="grey"
Countframe['state']=NORMAL
Positframe['state']=NORMAL
firstframes['state']=NORMAL
killframe['state']=DISABLED
elif(choice==modes[6]) or (choice==modes[10]) or (choice==modes[12]):
var2.set(1)
if (choice==modes[12]):
var4.set(0.2)
else:
var4.set(0.7)
var3.set(1)
countlabel['fg']="grey"
positlabel['fg']="grey"
firstflabel['fg']="green"
killlabel['fg']="green"
Countframe['state']=DISABLED
Positframe['state']=DISABLED
firstframes['state']=NORMAL
killframe['state']=NORMAL
elif(choice==modes[5]):
var2.set(1)
var4.set(0.7)
countlabel['fg']="grey"
positlabel['fg']="grey"
firstflabel['fg']="green"
killlabel['fg']="grey"
Countframe['state']=DISABLED
Positframe['state']=DISABLED
firstframes['state']=NORMAL
killframe['state']=DISABLED
elif(choice==modes[1]) or (choice==modes[11]):
var2.set(1)
if (choice==modes[11]):
var3.set(0.5)
else:
var3.set(1)
countlabel['fg']="grey"
positlabel['fg']="grey"
firstflabel['fg']="green"
killlabel['fg']="grey"
Countframe['state']=DISABLED
Positframe['state']=DISABLED
firstframes['state']=NORMAL
killframe['state']=DISABLED
elif(choice==modes[2]):
var2.set(1)
var4.set(0.7)
countlabel['fg']="grey"
positlabel['fg']="green"
firstflabel['fg']="green"
killlabel['fg']="green"
Countframe['state']=DISABLED
Positframe['state']=NORMAL
firstframes['state']=NORMAL
killframe['state']=NORMAL
elif(choice==modes[0]) or (choice==modes[3]) or (choice==modes[4]):
var2.set(1)
var4.set(0.7)
countlabel['fg']="green"
positlabel['fg']="green"
firstflabel['fg']="green"
killlabel['fg']="green"
Countframe['state']=NORMAL
Positframe['state']=NORMAL
firstframes['state']=NORMAL
killframe['state']=NORMAL
def Disableadvanced():
var1.set("1")
countlabel['fg']="grey"
positlabel['fg']="grey"
firstflabel['fg']="grey"
killlabel['fg']="grey"
Countframe['state']=DISABLED
Positframe['state']=DISABLED
firstframes['state']=DISABLED
killframe['state']=DISABLED
def refresh(event):
if var=="0":
pass
else:
modechoices['values']=toggle()
def info():
messagebox.showinfo("Help",
"Datamosher Pro is a tool that can mosh and corrupt video files and returns an awesome glitched video"
"\nHow To Use:\n➤First open the video you want to datamosh."
"\n➤Choose the desired datamosh mode, then select the export format."
"\n➤Use advance options for different modes (For more details about the advanced options, visit our Github page)."
"\n➤Click on the datamosh button, then wait for a few seconds."
"\n➤After conversion, your video will be ready and you can view the datamoshed video inside its directory."
"\n\nDeveloper: Akash Bora (a.k.a. Akascape)\nIf you are facing any issue then contact me on Github."
"\nVersion-1.3")
def callback(url):
webbrowser.open_new_tab("https://github.com/Akascape/Datamosher-Pro-GUI-.git")
root=Tk()
root.title("Datamosher Pro")
root.resizable(width=False, height=False)
root.geometry("500x450")
root.configure(bg='#FFFFFF')
root.columnconfigure(0,weight=1)
icopath=resource_path0("icon.ico")
root.wm_iconbitmap(icopath)
path=resource_path0("label.png")
LabelIMG=PhotoImage(file=path)
headlabel=Label(root,image=LabelIMG,borderwidth=0, highlightthickness=0, padx=0,pady=0)
headlabel.grid()
LocationError=Label(root,text="Choose Video To Datamosh",fg="red",bg='#FFFFFF')
LocationError.grid()
OpeningFile= Button(root, width=61,bg="#82CC6C",fg="white", text="OPEN",highlightthickness=1,borderwidth=0.2,relief="groove",command=openfile)
OpeningFile.grid()
chooselabel=Label(root,text="Select Mode:",font="Aharoni",bg='#FFFFFF')
chooselabel.place(x=80,y=115,anchor='center')
modes=["Bloom", "Invert", "Jiggle", "Overlap", "Pulse", "Reverse", "Random", "Classic", "Glide", "Sort", "Shake", "Echo", "Void"]
modechoices=ttk.Combobox(root,values=modes, font="Verdana 12", width=7, height=13)
modechoices.current(0)
modechoices.bind('<FocusIn>', lambda event: refresh(event))
modechoices.place(x=130,y=104)
exportchoices=["AVI","MP4","GIF","MOV","MKV","WMV"]
exportlabel=Label(root,text="Export Format:",font="Aharoni",bg='#FFFFFF')
exportlabel.place(x=270,y=105)
exportbox=ttk.Combobox(root,values=exportchoices, font="Verdana 10", width=8)
exportbox.current(1)
exportbox.place(x=380,y=106)
global var
var = IntVar()
var.set(0)
advancedbox=Checkbutton(root, text="Advanced",bg="#FFFFFF", command=toggle,variable=var,onvalue=1, offvalue=0)
advancedbox.place(x=70,y=150, anchor='center')
var1=DoubleVar()
var1.set(1)
countlabel=Label(root,text="Glitch Size",fg="grey",bg='#FFFFFF')
countlabel.place(x=50,y=165)
Countframe=Entry(root,bg="#00D2FF",width=10,borderwidth=3, textvariable=var1,state=DISABLED)
Countframe.place(x=140,y=165)
var2=DoubleVar()
var2.set(1)
positlabel=Label(root,text="Frames Frequency",fg="grey",bg='#FFFFFF')
positlabel.place(x=270,y=165)
Positframe=Entry(root,bg="#00D2FF",width=10,borderwidth=3, textvariable=var2, state=DISABLED)
Positframe.place(x=380,y=165)
var3=IntVar()
var3.set(1)
firstflabel=Label(root,text="First Frame",fg="grey",bg='#FFFFFF')
firstflabel.place(x=50,y=200)
firstframes=Entry(root,bg="#00D2FF",width=10,borderwidth=3, textvariable=var3, state=DISABLED)
firstframes.place(x=140,y=200)
var4=DoubleVar()
var4.set(0.7)
killlabel=Label(root,text="Kill Frames",fg="grey",bg='#FFFFFF')
killlabel.place(x=270,y=200)
killframe=Entry(root,bg="#00D2FF",width=10,borderwidth=3, textvariable=var4, state=DISABLED)
killframe.place(x=380,y=200)
global Wait
Wait=Label(root,text="",fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
infobtn=Button(root, width=2,bg="#FFFFFF",fg="black", text="",font=(10),relief="sunken",cursor='hand2', highlightthickness=0,borderwidth=0,padx=0,pady=0,command=info)
infobtn.place(x=475,y=425)
dev=Label(root, text='Developed by Akascape | For more info, visit:',bg='#FFFFFF',fg="#6D76CD", font=("Impact",10))
dev.place(x=5,y=430)
link=Label(root, text="Datamosher Pro Github",font=('Impact',10),bg='#FFFFFF',fg="#6D76CD", cursor="hand2")
link.place(x=245,y=430)
link.bind("<Button-1>", lambda e:
callback("https://github.com/Akascape/Datamosher-Pro-GUI-.git"))
path0=resource_path0("button.png")
buttonIMG=PhotoImage(file=path0)
datamoshbtn=Button(root,image=buttonIMG,borderwidth=0, highlightthickness=0, padx=0,pady=0,command=Step1)
datamoshbtn.place(x=100,y=270)
root.mainloop()
#DEVELOPER: AKASH BORA (a.k.a Akascape)
#Version=1.3

View File

@@ -0,0 +1,725 @@
#Author: Akash Bora
#License: MIT | Copyright (c) 2022 Akash Bora
currentversion=1.8
#Import required modules
import tkinter
import tkinter.messagebox
import customtkinter
from tkinter import ttk, messagebox, filedialog
import sys
import os
import imageio_ffmpeg
import subprocess
import imageio
from PIL import Image, ImageTk #Upgrade pillow if you are facing any import error with PIL (pip install pillow --upgrade)
from RangeSlider.RangeSlider import RangeSliderH, RangeSliderV
import threading
import ctypes
import webbrowser
import requests
import time
#Import the local datamosh library
from DatamoshLib.Tomato import tomato
from DatamoshLib.Original import classic, repeat, pymodes
from DatamoshLib.FFG_effects import basic_modes, external_script
#Resource Finder
def resource(relative_path):
base_path = getattr(
sys,
'_MEIPASS',
os.path.dirname(os.path.abspath(__file__)))
return os.path.join(base_path, relative_path)
#Main Window
WIDTH = 780
HEIGHT = 520
try:
ctypes.windll.shcore.SetProcessDpiAwareness(0)
except:
pass
customtkinter.set_appearance_mode("Dark")
customtkinter.set_default_color_theme("blue")
self=customtkinter.CTk()
self.title("Datamosher Pro (python version)")
self.geometry(f"{WIDTH}x{HEIGHT}")
self.bind("<1>", lambda event: event.widget.focus_set())
self.grid_columnconfigure(1, weight=1)
self.grid_rowconfigure(0, weight=1)
self.resizable(width=False, height=False)
frame_left = customtkinter.CTkFrame(master=self,width=180,corner_radius=0)
frame_left.grid(row=0, column=0, sticky="nswe")
frame_right = customtkinter.CTkFrame(master=self)
frame_right.grid(row=0, column=1, sticky="nswe", padx=20, pady=20)
icopath=ImageTk.PhotoImage(file=resource("Assets/Icons/Program_icon.png"))
self.iconphoto(False, icopath)
#FFMPEG path (using the imageio ffmpeg plugin)
ffdir=os.path.dirname(imageio_ffmpeg.__file__).replace(os.sep, '/')+"/binaries/"
fileff=''.join([idx for idx in os.listdir(ffdir) if idx[0].lower()=='f'.lower()])
ffmpeg=resource(ffdir+fileff)
#Effect List
modelist=sorted(["Bloom", "Invert", "Jiggle", "Overlap", "Pulse", "Reverse",
"Random", "Classic", "Glide", "Sort", "Echo", "Void",
"Fluid", "Stretch", "Motion Transfer", "Repeat", "Shear", "Delay", "Sink",
"Mirror", "Vibrate", "Slam Zoom", "Zoom","Invert-Reverse", "Shift",
"Noise", "Stop", "Buffer", "Slice", "Shuffle", "Rise", "Custom Script"])
current=modelist[0]
#Making the top widgets for changing the modes dynamically
def ChangeModeRight():
global current
modelist.append(modelist.pop(0))
current=modelist[0]
mode_info.configure(text=current)
dynamic()
def ChangeModeLeft():
global current
modelist.insert(0, modelist.pop())
current=modelist[0]
mode_info.configure(text=current)
dynamic()
frame_info = customtkinter.CTkFrame(master=frame_right, width=520, height=100)
frame_info.place(x=20,y=20)
mode_info = customtkinter.CTkLabel(master=frame_info,text=current, corner_radius=10, width=320,
height=50,
fg_color=("white", "gray38"))
mode_info.place(x=100,y=25)
play_icon =Image.open(resource("Assets/Icons/right_icon.png")).resize((20, 20), Image.Resampling.LANCZOS)
left_but = customtkinter.CTkButton(master=frame_info, image=ImageTk.PhotoImage(play_icon.transpose(Image.Transpose.FLIP_LEFT_RIGHT)), text="", width=50, height=50,
corner_radius=10, fg_color="gray40", hover_color="gray25", command=ChangeModeLeft)
left_but.place(x=20,y=25)
right_but = customtkinter.CTkButton(master=frame_info, image=ImageTk.PhotoImage(play_icon), text="", width=50, height=50,
corner_radius=10, fg_color="gray40", hover_color="gray25", command=ChangeModeRight)
right_but.place(x=450,y=25)
#Open video function
previous=""
def open_function():
global ofile, vid_image2, previous, duration, vid
ofile=tkinter.filedialog.askopenfilename(filetypes =[('Video', ['*.mp4','*.avi','*.mov','*.mkv','*gif']),('All Files', '*.*')])
#Check the video type
supported=["mp4","avi","mov","gif","mkv","wmv","m4v"]
if ofile:
previous=ofile
pass
else:
ofile=previous
return
if ofile[-3:].lower() in supported:
pass
else:
print("This file type is not supported!")
return
if len(os.path.basename(ofile))>=20:
showinput=os.path.basename(ofile)[:10]+"..."+os.path.basename(ofile)[-3:]
else:
showinput=os.path.basename(ofile)[:20]
#Change the thumbnail
button_open.configure(fg_color='grey', text=showinput)
outpng="Assets/thumbnail_cache/vid_thumbnail.jpg"
button_thumbnail.configure(image=vid_image)
if os.path.exists("Assets/thumbnail_cache/vid_thumbnail.jpg"):
os.remove("Assets/thumbnail_cache/vid_thumbnail.jpg")
subprocess.call(f'"{ffmpeg}" -loglevel quiet -ss 00:00:01 -t 00:00:01 -i "{ofile}" -qscale:v 2 -r 10.0 "{outpng}"', shell=True)
vid_image2 = ImageTk.PhotoImage(Image.open(outpng).resize((167, 100), Image.Resampling.LANCZOS))
button_thumbnail.configure(image=vid_image2)
vid=imageio.get_reader(ofile, 'ffmpeg')
#Update the widget parameters
position_frame.configure(to=vid.count_frames(), number_of_steps=vid.count_frames())
duration= vid.get_meta_data()['duration']
rangebar.max_val=duration
label_seconds2.configure(text="End: "+str(int(duration))+"s")
rangebar2.max_val=vid.count_frames()
label_showframe2.configure(text="End: "+str(vid.count_frames()))
shuf_slider.configure(to=vid.count_frames(), number_of_steps=vid.count_frames())
end_mosh.set(duration)
end_frame_mosh.set(vid.count_frames())
#Left Frame Widgets
label_appname = customtkinter.CTkLabel(master=frame_left,text="DATAMOSHER PRO")
label_appname.place(x=20,y=10)
vid_image = ImageTk.PhotoImage(Image.open("Assets/thumbnail_cache/offline_image.png").resize((167, 100), Image.Resampling.LANCZOS))
button_thumbnail = tkinter.Label(master=frame_left, image=vid_image, width=167, height=100, text="", bg="grey")
button_thumbnail.place(x=5,y=40)
add_video_image = ImageTk.PhotoImage(Image.open(resource("Assets/Icons/video_icon.png")).resize((20, 15), Image.Resampling.LANCZOS))
button_open = customtkinter.CTkButton(master=frame_left, image=add_video_image, text="IMPORT VIDEO", width=160, height=35,
compound="right", command=open_function)
button_open.place(x=10,y=170)
label_export = customtkinter.CTkLabel(master=frame_left,anchor="w",text="Export Format")
label_export.place(x=12,y=215)
optionmenu_1 = customtkinter.CTkOptionMenu(master=frame_left, fg_color="#4d4d4d",width=160, height=35, values=["mp4","avi","mov","mkv"])
optionmenu_1.set("mp4")
optionmenu_1.place(x=10,y=250)
settingpng = ImageTk.PhotoImage(Image.open(resource("Assets/Icons/settings.png")).resize((20, 20), Image.Resampling.LANCZOS))
#Setting Window
def close_top3():
window_UI.destroy()
uisetting.configure(state=tkinter.NORMAL)
def changeUI():
global window_UI
window_UI = customtkinter.CTkToplevel(self)
window_UI.geometry("410x200")
window_UI.resizable(width=False, height=False)
window_UI.title("App Preferences")
window_UI.iconphoto(False, icopath)
uisetting.configure(state=tkinter.DISABLED)
window_UI.wm_transient(self)
def check():
URL = "https://raw.githubusercontent.com/Akascape/Datamosher-Pro/Miscellaneous/VERSIONPY.txt"
try:
response = requests.get(URL)
open("Assets\\version\\VERSIONPY.txt", "wb").write(response.content)
except:
tkinter.messagebox.showinfo("Unable to connect!", "Unable to get information, please check your internet connection or visit the github repository.")
return
time.sleep(2)
with open("Assets\\version\\VERSIONPY.txt", 'r') as uf:
nver=float(uf.read())
if nver>currentversion:
tkinter.messagebox.showinfo("New Version available!","A new version "+ str(nver) +
" is available, \nPlease visit the github repository or the original download page!")
else:
tkinter.messagebox.showinfo("No Updates!", "You are on the latest version!")
def docs():
webbrowser.open_new_tab("https://github.com/Akascape/Datamosher-Pro/wiki")
def repo():
webbrowser.open_new_tab("https://github.com/Akascape/Datamosher-Pro")
logo_image = ImageTk.PhotoImage(Image.open(resource("Assets/Icons/Logo.png")).resize((210, 200), Image.Resampling.LANCZOS))
logo=customtkinter.CTkButton(master=window_UI, image=logo_image, width=205, height=105, border_width=0,
corner_radius=1, border_color="grey20", text="",fg_color=customtkinter.ThemeManager.theme["color"]["frame_low"][1],
hover_color=customtkinter.ThemeManager.theme["color"]["frame_low"][1])
logo.place(x=200,y=0)
visit=customtkinter.CTkButton(window_UI, text="Visit Repo", width=150, height=35,
corner_radius=10, fg_color=customtkinter.ThemeManager.theme["color"]["button"][1], hover_color="gray25",command=repo)
visit.place(x=20,y=30)
checkupdate=customtkinter.CTkButton(window_UI, text="Check For Updates", width=150, height=35,
corner_radius=10, fg_color=customtkinter.ThemeManager.theme["color"]["button"][1], hover_color="gray25",command=check)
checkupdate.place(x=20,y=80)
helpbutton=customtkinter.CTkButton(window_UI, text="Help", width=150, height=35,
corner_radius=10, fg_color=customtkinter.ThemeManager.theme["color"]["button"][1], hover_color="gray25",command=docs)
helpbutton.place(x=20,y=130)
version_label=customtkinter.CTkLabel(window_UI,anchor="w",width=1,fg_color=customtkinter.ThemeManager.theme["color"]["frame_low"][1],
text="v"+str(currentversion), bg_color=customtkinter.ThemeManager.theme["color"]["frame_low"][1])
version_label.place(x=365, y=2)
dvname=customtkinter.CTkLabel(window_UI,anchor="w",width=1,fg_color=customtkinter.ThemeManager.theme["color"]["frame_low"][1],
text="Developer: Akash Bora", bg_color=customtkinter.ThemeManager.theme["color"]["frame_low"][1])
dvname.place(x=30,y=170)
window_UI.protocol("WM_DELETE_WINDOW", close_top3)
uisetting = customtkinter.CTkButton(master=frame_left, image=settingpng, text="", width=40, height=40,
corner_radius=10, fg_color=customtkinter.ThemeManager.theme["color"]["text_disabled"][1],
hover_color="gray25", command=changeUI)
uisetting.place(x=10,y=470)
#Validation for entries
def only_numbers(char):
if ((char.isdigit()) or (char=="")) and (len(char)<=6):
return True
else:
return False
validation = self.register(only_numbers)
### Dynamimc widgets that change with modes ###
#Kill Frame Widget
def changekill(value):
label_kill.configure(text="Kill Frame Size: "+str(round(value,4)))
label_kill = customtkinter.CTkLabel(master=frame_right,anchor="w",text="Kill Frame Size: 0.6")
slider_kill= customtkinter.CTkSlider(master=frame_right, width=500,
from_=1,
to=0,
number_of_steps=100, command=changekill)
slider_kill.set(0.6)
#N-frameWidget
varn=tkinter.IntVar()
label_ctime = customtkinter.CTkLabel(master=frame_right,anchor='w',text="Frame Count:",width=1)
ctime=customtkinter.CTkEntry(frame_right,textvariable=varn, validate='key', validatecommand=(validation, '%P'),
placeholder_text="1",
width=100,
placeholder_text_color="grey70",
height=30,
border_width=2,
corner_radius=10)
varn.set(1)
#Keep frame & Keep audio widgets
keepaudio = customtkinter.CTkCheckBox(master=frame_right, text="Keep Audio", onvalue=1, offvalue=0)
keepframe = customtkinter.CTkCheckBox(master=frame_right, text="Keep First Frame", onvalue=1, offvalue=0)
#Count Frame widget
label_frame1 = customtkinter.CTkLabel(master=frame_right,anchor='w',text="Position Frame: 1",width=1)
def framework(value):
try:
if ofile:
pass
except:
return
label_frame1.configure(text="Position Frame: "+str(int(value)))
position_frame=customtkinter.CTkSlider(master=frame_right, width=500,progress_color="black", fg_color="black",
from_=1,
to=0,
number_of_steps=1, command=framework)
position_frame.set(1)
#Classic Rangebar
start_mosh = tkinter.DoubleVar()
end_mosh = tkinter.DoubleVar()
rangebar = RangeSliderH(frame_right, [start_mosh, end_mosh], Width=510, Height=63,
bgColor=customtkinter.ThemeManager.theme["color"]["frame_low"][1],line_color="black",
bar_color_outer=customtkinter.ThemeManager.theme["color"]["button"][0],
bar_color_inner=customtkinter.ThemeManager.theme["color"]["checkmark"][1],min_val=0, max_val=1, show_value= False,
line_s_color=customtkinter.ThemeManager.theme["color"]["button"][0])
label_seconds1 = customtkinter.CTkLabel(master=frame_right,anchor='w',text="Start: 0s",width=1)
label_seconds2 = customtkinter.CTkLabel(master=frame_right,anchor='w',text="End: 0s",width=1)
label_segment= customtkinter.CTkLabel(master=frame_right,anchor='w',text="Choose Segment:",width=1)
def show2(*args):
try:
if ofile:
pass
except:
return
label_seconds2.configure(text="End: "+str(int(end_mosh.get()))+"s")
def show(*args):
try:
if ofile:
pass
except:
return
label_seconds1.configure(text="Start: "+str(int(start_mosh.get()))+"s")
start_mosh.trace_add('write', show)
end_mosh.trace_add('write', show2)
#Delta entry widget
label_p = customtkinter.CTkLabel(master=frame_right,anchor='w',text="P-frames (Delta):",width=1)
label_segment= customtkinter.CTkLabel(master=frame_right,anchor='w',text="Choose Segment:",width=1)
varp=tkinter.IntVar()
delta=customtkinter.CTkEntry(frame_right,
placeholder_text="1",validate='key', validatecommand=(validation, '%P'),
width=100, textvariable=varp,
placeholder_text_color="grey70",
height=30,
border_width=2,
corner_radius=10)
varp.set(1)
#Frame Rangebar for repeat and rise modes
start_frame_mosh = tkinter.DoubleVar()
end_frame_mosh = tkinter.DoubleVar()
rangebar2 = RangeSliderH(frame_right, [start_frame_mosh, end_frame_mosh], Width=510, Height=63,
bgColor=customtkinter.ThemeManager.theme["color"]["frame_low"][1],line_color="black",
bar_color_outer=customtkinter.ThemeManager.theme["color"]["button"][0],
bar_color_inner=customtkinter.ThemeManager.theme["color"]["checkmark"][1],min_val=0, max_val=1, show_value= False,
line_s_color=customtkinter.ThemeManager.theme["color"]["button"][0])
label_showframe1 = customtkinter.CTkLabel(master=frame_right,anchor='w',text="Start Frame: 0",width=1)
label_showframe2 = customtkinter.CTkLabel(master=frame_right,anchor='w',text="End: 0",width=1)
label_segment2= customtkinter.CTkLabel(master=frame_right,anchor='w',text="Choose Frame Segment:",width=1)
def show3(*args):
try:
if ofile:
pass
except:
return
label_showframe2.configure(text="End: "+str(int(end_frame_mosh.get())))
def show4(*args):
try:
if ofile:
pass
except:
return
label_showframe1.configure(text="Start Frame: "+str(int(start_frame_mosh.get())))
start_frame_mosh.trace_add('write', show4)
end_frame_mosh.trace_add('write', show3)
#slider for echo mode
def midwork(value):
label_mid.configure(text="Start Point: "+str(round(value,1)))
label_mid = customtkinter.CTkLabel(master=frame_right,anchor='w',text="Start Point: 0.5",width=1)
mid_point=customtkinter.CTkSlider(master=frame_right, width=500,progress_color="black", fg_color="black",
from_=0,
to=1,
number_of_steps=10,command=midwork)
mid_point.set(0.5)
#Some options for sort mode
keepsort = customtkinter.CTkCheckBox(master=frame_right, text="Keep First Frames", onvalue=0, offvalue=1)
reversesort=customtkinter.CTkCheckBox(master=frame_right, text="Reverse", onvalue=False, offvalue=True)
#Options for ffglitch modes
hw_auto=customtkinter.CTkSwitch(master=frame_right,text="HW Acceleration \n(Auto)",onvalue=1, offvalue=0)
labelk=customtkinter.CTkLabel(master=frame_right,anchor='w',text="Keyframes:",width=1)
kf=customtkinter.CTkComboBox(master=frame_right,height=30, width=150,
values=["1000","100","10", "1"])
#Widget for Shuffle mde
def changeshuf(value):
shuf_label.configure(text="Chunk Size: "+str(int(value)))
shuf_label=customtkinter.CTkLabel(master=frame_right,anchor='w',text="Chunk Size: 1",width=1)
shuf_slider=customtkinter.CTkSlider(master=frame_right, width=500,
from_=1,
to=0,
number_of_steps=1, command=changeshuf)
shuf_slider.set(1)
#Widget for Fluid mode
def changefluid(value):
fluid_label.configure(text="Amount: "+str(int(value)))
fluid_label=customtkinter.CTkLabel(master=frame_right,anchor='w',text="Amount: 5",width=1)
slider_fluid=customtkinter.CTkSlider(master=frame_right, width=500,
from_=1,
to=20,
number_of_steps=100, command=changefluid)
slider_fluid.set(5)
#Stretch mode widget
v_h=customtkinter.CTkSwitch(frame_right,text="Horizontal Stretch", onvalue=1, offvalue=0)
#Button for motion transfer mode
def open_MT():
global vfile
vfile=tkinter.filedialog.askopenfilename(filetypes =[('Vector File', ['*.mp4','*.avi','*.mov','*.mkv']),('All Files', '*.*')])
if vfile:
mt_button.configure(fg_color='grey', text=os.path.basename(vfile))
else:
return
mt_button=customtkinter.CTkButton(master=frame_right, text="OPEN VIDEO", width=520, height=30,
compound="right",command=open_MT)
#Button for custom script mode
scriptfile=''
def open_script():
global scriptfile
scriptfile=tkinter.filedialog.askopenfilename(filetypes =[('Script File', ['*.js','*.py']),('All Files', '*.*')])
if scriptfile:
scriptbutton.configure(fg_color='grey', text=os.path.basename(scriptfile))
else:
scriptbutton.configure(fg_color=customtkinter.ThemeManager.theme["color"]["button"], text='OPEN SCRIPT')
scriptfile=''
scriptbutton=customtkinter.CTkButton(master=frame_right, text="OPEN SCRIPT", width=520, height=30,
compound="right",command=open_script)
#Dynamic UI functions for each widget
def rangeslider(x):
if x==1:
rangebar.place(x=20,y=210)
label_seconds1.place(x=25,y=200)
label_seconds2.place(x=470,y=200)
label_segment.place(x=25,y=170)
else:
rangebar.place_forget()
label_segment.place_forget()
label_seconds1.place_forget()
label_seconds2.place_forget()
def rangeslider2(x):
if x==1:
if (current=="Rise"):
rangebar2.place(x=20,y=260)
label_showframe1.place(x=25,y=250)
label_showframe2.place(x=470,y=250)
label_segment2.place(x=25,y=220)
else:
rangebar2.place(x=20,y=210)
label_showframe1.place(x=25,y=200)
label_showframe2.place(x=470,y=200)
label_segment2.place(x=25,y=170)
else:
rangebar2.place_forget()
label_showframe1.place_forget()
label_showframe2.place_forget()
label_segment2.place_forget()
def mid(x):
if x==1:
mid_point.place(x=20,y=210)
label_mid.place(x=25,y=170)
else:
mid_point.place_forget()
label_mid.place_forget()
def killoption(x):
if x==1 or x==2 or x==3:
label_kill.place(x=25,y=170)
slider_kill.place(x=20,y=200)
else:
label_kill.place_forget()
slider_kill.place_forget()
def positionslider(x):
if x==1:
label_frame1.place(x=25,y=230)
position_frame.place(x=20,y=260)
else:
label_frame1.place_forget()
position_frame.place_forget()
def framekeep(x):
if x==1:
keepframe.place(x=250,y=300)
elif x==2:
keepframe.place(x=250,y=240)
else:
keepframe.place_forget()
def audiokeep(x):
if x==1:
keepaudio.place(x=400,y=300)
elif x==2:
keepaudio.place(x=400,y=240)
else:
keepaudio.place_forget()
def ctimes(x):
if x==1:
ctime.place(x=110,y=300)
label_ctime.place(x=25,y=300)
else:
ctime.place_forget()
label_ctime.place_forget()
def pdelta(x):
if x==1:
delta.place(x=135,y=275)
label_p.place(x=25,y=275)
if current=="Repeat":
varp.set(5)
elif x==2:
delta.place(x=135,y=170)
label_p.place(x=25,y=170)
if current=="Glide":
varp.set(5)
else:
delta.place_forget()
label_p.place_forget()
def sortoptions(x):
if x==1:
keepsort.place(x=30, y=170)
reversesort.place(x=300, y=170)
else:
keepsort.place_forget()
reversesort.place_forget()
def ffgassist(x):
if x==1:
hw_auto.place(x=25, y=170)
labelk.place(x=300,y=170)
kf.place(x=380,y=170)
else:
hw_auto.place_forget()
labelk.place_forget()
kf.place_forget()
def shuf(x):
if x==1:
shuf_label.place(x=25,y=220)
shuf_slider.place(x=20,y=250)
else:
shuf_label.place_forget()
shuf_slider.place_forget()
def fluidwidget(x):
if x==1:
fluid_label.place(x=25,y=220)
slider_fluid.place(x=20,y=250)
else:
fluid_label.place_forget()
slider_fluid.place_forget()
def h_v(x):
if x==1:
v_h.place(x=25,y=220)
else:
v_h.place_forget()
def mtwid(x):
if x==1:
mt_button.place(x=20,y=230)
else:
mt_button.place_forget()
def custom(x):
if x==1:
scriptbutton.place(x=20,y=230)
else:
scriptbutton.place_forget()
#Main Function to update the widgets
def dynamic():
global current, showwidgets
allwidgets=[audiokeep, positionslider, killoption, framekeep,
ctimes, pdelta, rangeslider, rangeslider2, mid, sortoptions, ffgassist, fluidwidget, h_v, custom, mtwid, shuf]
for i in allwidgets:
i(0)
showwidgets=[]
if (current=="Bloom") or (current=="Pulse") or (current=="Pulse") or(current=="Overlap"):
showwidgets=[audiokeep, positionslider, killoption, framekeep, ctimes]
u=1
elif (current=="Jiggle"):
showwidgets=[positionslider, audiokeep, killoption, framekeep]
u=1
elif (current=="Void") or (current=="Reverse") or (current=="Invert") or (current=="Random"):
showwidgets=[killoption,audiokeep, framekeep]
u=2
elif (current=="Classic"):
showwidgets=[rangeslider, pdelta]
u=1
elif (current=="Glide"):
showwidgets=[pdelta]
u=2
elif (current=="Repeat") or (current=="Rise"):
if (current=="Rise"):
showwidgets=[rangeslider2, ffgassist]
else:
showwidgets=[rangeslider2, pdelta]
u=1
elif (current=="Echo"):
showwidgets=[mid]
u=1
elif (current=="Sort"):
showwidgets=[sortoptions]
u=1
elif ((current=="Buffer") or (current=="Sink") or (current=="Mirror") or (current=="Shear") or (current=="Noise")
or (current=="Delay") or (current=="Slam Zoom") or (current=="Invert-Reverse") or (current=="Shift") or (current=="Zoom")
or (current=="Slice")or (current=="Vibrate") or (current=="Stop")):
showwidgets=[ffgassist]
u=1
elif (current=="Fluid"):
showwidgets=[ffgassist, fluidwidget]
u=1
elif (current=="Stretch"):
showwidgets=[ffgassist, h_v]
u=1
elif (current=="Motion Transfer"):
showwidgets=[ffgassist, mtwid]
u=1
elif (current=="Custom Script"):
showwidgets=[ffgassist, custom]
u=1
elif (current=="Shuffle"):
showwidgets=[ffgassist, shuf]
u=1
for widgets in showwidgets:
widgets(u)
dynamic()
keepframe.select()
#autosave video function
def savename():
global sfile
if ofile:
try:
sfile=ofile[:-4]+"_datamoshed_"+current+'.'+optionmenu_1.get()
nf=0
while os.path.exists(sfile):
nf=nf+1
sfile=ofile[:-4]+"_datamoshed_"+current+'('+str(nf)+')'+'.'+optionmenu_1.get()
except:
sfile=""
#A function that will thread the main mosh function to separate the processes
def Threadthis():
global varp, varn
if delta.get()=='' or delta.get()<'1':
varp.set(1)
if ctime.get()=='' or ctime.get()<'1':
varn.set(1)
threading.Thread(target=Do_the_mosh).start()
#Converter function
def ffmpeg_convert(inputpath, parameters, outputpath, extra=''):
subprocess.call(f'"{ffmpeg}" {extra} -i "{inputpath}" {parameters} -y "{outputpath}"', shell=True)
#Main Function of the whole program
def Do_the_mosh():
global ofile, sfile, param, param2
button_mosh.configure(state=tkinter.DISABLED)
if previous=="":
tkinter.messagebox.showinfo("No Video imported!","Please import a video file!")
button_mosh.configure(state=tkinter.NORMAL)
return
try:
savename()
ProcessLabel.configure(text='STEP 1/3 CONVERTING...')
param="-c:v libx264 -preset medium -b:v 2M -minrate 2M -maxrate 2M -bufsize 2M" #Add other ffmpeg parameters in this line only
if ((current=="Bloom") or (current=="Pulse") or (current=="Pulse") or(current=="Overlap")
or (current=="Void") or (current=="Reverse") or (current=="Invert") or (current=="Random") or (current=="Jiggle")):
ifile=sfile[:-4]+".avi"
ffmpeg_convert(ofile,param,ifile)
ProcessLabel.configure(text='STEP 2/3 MOSHING...')
mfile=sfile[:-4]+"_corrupted.avi"
tomato.mosh(infile=ifile, outfile=mfile, m=current.lower(), c=varn.get(), n=int(position_frame.get()), k=round(slider_kill.get(),4), a=keepaudio.get(), f=keepframe.get())
time.sleep(1)
os.remove(ifile)
ProcessLabel.configure(text='STEP 3/3 FIXING THE CORRUPTED FILE...')
ffmpeg_convert(mfile,param,sfile)
os.remove(mfile)
elif ((current=="Classic") or (current=="Repeat") or (current=="Glide") or (current=="Sort") or (current=="Echo")):
param="-bf 0 -b 10000k" #Add other ffmpeg parameters in this line only for the above modes
ifile=sfile[:-4]+".avi"
ffmpeg_convert(ofile,param,ifile)
ProcessLabel.configure(text='STEP 2/3 MOSHING...')
mfile=sfile[:-4]+"_corrupted.avi"
if current=="Classic":
classic.Datamosh(ifile, mfile,s=int(start_mosh.get()),e=int(end_mosh.get()),p=varp.get(), fps=vid.get_meta_data()['fps'])
elif current=="Repeat":
repeat.Datamosh(ifile, mfile, s=int(start_frame_mosh.get()), e=int(end_frame_mosh.get()), p=varp.get(), fps=vid.get_meta_data()['fps'])
elif current=="Glide":
pymodes.library.glide(varp.get(), ifile, mfile)
elif current=="Sort":
pymodes.library.avi_sort(ifile, mfile, mode=keepsort.get(), rev=reversesort.get())
elif current=="Echo":
pymodes.library.process_streams(ifile, mfile, mid=round(mid_point.get(),1))
os.remove(ifile)
ProcessLabel.configure(text='STEP 3/3 FIXING THE CORRUPTED FILE...')
ffmpeg_convert(mfile,param,sfile)
os.remove(mfile)
else:
time.sleep(1)
ProcessLabel.configure(text='STEP 2/3 MOSHING...')
mfile=sfile[:-4]+"_corrupted.mpg"
if current=="Fluid":
basic_modes.library(ofile, mfile, mode=3, fluidity=int(slider_fluid.get()), gop=kf.get())
elif current=="Stretch":
basic_modes.library(ofile, mfile, mode=2, vh=v_h.get(), gop=kf.get())
elif current=="Motion Transfer":
if vfile:
basic_modes.library(ofile, mfile, mode=1, extract_from=vfile, gop=kf.get())
else:
tkinter.messagebox.showinfo("No Vector File imported!", "Please choose the video from where you want to extract the vector motion.")
button_mosh.configure(state=tkinter.NORMAL)
ProcessLabel.configure(text='Choose any secondary video file for transfering the vectors!')
return
elif current=="Shuffle":
basic_modes.library(ofile, mfile, mode=4, size=int(shuf_slider.get()), gop=kf.get())
elif current=="Rise":
basic_modes.library(ofile, mfile, mode=5, s=int(start_frame_mosh.get()), e=int(end_frame_mosh.get()-start_frame_mosh.get()), gop=kf.get())
elif current=="Custom Script":
external_script.mosh(ofile, mfile, mode=1, scriptfile=scriptfile, gop=kf.get())
else:
external_script.mosh(ofile, mfile, mode=2, effect=current, gop=kf.get())
ProcessLabel.configure(text='STEP 3/3 FIXING THE CORRUPTED FILE...')
if hw_auto.get()==1:
hw_type=' -hwaccel auto '
else:
hw_type=''
ffmpeg_convert(mfile,param,sfile,extra=hw_type)
os.remove(mfile)
except:
pass
#Check the result and complete the task
if os.path.exists(sfile):
tkinter.messagebox.showinfo("Exported!", "File exported successfully, \nFile Location:" +str(sfile))
ProcessLabel.configure(text="Last used: "+current)
button_mosh.configure(state=tkinter.NORMAL)
else:
tkinter.messagebox.showerror("Oops!", "Something went wrong! \nPlease recheck the settings and try again.")
ProcessLabel.configure(text='Recheck the settings and try again!')
button_mosh.configure(state=tkinter.NORMAL)
#Bottom Part
ProcessLabel = customtkinter.CTkLabel(master=frame_right,
width=400, height=30,corner_radius=10,
text="START DATAMOSHING!", fg_color=("white", "gray38"))
ProcessLabel.place(x=20,y=430)
button_mosh = customtkinter.CTkButton(master=frame_right, height=30,width=110,corner_radius=10,
text="MOSH", command=Threadthis)
button_mosh.place(x=430,y=430)
self.mainloop()
#--------------------------------------------------------------------#

View File

@@ -1,9 +0,0 @@
#Read this to use the python version.
This version is comparitively lower in size and works the same inside python environment.
To use this version, just download the zip file and extract this folder and then double
click on the Datamosher Pro v1.2.py to open the program, then use the software as describes in the Readme.md
or click the "i" button inside the software.
In this version, the modules will be automatically downloaded and ffmpeg path will be pre-specified, so no need to worry about modules and stuff
(specially for windows user). Make sure to restart the program after completing the automatic module installation.
Do not delete or move any assets or folder that are linked with the main file or else it will show error.
This is all about the python version, you can now Datamosh your videos!

127
Python Version/Setup.py Normal file
View File

@@ -0,0 +1,127 @@
#Automatic Setup for Datamosher-Pro
#Author: Akash Bora
#Importing some built in modules
import subprocess
import pkg_resources
import sys
import time
import os
import shutil
from zipfile import ZipFile
DIRPATH = os.path.dirname(os.path.realpath(__file__))
#Checking the required folders
folders= ["Assets","FFglitch","DatamoshLib","pymosh"]
missingfolder=[]
for i in folders:
if not os.path.exists(i):
missingfolder.append(i)
if missingfolder:
print("These folder(s) not available: "+str(missingfolder))
print("Download them from the repository properly")
sys.exit()
else:
print("All folders available!")
#Checking required modules
required = {'imageio', 'imageio-ffmpeg', 'numpy', 'customtkinter', 'pillow', 'rangeslider', 'requests'}
installed = {pkg.key for pkg in pkg_resources.working_set}
missing = required - installed
missingset=[*missing,]
#Download the modules if not installed
if missing:
res=input("Some modules are not installed \n do you want to download and install them? (Y/N): ")
while not ((res=="Y") or (res=="y") or (res=="N") or (res=="n")):
print("Please choose a valid option!")
res=input("Some modules are not installed \n do you want to download and install them? (Y/N): ")
if res=="Y" or res=="y":
try:
print("Installing modules...")
for x in range(len(missingset)):
y=missingset[x]
if sys.platform.startswith("win"):
subprocess.call('python -m pip install '+y, shell=True)
else:
subprocess.call('python3 -m pip install '+y, shell=True)
except:
print("Unable to download! \nThis are the required ones: "+str(required)+"\nUse 'pip install module_name' to download the modules one by one")
time.sleep(3)
sys.exit()
elif res=="N" or res=="n":
print("Without the modules you can't use this program. Please install them first! \nThis are the required one: "+str(required)
+"\nUse 'pip install module_name' to download modules one by one")
time.sleep(3)
sys.exit()
else:
print("All modules installed!")
#Check FFglitch Status
def checkffglitch():
print("Checking FFglitch:")
print("Running ffgac...")
ffgac=str(DIRPATH).replace(os.sep, '/')+"/FFglitch/ffgac"
ffedit=str(DIRPATH).replace(os.sep, '/')+"/FFglitch/ffedit"
try:
subprocess.Popen(f'"{ffgac}" -version', shell=True)
except:
print("permission denied! Please give permission to ffgac to execute.")
time.sleep(1)
print("Running ffedit...")
try:
subprocess.Popen(f'"{ffedit}" -version', shell=True)
except:
print("permission denied! Please give permission to ffedit to execute.")
time.sleep(1)
print("Done...")
#Download ffglitch if not available
if (os.path.exists("FFglitch/ffgac") or os.path.exists("FFglitch/ffgac.exe")) and (os.path.exists("FFglitch/ffedit") or os.path.exists("FFglitch/ffedit.exe")):
checkffglitch()
else:
print("ffgac/ffedit not found inside ffglitch folder, you cannot run the ffglitch modes without these programs")
res2=input("Do you want to download ffglitch now? (Y/N): ")
while not ((res2=="Y") or (res2=="y") or (res2=="N") or (res2=="n")):
print("Please choose a valid option!")
res2=input("Do you want to download ffglitch now? (Y/N): ")
if res2=="Y" or res2=="y":
print("Downloading FFglitch...(size: approx 17MB)")
if sys.platform.startswith("win"): #download ffglitch for windows
URL = "https://github.com/Akascape/FFglitch-0.9.3-executables/releases/download/zip-packages/ffglitch-0.9.3-win64.zip"
elif sys.platform.startswith("linux"): #download ffglitch for linux
URL = "https://github.com/Akascape/FFglitch-0.9.3-executables/releases/download/zip-packages/ffglitch-0.9.3-linux64.zip"
else: #download ffglitch for mac
URL = "https://github.com/Akascape/FFglitch-0.9.3-executables/releases/download/zip-packages/ffglitch-0.9.3-mac64.zip"
try:
try:
import requests
response = requests.get(URL)
open("FFglitch//ffglitch.zip", "wb").write(response.content)
except:
print("Unable to download ffglitch from site! Check your connection or download it manually from https://github.com/Akascape/FFglitch-0.9.3-executables \nand paste the files (ffgac and ffedit) inside FFglitch folder.")
time.sleep(3)
sys.exit()
time.sleep(1)
print("Exctracting the files...")
try:
with ZipFile('FFglitch/ffglitch.zip', 'r') as zip:
zip.extractall('FFglitch/')
except:
print("Failed to extract ffglitch.zip, please extract it manually in the FFglitch folder.")
time.sleep(3)
sys.exit()
if os.path.exists("FFglitch/ffgac") or os.path.exists("FFglitch/ffgac.exe"):
os.remove("FFglitch//ffglitch.zip")
time.sleep(1)
checkffglitch()
print("FFglitch setup complete!")
except:
print("Something went wrong!")
elif res2=="N" or res2=="n":
print("ffglitch modes cannot run without ffgac and ffedit, download them manually and paste them inside the FFglitch folder.")
#Everything done!
print("Setup Complete!")
time.sleep(5)
sys.exit()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1,7 @@
Copyright (c) 2011 - 2014 Joe Friedl
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1 +0,0 @@

View File

@@ -1 +0,0 @@

164
Readme.md
View File

@@ -1,50 +1,124 @@
[![header](https://capsule-render.vercel.app/api?type=waving&color=timeGradient&height=300&section=header&text=DATAMOSHER%20PRO&fontSize=90&fontAlignY=30&desc=Automated%20Glitching!&descAlign=80&descSize=30&animation=scaleIn)](https://akascape.gumroad.com/l/Datamosher-Pro)
# Datamosher Pro
<br><b>Datamoshing is a cool video effect and if you also want to create this glitch effect with your videos, you are in the right place!</b>
<br><p align='center'><img src="https://user-images.githubusercontent.com/89206401/141642297-7c62cf6f-7024-430f-88a2-c9cbbf0dc655.png"></p>
<br>➤Why I made this?
<br>I was also looking for some good datamoshing software and I found that you have to either use those old softwares like Avidemux or have to look for some paid plugins, so I created my own GUI based application that is Datamosher Pro which is a free project. It contains 13 different effects which can replicate any type of datamoshing style. With Datamosher Pro, you can quickly and easily datamosh your videos (supports mp4, gif, avi, mkv etc).
<b>Datamoshing is a cool video effect and if you want to achieve this glitch with your videos, then you are in the right place!
<br><img align="right" src="https://user-images.githubusercontent.com/89206401/141642297-7c62cf6f-7024-430f-88a2-c9cbbf0dc655.png" width="300">
<br> Datamosher Pro is an automated glitching application for free (python version)! With Datamosher Pro you can quickly and easily datamosh your videos! </b> <br>
### Why I made this?
I was also looking for some good datamoshing software and I found that you have to either use those old softwares like Avidemux or have to look for some paid plugins, so I created my own python based application 'Datamosher Pro'. It contains `30+` different effects which can replicate any type of datamoshing style.
It comes in two version, one paid and one basic free source code version.
# DOWNLOAD
### <p align='center'> Support Datamosher-Pro Development by purchashing its executable version for *windows* on Gumroad which have a modern UI and lots of other features. It will be really helpful!
### <p align='center'> MODERN VERSION (SEE DETAILS)
<br> <p align='center'> [<img src="https://img.shields.io/badge/WINDOWS-DATAMOSHER_PRO-informational?style=for-the-badge&logo=Microsoft&logoColor=blue&color=007ec6" width="500">](https://akascape.gumroad.com/l/Datamosher-Pro) </br>
<br>
### <p align='center'> FREE BASIC SOURCE CODE VERSIONS
<br> <p align='center'> [<img src="https://img.shields.io/badge/Python_Version-Windows-informational?style=flat&logo=Microsoft&logoColor=blue&color=1bdce3" width=300>](https://github.com/Akascape/Datamosher-Pro/releases/download/Datamosher_Prov1.7/Datamosher_Pro-python_version-win.zip)
<br> <p align='center'> [<img src="https://img.shields.io/badge/Python_Version-MacOS-informational?style=flat&logo=apple&logoColor=b0b5b9&color=b2b7bb" width=300 height=35>](https://github.com/Akascape/Datamosher-Pro/releases/download/Datamosher_Prov1.7/Datamosher_Pro-python_version-mac.zip)
<br> <p align='center'> [<img src="https://img.shields.io/badge/Python_Version-Linux-informational?style=flat&logo=linux&logoColor=black&color=eaea4a" width=300 height=35>](https://github.com/Akascape/Datamosher-Pro/releases/download/Datamosher_Prov1.7/Datamosher_Pro-python_version-linux.zip) <br> Don't forget to give a ⭐ :) </p>
# How to Install?
You can either use the python based version for viewing logs and changing source code if you want, but if you are looking for faster renders then download the windows executable version of Datamosher Pro from the release page:
<br>[DOWNLOAD⬇](https://github.com/Akascape/Datamosher-Pro/releases/tag/Datamosher_Prov1.3.exe)
<br>There is no malware or difference in the exe version as the same python version is converted to .exe using Auto-Py-To-Exe Converter.
<br>Note: For python users, make sure you have all the assets saved in the same folder. Modules will be automatically downloaded if not installed, so no need to worry.
- For those who are using the python-version,
<br> Download the correct python version (3.10+ recomended) and make sure you have python installed properly. Extract the zip file and open the "datamosher_pro-python_version" folder and just run that Datamosher-Pro.py file. If any module error pops up then just click on yes and the required modules will get downloaded automatically. You can also do that manually if it doesn't work. Then it is ready to use! (No python skills needed)
- For the executable version, just extract the downloaded zip file and run the Datamosher_Pro.exe application.
# How to Use?
•Input the video file first (supported formats- mp4, gif, avi + more will be added if you demand")
<br>•Choose the desired datamosh mode, then select the export format"
<br>•Use advance options to get more accurate results"
<br>•Click on the datamosh button, then wait for a few seconds"
<br>•Then your video will be moshed, see the video in the directory"
<br>NOTE: audio glitching is not available for all modes!
# Effects Info:
c=Glitch Size; n=Frame Frequency
<b>
<br>All effects:
<br>•Glide - duplicates number of n frames and show it as a flow before reaching the p-frame (NEW)
<br>•Sort - sorts video frames by data size in a rapid movement (NEW)
<br>•Echo - duplicates the single video and apply the mosh in the midpoint (NEW)
<br>•Shake - shakes the pixel movement throughout the video (NEW)
<br>•Classic - uses the traditional ffmpeg way to change the files and then remove the i-frames
<br>•Random - randomizes frame order
<br>•Reverse - reverse frame order
<br>•Invert - switches each consecutive frame witch each other
<br>•Bloom - duplicates c times p-frame number n
<br>•Pulse - duplicates groups of c p-frames every n frames
<br>•Overlap - copy group of c frames taken from every nth position
<br>•Jiggle - take frame from around current position. n parameter is spread size.
<br>•Void - gives a clean output but with distorted pixels
</b>
For the basic python version:
• Input the video file first (supported formats- mp4, gif, avi, mov, mkv, wmv)
<br>• Choose the desired datamosh mode and the export format (mp4 is recommended)
<br>• Use the advanced options to get more accurate results
<br>• Check/uncheck the highest quality box for quality adjustments
<br>• Then simply click on the datamosh button and wait for a few seconds
<br>• After conversions, your video will be moshed and saved in the same directory
**Important Tip: Press "q" key in the command line whenever you want to end a long running conversion process.**
### A documentation is also available in the [Wiki](https://github.com/Akascape/Datamosher-Pro/wiki) page
## Gallery
[![forthebadge](https://forthebadge.com/images/badges/check-it-out.svg)](https://github.com/Akascape/Datamosher-Pro/blob/Datamosher-Pro-v1.7/Demos.md)
# Effects Info
### Effects List available in the python version:
<br> TIP: Major effects used for datamoshing are Classic, Bloom, Glide, Repeat, Motion Transfer, Rise, Fluid
<br>
<br>➤How to use Advanced Options?
<br>The advanced tab is very useful and you can use it to get accurate results.
<br>•Glitch Size - tells how often to glitch (for modes that support it)
<br>•Frame Frequency - tells how many frames to apply in the glitch (for modes that support it)
<br>•First Frame - tells whether to keep first video frames
<br>•Kill frames - tells max framesize to kill while cleaning
<br>You can try experimenting with the values and see the results.
# User Interface:
<br><img src="https://user-images.githubusercontent.com/89206401/141643709-73b68644-5697-4c39-8be0-5384dc391fa4.png">
<br>➤More Info about this project:
<br>The effects are inspired from ItsKaspar's [tomato.py](https://github.com/itsKaspar/tomato) and Joe Friedl's [pymosh](https://github.com/grampajoe/pymosh) which can only handle .avi file structures, but in Datamosher Pro you can use any video file type including mp4, avi, gif, mov, mkv +more. The files are first converted to avi file using Imageio-ffmpeg without losing much quality and then the effect is applied and then again the corrupted file is converted to stable version using the same process so that the output video can be directly used in other softwares for editing without any error. A raw file option is also available if needed. You will not find this type of GUI program anywhere with so many free effects, I hope there is no error in the program but if you find any bug then raise an issue. You can also help to make new datamosh effects. All the logo and designs are created by me. <br>Thanks! Made by Akash Bora (a.k.a Akascape).
| Effect Name | Description |
| ----------------| --------------------------------------------------------------------- |
| Rise | another classic i frames removal effect|
| Shuffle | randomly shuffles chunks of video frames with the classic ffglitch datamosh (unstable with short videos)|
| Buffer | creates ring buffers to mosh|
| Delay | another delaying ffglitch effect|
| Invert-Reverse | applies both inverse and reverse mode|
| Mirror | does the mosh with ffglitch but with mirrored X|
| Noise | makes large noisy mosh|
| Shear | tilt the video clockwise and merges the mosh|
| Shift | shifts random blocks of the video upwards|
| Sink | drowns the next frame of the video in the previous one|
| Slam Zoom | applies zoom with the sink effect|
| Slice | randomly zooms and slices the video in parts|
| Stop | similar to sink but stops the XY values|
| Vibrate | works as a randomizer|
| Zoom | simply zooms inside the moshed video|
| Fluid | this is a ffglitch's average effect which gives a smooth liquid type motion in the video|
| Repeat | repeats a series of p frames which gives the melting effect|
| Motion Transfer | a powerful ffglitch feature that can transfer the vector motion data from one video to another. Make sure both videos have the same resolution, this effect is also known as style transfer/swap motion.|
| Stretch | stretches the p-frames horizontally and vertically|
| Glide | duplicates number of n frames and show it as a flow before reaching the p-frame|
| Sort | sorts video frames by data size in a rapid movement|
| Echo | duplicates the single video and apply the mosh effect in the midpoint|
| Shake | randomly shakes the pixels/blocks throughout the video|
| Classic | uses the traditional ffmpeg way to convert and corrupt the video by removing the i-frames|
| Random | randomizes frame order|
| Reverse | reverses frame order|
| Invert | switches each consecutive frame witch each other|
| Bloom | duplicates c times p-frame number n (c=Glitch Size; n=Frame Frequency)|
| Pulse | duplicates groups of c p-frames every n frames|
| Overlap | copy group of c frames taken from every nth position|
| Jiggle | take frame from around current position. n parameter is spread size|
| Void | gives a clean output but with distortion|
## More effects including these ones are all available in the paid version.
### How to use Advanced Options (Python version)?
The advanced tab is very useful if you want accurate results. The options are:
<br>• `Glitch Size` - tells how long/often to glitch per part (depends on the mode)
<br>• `Frame Frequency` - tells how many frames to apply/repeat in the glitch
<br>• `Ignore Frame` - tells whether to keep the first video frame
<br>• `Kill Frames` - tells max framesize to kill while cleaning (For shuffle/rise mode the kill frame is number of frames that will be deleted)
<br>• `First Frame` - tells the starting frame for the glitch
<br>• `Last Frame` - tells the ending frame for the glitch
<br>• `Start(sec)` - tells the starting time (in seconds) for the glitch
<br>• `End(sec)` - tells the ending time (in seconds) for the glitch
<br>• `Mid Point (Echo mode only)` - tells the point from where the video to repeat(echo)
<br>
<br>DATAMOSH MADE EASY!
<br>Current Version=1.3
<br>NOTE:
<br>- Some modes may not support all the 4 advanced options.
<br>- You can try experimenting with the options but don't put huge values.
<br>- Audio glitching is only available in few modes like classic and repeat.
# UI (BASIC PYTHON VERSION)
| Windows | Linux | MacOS |
| ---------| ------- | ------- |
| ![Windows UI](https://user-images.githubusercontent.com/89206401/142208408-6970448d-fe9d-4e60-aac6-21809aefcfca.png) | ![Linux UI](https://user-images.githubusercontent.com/89206401/168416728-fc9bc8e5-ce34-40c8-9222-bf9986dbb280.png) | ![Mac UI](https://user-images.githubusercontent.com/89206401/168416751-73658dcf-506f-4166-933b-e3f3cb43194c.png) |
# UI (PAID VERSION ONLY WINDOWS)
### This modern UI is available in the paid version only.
![newthemes](https://user-images.githubusercontent.com/89206401/174493211-febc4193-1090-4dbb-8eea-23d7d10e3741.png)
## How It Works?
The main issue with datamoshing is conversion of corrupted files but with Datamosher Pro you can use any video file and it will export an usable datamoshed file. But I still recomend everyone to use MP4 videos. The video is first converted to the required file format using ffmpeg (distributed **externally** with Imageio module) and then the effect is applied and the corrupted file is converted back to stable version using the same process so that the output video can directly be used in other editing softwares. All the unnecessary temp files are removed automatically.
### Read these guides for more details about the python version:
<br> [![Read](https://img.shields.io/badge/Guide-1-orange)](https://akascape.gumroad.com/p/datamosher-pro-guide) [![Read](https://img.shields.io/badge/Guide-2-green)](https://akascape.gumroad.com/p/datamosher-pro-guide-2)
## Conclusion
You will not find this type of software anywhere with so many effects only for datamoshing. This program can be your companion while editing cool glitchy videos :)
<br> As it is a new piece of software some users may find some errors and bugs (specially in the python version), but updates will be on their way.
<br>The effects are all inspired from ItsKaspar's [tomato.py](https://github.com/itsKaspar/tomato), Joe Friedl's [pymosh](https://github.com/grampajoe/pymosh) and [FFglitch](https://ffglitch.org/).
All the logos and designs are created by me. <br>-Akash Bora
<br>
## License
[<img src="https://user-images.githubusercontent.com/89206401/168461242-884f25ce-eb67-406a-9d98-cf8d0f28cb43.png" width=100>](https://github.com/Akascape/Datamosher-Pro/blob/Datamosher-Pro-v1.7/LICENSE)
Only the python version is licensed under MIT. The executable windows version is different and closed source.
Note that the **FFglitch** part provided in the *releases* is not placed under this license. It is itself an independent program provided without any **modification**. When distributing an application with this package, it must be taken into account that multiple licenses are involved. See the [FFglitch's github page](https://github.com/ramiropolla/ffglitch-core/tree/master) for further details. (That source code is freely available there)
<br>
## Follow me
[<img src="https://img.shields.io/badge/-Github-informational?style=flat&logo=github&logoColor=black&color=grey">](https://github.com/Akascape)
[<img src="https://img.shields.io/badge/-Reddit-informational?style=flat&logo=reddit&logoColor=black&color=orange">](https://www.reddit.com/user/Akascape)
[<img src="https://img.shields.io/badge/-YouTube-informational?style=flat&logo=youtube&logoColor=black&color=red">](https://www.youtube.com/channel/UC7naboenYq9FAo80aPUkqSw)
[<img src="https://img.shields.io/badge/-Twitter-informational?style=flat&logo=twitter&logoColor=black&color=blue">](https://twitter.com/Akascape)
<br> DATAMOSHING MADE EASY!
### Current Version-1.7
<br> [![forthebadge made-with-python](http://ForTheBadge.com/images/badges/made-with-python.svg)](https://www.python.org/) [![forthebadge](https://forthebadge.com/images/badges/built-with-love.svg)](https://github.com/Akascape/Datamosher-Pro) [![forthebadge](https://forthebadge.com/images/badges/not-a-bug-a-feature.svg)](https://github.com/Akascape/Datamosher-Pro)
[![footer](https://capsule-render.vercel.app/api?type=rect&color=timeGradient&height=2)](https://opensourcelibs.com/lib/capsule-render)