97 Commits

Author SHA1 Message Date
Akascape
92446525e9 Update Readme.md 2021-11-17 14:22:09 +05:30
Akascape
23898d12a0 Update Readme.md 2021-11-17 14:21:49 +05:30
Akascape
aa02f643fb Update Readme.md 2021-11-14 13:18:57 +05:30
Akascape
7b7eb84333 Update Readme.md 2021-11-13 18:00:17 +05:30
Akascape
09f787a635 Update Readme.md 2021-11-13 17:59:59 +05:30
Akascape
56a498ab15 Update Readme.md 2021-11-13 17:59:25 +05:30
Akascape
d94da16c30 Update Readme.md 2021-11-13 17:56:13 +05:30
Akascape
1568a58195 Update Readme.md 2021-11-13 17:55:48 +05:30
Akascape
af607eb157 Update Readme.md 2021-11-13 17:50:25 +05:30
Akascape
36af34b55d Update Readme.md 2021-11-13 17:33:49 +05:30
Akascape
a9dd3dd677 Update Readme.md 2021-11-13 17:33:30 +05:30
Akascape
1fc8caaec9 Update Readme.md 2021-11-13 17:31:56 +05:30
Akascape
54f79a2ed6 Update Readme.md 2021-11-13 17:30:52 +05:30
Akascape
81144da0f9 Update Readme.md 2021-11-13 17:29:46 +05:30
Akascape
51c96258e9 Update Readme.md 2021-11-13 17:29:32 +05:30
Akascape
eee6b5d4a4 Update Readme.md 2021-11-13 17:28:19 +05:30
Akascape
520dbe8349 Update Readme.md 2021-11-13 17:28:01 +05:30
Akascape
88f9923a0a Update Readme.md 2021-11-13 17:27:28 +05:30
Akascape
ce3aceb3ed Update Readme.md 2021-11-13 17:25:22 +05:30
Akascape
3ce55cecb7 Update Readme.md 2021-11-13 17:23:52 +05:30
Akascape
11b3248924 Update Readme.md 2021-11-13 17:23:30 +05:30
Akascape
57c25c0026 Update Readme.md 2021-11-13 17:20:23 +05:30
Akascape
b03823dbcd Update Readme.md 2021-11-13 17:18:32 +05:30
Akascape
9d071b723a Update Readme.md 2021-11-13 17:17:25 +05:30
Akascape
2e27e84732 Update Readme.md 2021-11-13 17:16:58 +05:30
Akascape
f79e8fc735 Update Readme.md 2021-11-13 17:15:36 +05:30
Akascape
d179113543 Update Readme.md 2021-11-13 17:15:17 +05:30
Akascape
d5ad710835 Update Readme.md 2021-11-13 17:14:47 +05:30
Akascape
943d64fb42 Update Readme.md 2021-11-13 17:14:19 +05:30
Akascape
de3a1fa7e1 Update Readme.md 2021-11-13 17:13:53 +05:30
Akascape
2c65f8d682 Update Readme.md 2021-11-13 17:13:20 +05:30
Akascape
57946f1909 Update Readme.md 2021-11-13 17:12:45 +05:30
Akascape
87456ecd7f Update Readme.md 2021-11-13 17:12:07 +05:30
Akascape
13d333b412 Update Readme.md 2021-11-13 17:11:27 +05:30
Akascape
4e433eab4e Update Readme.md 2021-11-13 17:10:43 +05:30
Akascape
b561d9354a Update Readme.md 2021-11-13 17:10:06 +05:30
Akascape
f69ad552a7 Update Readme.md 2021-11-13 17:09:45 +05:30
Akascape
c129e8f558 Update Readme.md 2021-11-13 17:08:54 +05:30
Akascape
89904a2578 Update Readme.md 2021-11-13 17:08:40 +05:30
Akascape
0a8814343a Update Readme.md 2021-11-13 17:07:55 +05:30
Akascape
7e6a480e89 Update Readme.md 2021-11-13 17:07:25 +05:30
Akascape
2084d8c349 Update Readme.md 2021-11-13 17:06:29 +05:30
Akascape
670d39e8b2 Update Readme.md 2021-11-13 17:06:11 +05:30
Akascape
953cb59eff Update Readme.md 2021-11-13 17:05:57 +05:30
Akascape
f9aa09153b Update Readme.md 2021-11-13 17:05:39 +05:30
Akascape
dcaae608a5 Update Readme.md 2021-11-13 17:05:23 +05:30
Akascape
f8ec406722 Update Readme.md 2021-11-13 17:05:12 +05:30
Akascape
687fe27530 Update Readme.md 2021-11-13 17:03:42 +05:30
Akascape
7e39a87d23 Update Readme.md 2021-11-13 17:03:29 +05:30
Akascape
08a4ce9f50 Update Readme.md 2021-11-13 17:03:08 +05:30
Akascape
5fb453d295 Update Readme.md 2021-11-13 17:02:14 +05:30
Akascape
0602a2d618 Update Readme.md 2021-11-13 17:01:56 +05:30
Akascape
f2f78dd5a6 Update Readme.md 2021-11-13 17:01:37 +05:30
Akascape
625fc0f4fd Update Readme.md 2021-11-13 17:00:32 +05:30
Akascape
8f35e9af4b Update Readme.md 2021-11-13 17:00:03 +05:30
Akascape
424e857424 Update Readme.md 2021-11-13 16:59:39 +05:30
Akascape
ec7e6843a6 Update Readme.md 2021-11-13 16:57:34 +05:30
Akascape
26f9ec3ace Update Readme.md 2021-11-13 16:56:58 +05:30
Akascape
b67371f580 Update Readme.md 2021-11-13 16:56:15 +05:30
Akascape
4c89bd3264 Update Readme.md 2021-11-13 16:46:47 +05:30
Akascape
334e0afd2e Update Readme.md 2021-11-13 16:45:10 +05:30
Akascape
af3efe0dc9 Update Readme.md 2021-11-13 16:44:13 +05:30
Akascape
983c0fdbc2 Update Readme.md 2021-11-13 16:43:48 +05:30
Akascape
55303c1dcc Update Readme.md 2021-11-13 16:41:55 +05:30
Akascape
e67d281e4b Update Readme.md 2021-11-13 16:41:28 +05:30
Akascape
a9b53b07c0 Update Readme.md 2021-11-13 16:40:13 +05:30
Akascape
7c6482e060 Update Readme.md 2021-11-13 16:39:41 +05:30
Akascape
fc56de9bcc Create __init__.py 2021-11-13 16:16:38 +05:30
Akascape
c8ffd74a45 Create __init__.py 2021-11-13 16:15:45 +05:30
Akascape
afec2dd728 Add files via upload 2021-11-13 16:15:14 +05:30
Akascape
97c2c5c55b Delete 2.txt 2021-11-13 16:14:52 +05:30
Akascape
a9b3d8e444 Add files via upload 2021-11-13 16:14:40 +05:30
Akascape
583d4f2e4d Delete Ok.txt 2021-11-13 16:13:58 +05:30
Akascape
5be68f3a7f Add files via upload 2021-11-13 16:13:47 +05:30
Akascape
5508f57eba Create 2.txt 2021-11-13 16:07:48 +05:30
Akascape
9535b09776 Create Ok.txt 2021-11-13 16:05:59 +05:30
Akascape
efa3ddbde6 Delete Python Version/pymosh/codec directory 2021-11-13 16:03:23 +05:30
Akascape
485b404cc7 Add files via upload 2021-11-13 16:02:57 +05:30
Akascape
c4c4e63185 Update ReadmeforPython.txt 2021-11-13 15:59:49 +05:30
Akascape
8d5ca45528 Delete Datamosher Pro v1.2.py 2021-11-13 15:58:50 +05:30
Akascape
a040b89bb0 Add files via upload 2021-11-13 15:58:29 +05:30
Akascape
544ccc2979 Update Readme.md 2021-11-08 18:19:01 +05:30
Akascape
2714de88f9 Update Readme.md 2021-11-07 20:38:38 +05:30
Akascape
c1fba754a5 Update Readme.md 2021-11-06 18:59:10 +05:30
Akascape
047042cfbb Update Readme.md 2021-11-06 18:52:48 +05:30
Akascape
af6f20df69 Update ReadmeforPython.txt 2021-11-06 18:40:43 +05:30
Akascape
517a402c10 Update Datamosher Pro v1.2.py 2021-11-06 18:39:12 +05:30
Akascape
1f2e620540 Update Datamosher Pro v1.2.py 2021-11-06 18:21:53 +05:30
Akascape
6102604a1e Update Datamosher Pro v1.2.py 2021-11-06 17:52:32 +05:30
Akascape
f66a780dda Update Readme.md 2021-11-06 17:14:09 +05:30
Akascape
fe08676f8c Update Readme.md 2021-11-06 16:50:16 +05:30
Akascape
9cd1a6fba2 Update Readme.md 2021-11-06 16:47:19 +05:30
Akascape
d12acc102f Update ReadmeforPython.txt 2021-11-06 16:43:54 +05:30
Akascape
ecc221c7f1 Update Readme.md 2021-11-06 16:25:38 +05:30
Akascape
6d000ec3ee Update ReadmeforPython.txt 2021-11-06 16:25:11 +05:30
Akascape
e1ac12ab81 Delete Datamosher Pro v1.1.py 2021-11-06 16:21:51 +05:30
Akascape
e2296abafe Add files via upload 2021-11-06 16:21:29 +05:30
9 changed files with 824 additions and 146 deletions

