diff --git a/Python Version/Assets/button.png b/Python Version/Assets/button.png deleted file mode 100644 index 7ddf4de..0000000 Binary files a/Python Version/Assets/button.png and /dev/null differ diff --git a/Python Version/Assets/icon.ico b/Python Version/Assets/icon.ico deleted file mode 100644 index 6a12d2f..0000000 Binary files a/Python Version/Assets/icon.ico and /dev/null differ diff --git a/Python Version/Assets/label.png b/Python Version/Assets/label.png deleted file mode 100644 index 681bcdd..0000000 Binary files a/Python Version/Assets/label.png and /dev/null differ diff --git a/Python Version/Datamosher-Pro.py b/Python Version/Datamosher-Pro.py deleted file mode 100644 index 304fcf9..0000000 --- a/Python Version/Datamosher-Pro.py +++ /dev/null @@ -1,1218 +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 -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 \nDo 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, shell=True) - messagebox.showinfo("Installing modules...","Modules are being installed...\nPlease restart the program once its done! \n(Make sure you are connected to internet)") - except: - messagebox.showerror("Error downloading modules","Please download the neccessary modules separately! \nRequired: 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! \nRequired: Imageio, Imageio-ffmpeg, Numpy") - sys.exit() - 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=''.join([idx for idx in os.listdir(ffdir) if idx[0].lower()=='f'.lower()]) -resource=resource_path0(ffdir+fileff) -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}"', shell=True) - 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}"', shell=True) - os.mkdir("cache/raws") - framelist=[] - subprocess.call(f'"{ffgac}" -i "{fin}" -vcodec copy cache/raws/frames_%04d.raw', shell=True) - 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}"', shell=True) - os.mkdir("cache/raws") - framelist=[] - subprocess.call(f'"{ffgac}" -i "{fin}" -vcodec copy cache/raws/frames_%04d.raw', shell=True) - 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('', 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("", 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 diff --git a/Python Version/ReadmeforPython.txt b/Python Version/ReadmeforPython.txt deleted file mode 100644 index d9d9533..0000000 --- a/Python Version/ReadmeforPython.txt +++ /dev/null @@ -1,24 +0,0 @@ -#Read this to use the python version. -This version is comparitively lower in size and works the same inside python environment. -Things to setup before running the python file: -The GUI of Datamosher-Pro.py given in this source code version is optimised for Windows; for other OS, download the python version from release page. -1) First setup ffglitch if you are using this repo only. (See readme.txt inside ffglitch folder to download ffglitch) -(Make sure you make it Unix executable if you are on Mac and also give permission) -Note: No need to setup the ffglitch if you downloaded the python version from release page as all the versions are pre-provided there -2) After doing that, run the datamosher-pro.py file and click yes if module error pops up and let the modules get downloaded. -If it doesn't work then install the modules manually- -# Modules you need to install: --- tkinter -If not installed then use- -(pip install tk) or (sudo apt-get install python3-tk) --- numpy -(pip install numpy) --- imageio -(pip install imageio) --- imageio-ffmpeg -(pip install imageio-ffmpeg) -# For Mac, you need to install one more module: --- tkmacosx -(pip install tkmacosx) -3) Do not delete or move any assets or folder that are linked with the main file or else it will show error. -After the setup the application will open and you can try datamoshing. diff --git a/Python Version/ffglitch/Readme.txt b/Python Version/ffglitch/Readme.txt deleted file mode 100644 index 2303c46..0000000 --- a/Python Version/ffglitch/Readme.txt +++ /dev/null @@ -1,11 +0,0 @@ -All ffglitch builds are given in the release python version, so download that directly -For people downloading this repo, -Download ffglitch from ffglitch.org or the direct links are given below: -For windows: -https://ffglitch.org/pub/bin/win64/ffglitch-0.9.3-win64.7z -For linux: -https://ffglitch.org/pub/bin/linux64/ffglitch-0.9.3-linux64.7z -For mac: -https://ffglitch.org/pub/bin/mac64/ffglitch-0.9.3-mac64.7z - -After downloading, extract the files and move the ffedit and ffgac file in this ffglitch folder of datamosher pro. diff --git a/Python Version/ffglitch/jscripts/Buffer.js b/Python Version/ffglitch/jscripts/Buffer.js deleted file mode 100644 index 6146ee8..0000000 --- a/Python Version/ffglitch/jscripts/Buffer.js +++ /dev/null @@ -1,75 +0,0 @@ -// 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 - - } - } -} diff --git a/Python Version/ffglitch/jscripts/Delay.js b/Python Version/ffglitch/jscripts/Delay.js deleted file mode 100644 index 56aad92..0000000 --- a/Python Version/ffglitch/jscripts/Delay.js +++ /dev/null @@ -1,71 +0,0 @@ -// 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 - - } - } -} diff --git a/Python Version/ffglitch/jscripts/Invert-Reverse.js b/Python Version/ffglitch/jscripts/Invert-Reverse.js deleted file mode 100644 index 8df79fe..0000000 --- a/Python Version/ffglitch/jscripts/Invert-Reverse.js +++ /dev/null @@ -1,58 +0,0 @@ -// 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; - } -} diff --git a/Python Version/ffglitch/jscripts/Mirror.js b/Python Version/ffglitch/jscripts/Mirror.js deleted file mode 100644 index 16d50a7..0000000 --- a/Python Version/ffglitch/jscripts/Mirror.js +++ /dev/null @@ -1,52 +0,0 @@ -// 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]; - //} - } - } -} diff --git a/Python Version/ffglitch/jscripts/Noise.js b/Python Version/ffglitch/jscripts/Noise.js deleted file mode 100644 index cb7d6ac..0000000 --- a/Python Version/ffglitch/jscripts/Noise.js +++ /dev/null @@ -1,67 +0,0 @@ -// 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; - } - } - } -} diff --git a/Python Version/ffglitch/jscripts/Shear.js b/Python Version/ffglitch/jscripts/Shear.js deleted file mode 100644 index d076fb6..0000000 --- a/Python Version/ffglitch/jscripts/Shear.js +++ /dev/null @@ -1,37 +0,0 @@ -// 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; - //} - } - } -} diff --git a/Python Version/ffglitch/jscripts/Shift.js b/Python Version/ffglitch/jscripts/Shift.js deleted file mode 100644 index 2c463ff..0000000 --- a/Python Version/ffglitch/jscripts/Shift.js +++ /dev/null @@ -1,74 +0,0 @@ -// 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; - } - } -} diff --git a/Python Version/ffglitch/jscripts/Sink.js b/Python Version/ffglitch/jscripts/Sink.js deleted file mode 100644 index 6a86c38..0000000 --- a/Python Version/ffglitch/jscripts/Sink.js +++ /dev/null @@ -1,38 +0,0 @@ -// 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; - } - } - } -} diff --git a/Python Version/ffglitch/jscripts/Slam Zoom.js b/Python Version/ffglitch/jscripts/Slam Zoom.js deleted file mode 100644 index 6993c42..0000000 --- a/Python Version/ffglitch/jscripts/Slam Zoom.js +++ /dev/null @@ -1,37 +0,0 @@ -// 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; - //} - } - } -} diff --git a/Python Version/ffglitch/jscripts/Slice.js b/Python Version/ffglitch/jscripts/Slice.js deleted file mode 100644 index 4ae40b2..0000000 --- a/Python Version/ffglitch/jscripts/Slice.js +++ /dev/null @@ -1,68 +0,0 @@ -// 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; - } -} diff --git a/Python Version/ffglitch/jscripts/Stop.js b/Python Version/ffglitch/jscripts/Stop.js deleted file mode 100644 index 3cf8ea4..0000000 --- a/Python Version/ffglitch/jscripts/Stop.js +++ /dev/null @@ -1,56 +0,0 @@ -// 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; - } -} diff --git a/Python Version/ffglitch/jscripts/Vibrate.js b/Python Version/ffglitch/jscripts/Vibrate.js deleted file mode 100644 index a33f759..0000000 --- a/Python Version/ffglitch/jscripts/Vibrate.js +++ /dev/null @@ -1,29 +0,0 @@ -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)); - } - } -} diff --git a/Python Version/ffglitch/jscripts/Zoom.js b/Python Version/ffglitch/jscripts/Zoom.js deleted file mode 100644 index 4f63b58..0000000 --- a/Python Version/ffglitch/jscripts/Zoom.js +++ /dev/null @@ -1,38 +0,0 @@ -// 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; - //} - } - } -} diff --git a/Python Version/pymosh/__init__.py b/Python Version/pymosh/__init__.py deleted file mode 100644 index f44ff8c..0000000 --- a/Python Version/pymosh/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -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) diff --git a/Python Version/pymosh/codec/__init__.py b/Python Version/pymosh/codec/__init__.py deleted file mode 100644 index 8b13789..0000000 --- a/Python Version/pymosh/codec/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Python Version/pymosh/codec/mpeg4.py b/Python Version/pymosh/codec/mpeg4.py deleted file mode 100644 index 3e4952d..0000000 --- a/Python Version/pymosh/codec/mpeg4.py +++ /dev/null @@ -1,6 +0,0 @@ -IFRAME_HEADER = b'\x00\x00\x01\xb0' - - -def is_iframe(frame): - """Determine whether frame is an I frame.""" - return frame[:4] == IFRAME_HEADER diff --git a/Python Version/pymosh/container/__init__.py b/Python Version/pymosh/container/__init__.py deleted file mode 100644 index 8b13789..0000000 --- a/Python Version/pymosh/container/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Python Version/pymosh/container/avi.py b/Python Version/pymosh/container/avi.py deleted file mode 100644 index 95f5cb8..0000000 --- a/Python Version/pymosh/container/avi.py +++ /dev/null @@ -1,124 +0,0 @@ -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 diff --git a/Python Version/pymosh/container/riff.py b/Python Version/pymosh/container/riff.py deleted file mode 100644 index bc2f18a..0000000 --- a/Python Version/pymosh/container/riff.py +++ /dev/null @@ -1,263 +0,0 @@ -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(' 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(' bytes: - """Returns a byte array representation of the chunk.""" - return self.header + struct.pack(' 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('