Files
Datamosher-Pro/Python Version/Datamosher Pro.py
2022-04-26 11:32:38 +05:30

1240 lines
50 KiB
Python

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
import json
import shutil
#Note that this program is optimised for only windows, for other systems you may have to adjust some parameters
required = {'imageio', 'imageio-ffmpeg', 'numpy'}
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":
try:
for x in range(len(missingset)):
y=missingset[x]
subprocess.Popen('python -m pip install '+y)
messagebox.showinfo("Modules Installed","Please restart the program!")
sys.exit()
except:
messagebox.showerror("Error downloading modules","Please download the neccessary modules separately!\n Required: Imageio, Imageio-ffmpeg, Numpy")
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
import imageio_ffmpeg
import numpy as np
if os.path.isdir("pymosh") and os.path.isdir("ffglitch") and os.path.isdir("Assets"):
from pymosh import Index
from pymosh.codec.mpeg4 import is_iframe
else:
messagebox.showerror("Missing Folder!","Some folder(s) are 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)
global resource, ffgac, ffedit
ffdir=os.path.dirname(imageio_ffmpeg.__file__).replace(os.sep, '/')+"/binaries/"
fileff=os.listdir(ffdir)[0]
resource=resource_path0(ffdir+fileff)
if os.path.exists("ffglitch/ffedit.exe") or os.path.exists("ffglitch/ffedit"):
pass
else:
ffres1=messagebox.askquestion("Setup","Are you on windows right now?")
if ffres1=="yes":
shutil.copy("ffglitch/windows/ffedit.exe","ffglitch/ffedit.exe")
shutil.copy("ffglitch/windows/ffgac.exe","ffglitch/ffgac.exe")
else:
ffres2=messagebox.askquestion("Setup","So you are using Mac?")
if ffres2=="yes":
shutil.copy("ffglitch/mac/ffedit","ffglitch/ffedit")
shutil.copy("ffglitch/mac/ffgac","ffglitch/ffgac")
else:
ffres3=messagebox.askquestion("Setup","Ok you are on linux, yes?")
if ffres3=="yes":
shutil.copy("ffglitch/linux/ffedit","ffglitch/ffedit")
shutil.copy("ffglitch/linux/ffgac","ffglitch/ffgac")
else:
messagebox.showerror("OOPS!","Sorry to say but other distributions are not available!")
sys.exit()
messagebox.showinfo("Setup Complete","Setup completed successfully! \nNow you can enter the program")
ffgac=resource_path0("ffglitch/ffgac")
ffedit=resource_path0("ffglitch/ffedit")
def openfile():
global file
file=tkinter.filedialog.askopenfilename(filetypes =[('Video', ['*.mp4','*.avi','*.mov','*.mkv','*wmv','*gif']),('All Files', '*.*')])
if(len(file)>1):
LocationError.config(text=file, fg="green")
if (len(file)>80):
LocationError.config(text=file[:77]+"...", 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 datafile():
global vecfile
vecfile=tkinter.filedialog.askopenfilename(filetypes =[('Video', ['*.mp4','*.avi','*.mov','*.mkv','*wmv','*gif']),('All Files', '*.*')])
if(len(vecfile)>1):
Opening_vector['text']='Open Again'
Opening_vector['bg']='#D0CECE'
else:
Opening_vector['text']="OPEN"
Opening_vector['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
if var5.get()==1:
subprocess.call(f'"{resource}" -loglevel error -y -i "{inputpath}" -crf 0 -bf 0 -b 10000k -r {fps} "{outputpath}"', shell=True)
else:
subprocess.call(f'"{resource}" -loglevel error -y -i "{inputpath}" -crf 0 -bf 0 -r {fps} "{outputpath}"', shell=True)
try:
choice=modechoices.get()
if (choice==modes[16]):
Wait.config(text="Applying Effect: Repeat", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
repeat(outputpath,inputpath)
else:
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!")
os.remove(outputpath)
end()
def convert(inputpath,targetformat):
global outputpath, highest
try:
Wait.config(text="Converting the Video...", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
outputpath=os.path.splitext(inputpath)[0]+'_datamoshed'+targetformat
x=os.path.splitext(file)[1]
choice = modechoices.get()
if ((x==".gif") or (choice==modes[17]) or (choice==modes[18])or (choice==modes[19])
or (choice==modes[20]) or (choice==modes[21]) or (choice==modes[22]) or (choice==modes[23])
or (choice==modes[24]) or (choice==modes[25]) or (choice==modes[26]) or (choice==modes[27])
or (choice==modes[28]) or (choice==modes[29])):
highest="no"
else:
pass
if highest=="yes":
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)
writer.close()
if var5.get()==1:
highest="yes"
else:
highest="no"
elif highest=="no":
if ((choice==modes[17]) or (choice==modes[18]) or (choice==modes[19]) or
(choice==modes[20]) or (choice==modes[21]) or (choice==modes[22]) or
(choice==modes[23]) or (choice==modes[24]) or (choice==modes[25]) or
(choice==modes[26]) or (choice==modes[27]) or (choice==modes[28]) or
(choice==modes[29])):
if targetformat==".gif":
subprocess.call(f'"{resource}" -i "{inputpath}" "{outputpath}"')
else:
subprocess.call(f'"{resource}" -hwaccel auto -i "{inputpath}" -c:v libx264 -preset medium -b:v 2M -minrate 2M -maxrate 2M -bufsize 2M -y "{outputpath}"', shell=True)
else:
subprocess.call(f'"{resource}" -loglevel error -y -i "{inputpath}" "{outputpath}"', shell=True)
try:
Datamosh(outputpath)
except:
pass
except:
choice = modechoices.get()
if (choice==modes[30]):
messagebox.showerror("FAILED","The kill value is invalid for this video so it failed to convert!")
else:
messagebox.showerror("FAILED","The video file or the input data have \n some issues!")
os.remove(outputpath)
end()
def validate():
try:
choice = modechoices.get()
float(Countframe.get())
float(Positframe.get())
float(firstframes.get())
float(killframe.get())
x=float(killframe.get())
if ((choice==modes[30]) or (choice==modes[31])):
pass
elif x>1:
var4.set(1)
except ValueError:
messagebox.showerror("Invalid Input","Please enter some valid values")
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 end():
datamoshbtn['state']=NORMAL
modechoices['state']="readonly"
exportbox['state']="readonly"
OpeningFile['state']=NORMAL
Highbox['state']=NORMAL
advancedbox['state']=NORMAL
Opening_vector['state']=NORMAL
root.config(cursor="")
Wait.config(text=" ", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
def Step1():
try:
if (OpeningFile['text']=='Open Again'):
Wait.place(relx=0.5,rely=0.85,anchor='center')
root.update()
datamoshbtn['state']=DISABLED
modechoices['state']=DISABLED
exportbox['state']=DISABLED
OpeningFile['state']=DISABLED
Highbox['state']=DISABLED
advancedbox['state']=DISABLED
Opening_vector['state']=DISABLED
extension=os.path.splitext(file)[1]
validate()
checkexist(file)
root.config(cursor="")
choice = modechoices.get()
if(choice==modes[7]) or (choice==modes[16]):
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)
elif((choice==modes[13]) or (choice==modes[14]) or (choice==modes[15]) or (choice==modes[17])
or (choice==modes[18]) or (choice==modes[19]) or (choice==modes[20]) or (choice==modes[21])
or (choice==modes[22]) or (choice==modes[23]) or (choice==modes[24]) or (choice==modes[25])
or (choice==modes[26]) or (choice==modes[27]) or (choice==modes[28]) or (choice==modes[29])
or (choice==modes[30]) or (choice==modes[31])) :
if (choice==modes[15]):
if (Opening_vector['text']=='Open Again'):
wrong.place_forget()
pass
elif (Opening_vector['text']=="OPEN"):
wrong.place(x=250,y=235)
os.kill(Step1)
ffglitch_library(file)
else:
targetformat=".avi"
convert(file,targetformat)
else:
os.kill(Step1)
except:
messagebox.showerror("","Please choose the video file again!")
end()
def get_vectors(input_video):
subprocess.call(f'"{ffgac}" -i "{input_video}" -an -mpv_flags +nopimb+forcemv -qscale:v 0 -g 1000' +
' -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 1000' +
' -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_video):
siz=int(Countframe.get())
kil=float(killframe.get())
if os.path.isdir("cache"):
shutil.rmtree("cache")
os.mkdir("cache")
base=os.path.basename(file)
fin="cache/"+base[:-4]+".mpg"
subprocess.call(f'"{ffgac}" -i "{file}" -an -vcodec mpeg2video -f rawvideo -mpv_flags +nopimb -qscale:v 6 -r 30 -g 90 -s 1280x720 -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")
if kil<=1:
kil=1
else:
if kil>30:
var4.set(30)
kil=30.0
kil=int(kil)
x=random.sample(frames,kil)
for i in x:
os.remove("cache/raws/"+i)
frames.clear()
frames=os.listdir("cache/raws")
if siz>=(len(frames)):
siz=(len(frames))
framelist.extend(frames)
if siz>=1:
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 i in chunked_list:
for j in i:
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_video, '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(file)
fin="cache/"+base[:-4]+".mpg"
if var5.get()==1:
qua='1920x1080'
else:
qua="1280x720"
subprocess.call(f'"{ffgac}" -i "{file}" -an -vcodec mpeg2video -f rawvideo -mpv_flags +nopimb -qscale:v 6 -r 30 -g 90 -s "{qua}" -y "{fin}"')
os.mkdir("cache/raws")
framelist=[]
subprocess.call(f'"{ffgac}" -i "{fin}" -vcodec copy cache/raws/frames_%04d.raw')
kil=float(killframe.get())
frames=os.listdir("cache/raws")
if kil<=1:
kil=10
else:
if kil>=(len(frames)):
kil=len(frames)/2
kil=int(kil)
po=int(firstframes.get())
if po>=(len(frames)):
po=len(frames)-3
frames.clear()
frames=os.listdir("cache/raws")
for i in frames[po:(po+kil)]:
os.remove("cache/raws/"+i)
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 = int(Positframe.get())
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[0] = 0
return frames
def external_scripts(output_video):
choice = modechoices.get()
gop_period = int(Countframe.get())
if (gop_period==1):
gop_period=1000
script_path =resource_path0( "ffglitch/jscripts/"+modechoices.get()+".js")
input_video = file
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_period}"' +
' -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')
def ffglitch_library(file):
choice = modechoices.get()
outpath=os.path.dirname(file)
outx=os.path.basename(file).split('.')[0]
if(choice==modes[15]):
Wait.config(text="Applying Effect: Motion Transfer", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
output=outpath+"/"+outx+"_datamoshed-motion transfer.mp4"
extract_from=vecfile
transfer_to=file
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(choice==modes[14]):
Wait.config(text="Applying Effect: Stretch", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
input_video = file
output= outpath+"/"+outx+"_datamoshed-stretch.mp4"
apply_vectors(movement(get_vectors(input_video)), input_video, output, method='')
elif(choice==modes[13]):
Wait.config(text="Applying Effect: Fluid", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
input_video = file
output= outpath+"/"+outx+"_datamoshed-fluid.mp4"
apply_vectors(fluid(get_vectors(input_video)), input_video, output, method='')
elif((choice==modes[13]) or (choice==modes[14]) or (choice==modes[15]) or (choice==modes[17])
or (choice==modes[18]) or (choice==modes[19]) or (choice==modes[20]) or (choice==modes[21])
or (choice==modes[22]) or (choice==modes[23]) or (choice==modes[24]) or (choice==modes[25])
or (choice==modes[26]) or (choice==modes[27]) or (choice==modes[28]) or (choice==modes[29])):
Wait.config(text="Applying Effect: "+modechoices.get(), fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
output= outpath+"/"+outx+"_datamoshed-"+(modechoices.get()).lower()+".mpg"
external_scripts(output)
elif(choice==modes[30]):
Wait.config(text="Applying Effect: Shuffle", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
output= outpath+"/"+outx+"_datamoshed-"+(modechoices.get()).lower()+".mpg"
shuffle(output)
elif(choice==modes[31]):
Wait.config(text="Applying Effect: Rise", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
output= outpath+"/"+outx+"_datamoshed-"+(modechoices.get()).lower()+".mpg"
rise(output)
export(output)
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
Wait.config(text="Converting the Video...", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
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 repeat(filename, mainfile):
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)
fps=30
start_frame = int(firstframes.get())
end_frame = int(Countframe.get())
if end_frame==1:
end_frame=1000
input_avi = filename
delta = int(Positframe.get())
in_file = open(input_avi, 'rb')
outx=os.path.basename(filename).split('.')[0]
outpath=os.path.dirname(mainfile)
output_avi=outpath+"/"+outx+"-repeat.avi"
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)
out=outpath+"/"+outx+"-repeat.mp4"
subprocess.call(f'"{resource}" -loglevel error -y -i "{output_avi}" "{out}"', shell=True)
export2=exportbox.get()
in_file.close()
out_file.close()
if(export2==exportchoices[0]):
pass
else:
os.remove(output_avi)
os.remove(filename)
export(out)
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())
audio=0
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)
end()
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":
Wait.config(text="Applying Effect: Void", fg="#6D76CD",bg='#FFFFFF', font=("Aharoni",15))
root.update()
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)
messagebox.showinfo("DONE","Datamoshed video is ready!")
end()
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]) or (choice==modes[16]):
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!")
end()
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!")
end()
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]) or (choice==modes[16]):
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!")
end()
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)
end()
os.kill(Datamosh())
def toggle():
if var.get()==0:
Disableadvanced()
dynamiclable()
else:
Enableadvanced()
dynamiclable()
def Enableadvanced():
choice = modechoices.get()
if(choice==modes[8]) or (choice==modes[13]):
var2.set(6)
var4.set(0.7)
var1.set(1)
if (choice==modes[13]):
var2.set(10)
countlabel['fg']="grey"
positlabel['fg']="green"
firstflabel['fg']="grey"
killlabel['fg']="grey"
Countframe['state']=DISABLED
Positframe['state']=NORMAL
firstframes['state']=DISABLED
killframe['state']=DISABLED
elif(choice==modes[7]) or (choice==modes[16]):
var2.set(1)
var1.set(1000)
if (choice==modes[16]):
var2.set(5)
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)
var1.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]) or (choice==modes[1]) or (choice==modes[31]):
var2.set(1)
var3.set(1)
var1.set(1)
var4.set(0.7)
if (choice==modes[31]):
var4.set(50)
var3.set(10)
else:
var4.set(0.7)
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[11]):
var2.set(1)
var1.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)
var1.set(1)
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)
var1.set(1)
countlabel['fg']="green"
positlabel['fg']="green"
firstflabel['fg']="green"
killlabel['fg']="green"
Countframe['state']=NORMAL
Positframe['state']=NORMAL
firstframes['state']=NORMAL
killframe['state']=NORMAL
elif((choice==modes[17]) or (choice==modes[18])
or (choice==modes[19]) or (choice==modes[20])
or (choice==modes[21]) or (choice==modes[22])
or (choice==modes[23]) or (choice==modes[24])
or (choice==modes[25]) or (choice==modes[26])
or (choice==modes[27]) or (choice==modes[28]) or (choice==modes[29])):
var1.set(1000)
countlabel['fg']="green"
positlabel['fg']="grey"
firstflabel['fg']="grey"
killlabel['fg']="grey"
Countframe['state']=NORMAL
Positframe['state']=DISABLED
firstframes['state']=DISABLED
killframe['state']=DISABLED
elif(choice==modes[30]):
var4.set(1)
var1.set(10)
countlabel['fg']="green"
positlabel['fg']="grey"
firstflabel['fg']="grey"
killlabel['fg']="green"
Countframe['state']=NORMAL
Positframe['state']=DISABLED
firstframes['state']=DISABLED
killframe['state']=NORMAL
else:
Disableadvanced()
def dynamiclable():
choice = modechoices.get()
if(choice==modes[7]):
firstflabel['text']= "Start(sec)"
countlabel['text']="End(sec)"
elif(choice==modes[16]):
countlabel['text']="Last Frame"
firstflabel['text']= "First Frame"
elif(choice==modes[11]):
countlabel['text']="Glitch Size"
firstflabel['text']= "Mid Point"
elif((choice==modes[0]) or (choice==modes[1]) or (choice==modes[2])
or (choice==modes[3]) or (choice==modes[4]) or (choice==modes[5])
or (choice==modes[6]) or (choice==modes[12]) or (choice==modes[10])):
countlabel['text']="Glitch Size"
firstflabel['text']= "Ignore Frame"
else:
firstflabel['text']="First Frame"
countlabel['text']="Glitch Size"
positlabel['text']="Frames Frequency"
killlabel['text']="Kill Frames"
def Disableadvanced():
var1.set("1")
var2.set(1)
var3.set(1)
var4.set(0.7)
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()
choice = modechoices.get()
if (choice==modes[15]):
vector_label.place(x=270,y=233)
Opening_vector.place(x=350,y=233)
else:
vector_label.place_forget()
Opening_vector.place_forget()
def toggle2():
global highest
if var5.get()==1:
highest="yes"
else:
highest="yes"
def info():
messagebox.showinfo("Help",
"Datamosher Pro is an automatic glitching tool that can mosh/corrupt video files and gives awesome glitchy results."
"\nHow To Use:\n➤First open the video you want to datamosh"
"\n➤Choose the desired datamosh mode, export format and quality adjustments"
"\n➤Use advanced options for different modes"
"\n➤Then click on the datamosh button and wait for a few seconds"
"\n➤After conversions, your video will be moshed and saved in the same video directory."
"\n\nDeveloper: Akash Bora (a.k.a. Akascape)\nIf you are facing any issue then contact me on reddit."
"\nVersion-1.7")
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)
try:
icopath=resource_path0("Assets/icon.ico")
root.wm_iconbitmap(icopath)
except:
pass
path=resource_path0("Assets/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",
"Fluid", "Stretch", "Motion Transfer", "Repeat", "Shear", "Delay", "Sink",
"Mirror", "Vibrate", "Slam Zoom", "Zoom","Invert-Reverse", "Shift",
"Noise", "Stop", "Buffer", "Slice", "Shuffle", "Rise"]
modechoices=ttk.Combobox(root,values=sorted(modes), font="Verdana 12", width=10, height=10,state="readonly")
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, state="readonly")
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="Ignore 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 | ',bg='#FFFFFF',fg="#6D76CD", font=("Halvetica",10))
dev.place(x=5,y=430)
link=Label(root, text="Datamosher Pro Help",font=('Halvetica',10),bg='#FFFFFF',fg="#6D76CD", cursor="hand2")
link.place(x=155,y=430)
link.bind("<Button-1>", lambda e:
callback("https://github.com/Akascape/Datamosher-Pro-GUI-.git"))
path0=resource_path0("Assets/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)
vector_label=Label(root,text="Vector Video:",fg="green",bg='#FFFFFF')
Opening_vector= Button(root, width=15,bg="#82CC6C",fg="white", text="OPEN",highlightthickness=1,borderwidth=0.2,relief="groove",command=datafile)
global var5
var5 = IntVar()
var5.set(1)
highest="yes"
Highbox=Checkbutton(root, text="Highest Quality",bg="#FFFFFF", command=toggle2,variable=var5,onvalue=1, offvalue=0)
Highbox.place(x=85,y=240, anchor='center')
wrong=Label(root, width=2,bg="#FFFFFF",fg="red", text="",font=(10),relief="sunken", highlightthickness=0,borderwidth=0,padx=0,pady=0)
root.mainloop()
#DEVELOPER: AKASH BORA (a.k.a Akascape)
#Version=1.7