View File

@@ -3,23 +3,52 @@ from tkinter import *
from tkinter import ttk, messagebox, filedialog
import tkinter
import sys
import imageio
import random
import re
import struct
import time
import webbrowser
from itertools import chain, repeat
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 =[('MP4', '*.mp4'),('AVI', '*.avi'),('GIF','*.gif'),('MOV','*.mov')])
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'
@@ -33,8 +62,6 @@ def convertffmpeg(inputpath):
root.update()
fps=30
targetformat='.avi'
#Change the imageio-ffmpeg path if not working (also in the datamoshclassic function)
resource=resource_path0("C:/Users/User/AppData/Local/Programs/Python/Python39/Lib/site-packages/imageio_ffmpeg/binaries/ffmpeg-win64-v4.2.2.exe")
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:
@@ -46,7 +73,10 @@ def convertffmpeg(inputpath):
Wait.place_forget()
os.remove(outputpath)
datamoshbtn['state']=NORMAL
datamoshbtn['cursor']=''
modechoices['state']=NORMAL
exportbox['state']=NORMAL
OpeningFile['state']=NORMAL
root.config(cursor="")
def convert(inputpath,targetformat):
global outputpath
try:
@@ -58,7 +88,7 @@ def convert(inputpath,targetformat):
writer= imageio.get_writer(outputpath, fps=fps)
for frames in reader:
writer.append_data(frames)
#for detailed logs of conversions, remove the comment in the next 2 lines
#to get detailed logs of conversions, remove the comment in the next 2 lines
#print(f'Frame {frames}')
#print("Converted")
writer.close()
@@ -66,21 +96,53 @@ def convert(inputpath,targetformat):
Datamosh(outputpath)
except:
pass
except Exception:
except:
messagebox.showerror("FAILED","The video file or the input data have \n some issues!")
Wait.place_forget()
os.remove(outputpath)
datamoshbtn['state']=NORMAL
datamoshbtn['cursor']=''
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()
extension=os.path.splitext(file)[1]
datamoshbtn['state']=DISABLED
datamoshbtn['cursor']='watch'
choice = modechoices.get()
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)
@@ -88,18 +150,120 @@ def Step1():
targetformat=".mp4"
convert(file,targetformat)
convertffmpeg(file)
else:
if extension==".avi":
Datamosh(file)
else:
targetformat=".avi"
convert(file,targetformat)
elif(choice==modes[8]) or (choice==modes[9]) or (choice==modes[11]):
pymosh_library(file)
else:
targetformat=".avi"
convert(file,targetformat)
else:
messagebox.showerror("OOPS","Please choose the video again!")
messagebox.showerror("","Please choose the video again!")
except:
messagebox.showerror("OOPS","Please choose the video!")
datamoshbtn['state']=NORMAL
datamoshbtn['cursor']=''
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'
@@ -107,16 +271,18 @@ def Datamoshclassic(filename,mainfile):
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=1):
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_datamoshed.mp4"
#Change the imageio-ffmpeg path here also if not working
resource=resource_path0("C:/Users/User/AppData/Local/Programs/Python/Python39/Lib/site-packages/imageio_ffmpeg/binaries/ffmpeg-win64-v4.2.2.exe")
out=outpath+"/"+outx+"-classic.mp4"
subprocess.call(f'"{resource}" -loglevel error -y -i "{outf}" "{out}"', shell=True)
os.remove(filename)
export(out)
os.remove(outf)
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)
@@ -141,12 +307,14 @@ def Datamoshclassic(filename,mainfile):
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=int(firstframes.get())
make=int(Countframe.get())
start=float(firstframes.get())
make=float(Countframe.get())
timer=int(Positframe.get())
main2(filename,[(start,make)],timer)
def Datamosh(Inputfile):
if os.path.splitext(outputpath)[1]==".avi":
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())
@@ -167,28 +335,26 @@ def Datamosh(Inputfile):
mode="reverse"
elif(choice==modes[6]):
mode="random"
elif(choice==modes[10]):
mode="shake"
elif(choice==modes[12]):
mode="void"
else:
messagebox.showerror("OOPS","Please Select the Correct Mode!")
messagebox.showerror("Error!","Please select a valid mode!")
os.remove(outputpath)
os.kill(Datamosh())
Wait.place_forget()
datamoshbtn['state']=NORMAL
datamoshbtn['cursor']=''
if filein is None or os.path.exists(filein) == False:
messagebox.showerror("ERROR","Input File is Missing!")
Wait.place_forget()
os.remove(outputpath)
datamoshbtn['state']=NORMAL
os.kill(Datamosh())
datamoshbtn['cursor']=''
#define temp directory and files
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)
#Define constrain function for jiggle :3
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):
@@ -205,8 +371,8 @@ def Datamosh(Inputfile):
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
marker_pos = re.search(marker, buffer).start()
marker_pos = marker_pos + pos
split = buffer.split(marker, 1)
wr.write(split[0])
return marker_pos
@@ -214,7 +380,6 @@ def Datamosh(Inputfile):
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)
@@ -226,17 +391,14 @@ def Datamosh(Inputfile):
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
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)): # find b frames
for m in (re.finditer(b'\x30\x30\x64\x63', buffer)):
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]
@@ -244,20 +406,18 @@ def Datamosh(Inputfile):
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]])
# 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":
final = clean
if mode == "random":
Wait.config(text="Applying Effect: Random", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
@@ -265,7 +425,7 @@ def Datamosh(Inputfile):
if mode == "reverse":
Wait.config(text="Applying Effect: Reverse", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
final = clean[::-1]
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()
@@ -275,10 +435,8 @@ def Datamosh(Inputfile):
root.update()
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':
Wait.config(text="Applying Effect: Pulse", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
@@ -306,13 +464,44 @@ def Datamosh(Inputfile):
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]
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)
#name new file
cname = '-c' + str(countframes) if int(countframes) > 1 else ''
pname = '-n' + str(positframes) if int(positframes) > 1 else ''
fileout= filein[:-4] + '-' + mode + cname + pname + '.avi'
#delete old file
fileout= filein[:-4] + '-' + mode + '.avi'
if os.path.exists(fileout):
os.remove(fileout)
bstream_until_marker(temp_hdrl, fileout)
@@ -341,40 +530,63 @@ def export(fileout):
def removefileout():
if os.path.exists(fileout):
os.remove(fileout)
messagebox.showinfo("DONE","Datamoshed video is ready!")
Wait.place_forget()
datamoshbtn['state']=NORMAL
datamoshbtn['cursor']=''
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)
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()
datamoshbtn['state']=NORMAL
datamoshbtn['cursor']=''
os.kill(Datamoshclassic())
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
datamoshbtn['cursor']=''
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]):
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
datamoshbtn['cursor']=''
modechoices['state']=NORMAL
exportbox['state']=NORMAL
OpeningFile['state']=NORMAL
else:
targetformat=".mp4"
convert(fileout,targetformat)
@@ -396,21 +608,36 @@ def export(fileout):
convert(fileout,targetformat)
removefileout()
else:
messagebox.showerror("OOPS","Please Select the Correct Format!")
os.remove(outputpath)
os.kill(Datamosh())
messagebox.showerror("Error!","Please select a valid video format!")
os.remove(fileout)
Wait.place_forget()
datamoshbtn['state']=NORMAL
datamoshbtn['cursor']=''
modechoices['state']=NORMAL
exportbox['state']=NORMAL
OpeningFile['state']=NORMAL
root.config(cursor="")
os.kill(Datamosh())
def toggle():
if var.get() == 0:
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]):
var1.set("3")
var2.set(1)
var1.set(100)
countlabel['fg']="green"
positlabel['fg']="green"
firstflabel['fg']="green"
@@ -419,7 +646,13 @@ def Enableadvanced():
Positframe['state']=NORMAL
firstframes['state']=NORMAL
killframe['state']=DISABLED
elif(choice==modes[6]):
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"
@@ -429,6 +662,8 @@ def Enableadvanced():
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"
@@ -437,7 +672,12 @@ def Enableadvanced():
Positframe['state']=DISABLED
firstframes['state']=NORMAL
killframe['state']=DISABLED
elif(choice==modes[1]):
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"
@@ -447,6 +687,8 @@ def Enableadvanced():
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"
@@ -455,8 +697,9 @@ def Enableadvanced():
Positframe['state']=NORMAL
firstframes['state']=NORMAL
killframe['state']=NORMAL
else:
var1.set("1")
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"
@@ -475,16 +718,21 @@ def Disableadvanced():
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 made for those who want to datamosh their video files and achieve that glitch effect."
"\nHow To Use:\n➤First input the video you want to datamosh."
"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 info about the advanced options, go to our Github page)."
"\nThen just click on the datamosh button, then wait for a few seconds."
"\n➤After converting, your video will be moshed and you can find the video in the directory."
"\n➤Note that if you mosh the same files in the same location again, then the new moshed file will replace the old file."
"\n\nDeveloper: Akash Bora (a.k.a. Akascape)\nIf you have any issue then contact me on Github.")
"\n➤Use advance options for different modes (For more details about the advanced options, visit our Github page)."
"\nClick 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()
@@ -501,47 +749,49 @@ headlabel=Label(root,image=LabelIMG,borderwidth=0, highlightthickness=0, padx=0,
headlabel.grid()
LocationError=Label(root,text="Choose Video To Datamosh",fg="red",bg='#FFFFFF')
LocationError.grid()
OpeningFile= Button(root, width=60,bg="#82CC6C",fg="white", text="OPEN",highlightthickness=1,borderwidth=0.2,relief="groove",command=openfile)
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"]
modechoices=ttk.Combobox(root,values=modes, font="Verdana 12", width=7)
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(RAW)","MP4","GIF","MOV","MKV","WMV"]
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=104)
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=IntVar()
var1=DoubleVar()
var1.set(1)
countlabel=Label(root,text="Glitch Freqency",fg="grey",bg='#FFFFFF')
countlabel.place(x=40,y=165)
Countframe=Entry(root,bg="light blue",width=10,borderwidth=3, textvariable=var1,state=DISABLED)
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=IntVar()
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="light blue",width=10,borderwidth=3, textvariable=var2, state=DISABLED)
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="Ignored Frames",fg="grey",bg='#FFFFFF')
firstflabel.place(x=40,y=200)
firstframes=Entry(root,bg="light blue",width=10,borderwidth=3, textvariable=var3, state=DISABLED)
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="light blue",width=10,borderwidth=3, textvariable=var4, state=DISABLED)
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))
@@ -559,4 +809,4 @@ datamoshbtn=Button(root,image=buttonIMG,borderwidth=0, highlightthickness=0, pad
datamoshbtn.place(x=100,y=270)
root.mainloop()
#DEVELOPER: AKASH BORA (a.k.a Akascape)
#Version=1.0
#Version=1.3

View File

@@ -1,6 +1,9 @@
#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.1.py to open the program, then use the software as describes in the Readme.md or click the "i" button inside the software.
Note that you must have the required modules installed. Most of the modules that are used are installed by default, but only one module you need to install separately is Imageio.
To install that module, open CMD or other terminal and type "pip install Imageio" and "pip install Imageio-ffmpeg, then it will be installed and you can open Datamosher Pro v1.1.py. Also change the directory of ffmpeg if needed (see the comments)
Do not delete or move any assets that are linked with the main file or else it will show error.
So, this is all about the python version, you can now Datamosh your videos!
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!

View File

@@ -0,0 +1,27 @@
from .container import avi
__all__ = ['Index']
class Index(object):
"""Index is an index of video frame data."""
def __init__(self):
pass
@staticmethod
def from_file(filename: str):
instance = Index()
instance.filename = filename
instance.index = None
# Assume AVI for now
instance.index = avi.AVIFile.from_file(filename)
return instance
def __getattr__(self, index):
return getattr(self.index, index)
def __iter__(self):
return iter(self.index)

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,6 @@
IFRAME_HEADER = b'\x00\x00\x01\xb0'
def is_iframe(frame):
"""Determine whether frame is an I frame."""
return frame[:4] == IFRAME_HEADER

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,124 @@
import struct
from pymosh.codec.mpeg4 import is_iframe
from . import riff
class AVIFile(object):
"""A wrapper for AVI files."""
def __init__(self):
self.riff = riff.RiffIndex()
self.streams = []
self.frame_order = []
@staticmethod
def from_file(filename: str):
instance = AVIFile()
instance.riff = riff.RiffIndex.from_file(filename=filename)
header = instance.riff.find(b'LIST', b'hdrl')
# Get stream info
stream_lists = header.find_all(b'LIST', b'strl')
for l in stream_lists:
strh = l.find(b'strh')
data = strh.data
fccType, = struct.unpack(b'4s', data[:4])
stream = Stream(len(instance.streams), fccType)
instance.streams.append(stream)
instance.split_streams()
return instance
def __iter__(self):
return iter(self.streams)
def add_frame(self, chunk):
stream_num = int(chunk.header[:2])
if stream_num < len(self.streams):
self.frame_order.append(
(stream_num, len(self.streams[stream_num])))
self.streams[stream_num].add_frame(chunk)
def split_streams(self):
movi = self.riff.find(b'LIST', b'movi')
for chunk in movi:
self.add_frame(chunk)
def combine_streams(self):
chunks = []
for frame_record in self.frame_order:
stream_num, frame_num = frame_record
stream = self.streams[stream_num]
frame = stream[frame_num]
chunks.append(frame)
return chunks
def _video(self):
return filter(lambda stream: stream.type == b'vids', self.streams)
video = property(_video)
def _audio(self):
return filter(lambda stream: stream.type == b'auds', self.streams)
audio = property(_audio)
def rebuild(self):
"""Rebuild RIFF tree and index from streams."""
movi = self.riff.find(b'LIST', b'movi')
movi.chunks = self.combine_streams()
self.rebuild_index()
def rebuild_index(self):
old_index = self.riff.find(b'idx1')
movi = self.riff.find(b'LIST', b'movi')
data = b''
offset = 0
flags = {
'base': 0x00000000,
'keyframe': 0x00000010,
}
for chunk in movi:
length = len(chunk)
frame_flags = flags['base']
# If it's a video keyframe or audio frame, use keyframe flag
if (chunk.header[2] == b'd' and is_iframe(chunk)) or (chunk.header[2] == b'w'):
frame_flags |= flags['keyframe']
data += struct.pack(b'<4sIII', chunk.header, frame_flags, offset,
length+8)
offset += length + 8 + (length % 2)
new_index = riff.RiffDataChunk(b'idx1', data)
self.riff.find(b'RIFF').replace(old_index, new_index)
def write(self, fh):
self.riff.write(fh)
class Stream(object):
def __init__(self, num, stream_type):
self.num = int(num)
self.type = stream_type
self.chunks = []
def add_frame(self, chunk):
self.chunks.append(chunk)
def __getitem__(self, index):
return self.chunks.__getitem__(index)
def __iter__(self):
return self.chunks.__iter__()
def __len__(self):
return len(self.chunks)
def append(self, *args):
return self.chunks.append(*args)
def extend(self, *args):
return self.chunks.extend(*args)
def replace(self, chunks):
self.chunks = chunks

View File

@@ -0,0 +1,263 @@
import os
import struct
from io import IOBase
list_headers = (b'RIFF', b'LIST')
class UnexpectedEOF(Exception):
pass
class RiffIndexChunk(object):
def __init__(self, fh, header, length, position):
self.file = fh
self.header = header
self.length = int(length)
self.position = position
def __str__(self):
return str(self.bytes())
def bytes(self) -> bytes:
return self.header + struct.pack('<I', self.length) + self.data
def __len__(self):
return self.length
def __getslice__(self, start, end):
if start is None:
start = 0
if end is None:
end = self.length
current = self.file.tell()
self.file.seek(self.position+start)
if start < end and start <= self.length:
if end > self.length:
end = self.length
data = self.file.read(end-start)
self.file.seek(current)
return data
else:
return ''
def __getitem__(self, index):
if isinstance(index, slice):
return self.__getslice__(index.start, index.stop)
return self[index:index+1]
def _data(self):
"""Read data from the file."""
current_position = self.file.tell()
self.file.seek(self.position)
data = self.file.read(self.length)
self.file.seek(current_position)
if self.length % 2:
data += b'\x00' # Padding byte
return data
data = property(_data)
def as_data(self):
"""Return a RiffDataChunk read from the file."""
raise NotImplementedError()
class RiffIndexList(RiffIndexChunk):
def __init__(self, header, list_type, *args, **kwargs):
self.header = header
self.type = list_type
self.file = kwargs.get('file', None)
self.position = kwargs.get('position', 0)
self.chunks = kwargs.get('chunks', [])
def __getitem__(self, index):
return self.chunks[index]
def __setitem__(self, index, value):
return self.chunks.__setitem__(index, value)
def __delitem__(self, index):
return self.chunks.__delitem__(index)
def __iter__(self):
return iter(self.chunks)
def __len__(self):
"""Return total data length of the list and its headers."""
return self.chunk_length() + len(self.type) + len(self.header) + 4
def chunk_length(self):
length = 0
for chunk in self.chunks:
chunk_len = len(chunk)
length += chunk_len + 8 # Header and length bytes
length += chunk_len % 2 # Pad byte
return length
def __str__(self):
return str(self.bytes())
def bytes(self) -> bytes:
"""Returns a byte representation of the chunk."""
length_bytes = struct.pack('<I', self.chunk_length() + len(self.type))
return self.header + length_bytes + self.type
class NotFound(Exception):
"""Indicates a chunk or list was not found by the find method."""
pass
def find(self, header, list_type=None):
"""Find the first chunk with specified header and optional list type."""
for chunk in self:
if chunk.header == header and (list_type is None or (header in
list_headers and chunk.type == list_type)):
return chunk
elif chunk.header in list_headers:
try:
result = chunk.find(header, list_type)
return result
except chunk.NotFound:
pass
if list_type is None:
raise self.NotFound('Chunk \'{0}\' not found.'.format(header))
else:
raise self.NotFound('List \'{0} {1}\' not found.'.format(header,
list_type))
def find_all(self, header, list_type=None):
"""Find all direct children with header and optional list type."""
found = []
for chunk in self:
if chunk.header == header and (not list_type or (header in
list_headers and chunk.type == list_type)):
found.append(chunk)
return found
def replace(self, child, replacement):
"""Replace a child chunk with something else."""
for i in range(len(self.chunks)):
if self.chunks[i] == child:
self.chunks[i] = replacement
def remove(self, child):
"""Remove a child element."""
for i in range(len(self)):
if self[i] == child:
del self[i]
class RiffDataChunk(object):
"""A RIFF chunk with data in memory instead of a file."""
def __init__(self, header, data):
self.header = header
self.length = len(data)
self.data = data
@staticmethod
def from_data(data):
"""Create a chunk from data including header and length bytes."""
header, _ = struct.unpack('4s<I', data[:8])
data = data[8:]
return RiffDataChunk(header, data)
def bytes(self) -> bytes:
"""Returns a byte array representation of the chunk."""
return self.header + struct.pack('<I', self.length) + self.data
def __str__(self):
return str(self.bytes())
def __len__(self):
return self.length
def __getslice__(self, start, end):
return self.data[start:end]
def __getitem__(self, index):
return self.data[index]
class RiffIndex(RiffIndexList):
def __init__(self):
self.file = None
self.chunks = []
@staticmethod
def from_file(filename: str):
instance = RiffIndex()
instance.file = open(filename, 'rb')
instance.size = instance.get_size()
instance.scan_file()
return instance
def write(self, fh: IOBase) -> None:
def print_chunks(chunks):
for chunk in chunks:
fh.write(chunk.bytes())
if chunk.header in (b'RIFF', b'LIST'):
print_chunks(chunk.chunks)
print_chunks(self.chunks)
def get_size(self):
current = self.file.tell()
self.file.seek(0, 2)
size = self.file.tell()
self.file.seek(current)
return size
def readlen(self, length):
buf = self.file.read(length)
if len(buf) == length:
return buf
else:
raise UnexpectedEOF(
'End of file reached after {0} bytes.'.format(len(buf)))
def scan_file(self):
header = self.readlen(4)
if header == b'RIFF':
length, list_type = struct.unpack('<I4s', self.readlen(8))
chunks = self.scan_chunks(length-4)
self.chunks.append(RiffIndexList(header, list_type, file=self.file,
position=0, chunks=chunks))
else:
raise Exception('Not a RIFF file!')
def scan_chunks(self, data_length):
chunks = []
total_length = 0
while total_length < data_length:
header = self.readlen(4)
total_length += 4
length, = struct.unpack('<I', self.file.read(4))
total_length += length + 4 # add 4 for itself
position = self.file.tell()
if header in list_headers:
list_type = self.readlen(4)
data = self.scan_chunks(length-4)
if length % 2:
# Padding byte
self.file.seek(1, os.SEEK_CUR)
total_length += 1
chunks.append(RiffIndexList(header, list_type, file=self.file,
position=position, chunks=data))
else:
self.file.seek(length, os.SEEK_CUR)
if length % 2:
# Padding byte
self.file.seek(1, os.SEEK_CUR)
total_length += 1
chunks.append(RiffIndexChunk(
self.file, header, length, position))
return chunks
def close(self):
self.file.close()

View File

@@ -1,47 +1,50 @@
# Datamosher Pro
<br>Datamoshing is an effect that really looks cool and if you also want to make this glitch effect with your videos, you are in the right place!
![icon](https://user-images.githubusercontent.com/89206401/138873267-16f152e7-b61a-4fc2-a215-1cb66a004f13.png)
<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 good datamoshing softwares, you can either have to use those old softwares like Avidemux or have to look for some paid plugins, but I created my own GUI based application that is Datamosher Pro which is a free project. It contains 7 different effects and more will be added in future, you can also help to make new effects. With Datamosher Pro, you can quickly and easily datamosh your videos(supports mp4, gif, avi, mov etc).
<br>
<br>➤How to Install?
<br>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 executable version of Datamosher Pro from the release page: (https://github.com/Akascape/Datamosher-Pro/releases/tag/Datamosher_Prov1.1.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 with the python file, Imageio and Imageio-ffmpeg module installed in your system.
<br>
<br>➤How to Use?
<br>•Input the video file first (supported formats- mp4, gif, avi + more will be added if you demand")
<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).
# 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.
# 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>•Then just click on the datamosh button, then wait for a few seconds"
<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 that if you mosh the same files in the same location again, then the new moshed file will replace the old file.
<br>
<br>➤Effects Info:
<br>(c is Glitch Frequency and n is Frame Frequency)
<br>Classic - uses classic ffmpeg way to corrupt videos and remove pixels (NEW)
<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 (also known as waterbloom)
<br>Pulse - duplicates groups of c p-frames every n frames (My fav)
<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>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>
<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 Frequency - tells how often to glitch (for modes that support it)
<br>Frame Frequency - tells how many frames in the glitch (for modes that support it)
<br>Ignored First Frame - tells whether to keep first video frames
<br>Kill frames - tells max framesize to kill while cleaning
<br>You can try around changing the values from 50-100 and see the results, you can visit https://github.com/itsKaspar/tomato.git to view more examples about the advanced tab.
<br>
<br>➤User Interface:
<br>![Screenshot 2021-10-26 220159](https://user-images.githubusercontent.com/89206401/138922164-4c78f673-050e-4513-a3d2-6208e836cabc.png)
<br>
<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 which can only handle .avi file structure, 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 without losing any 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 by other softwares without any error. A raw form option is also available if needed. You will not find this type of GUI program anywhere, I hope there is no error in the software but if you saw any bug then raise an issue. All the logo and designs are created by me. <br>Thanks! Made by Akash Bora (a.k.a Akascape).
<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).
<br>
<br>DATAMOSH MADE EASY!
<br>Current Version=1.1
<br>Current Version=1.3