Skip to content

Commit

Permalink
added new UI for python version
Browse files Browse the repository at this point in the history
Now python users can also enjoy the easy UI
  • Loading branch information
Akascape authored Jul 18, 2022
1 parent 7933558 commit a964ecf
Show file tree
Hide file tree
Showing 37 changed files with 2,546 additions and 0 deletions.
Binary file added Python Version/Assets/Icons/Logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Python Version/Assets/Icons/Program_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Python Version/Assets/Icons/right_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Python Version/Assets/Icons/settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Python Version/Assets/Icons/video_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions Python Version/Assets/version/VERSIONPY.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.8
154 changes: 154 additions & 0 deletions Python Version/DatamoshLib/FFG_effects/basic_modes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#Author: Akash Bora
import os, shutil, subprocess, random, json
from pathlib import Path
import numpy as np
DIRPATH = Path(os.path.dirname(os.path.realpath(__file__)))
ffgac=str(DIRPATH.parent.parent).replace(os.sep, '/')+"/FFglitch/ffgac"
ffedit=str(DIRPATH.parent.parent).replace(os.sep, '/')+"/FFglitch/ffedit"

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

// global variable holding forward motion vectors from previous frames
var prev_fwd_mvs = [ ];

// change these values to use a smaller or greater number of frames to
// perform the average of motion vectors

// try making the delay long enough to overlap an edit in the content ...
var delay = 10;
// divisor controls "feedback" ... or "feedforward" which ever is a better description ...
var feedback = 0.5; // a number between 0.000001 and .... yeah - controls how much of the buffered mv gets into the next pass

var divisor = 1.0/feedback;

function glitch_frame(frame)
{
// bail out if we have no motion vectors
let mvs = frame["mv"];
if ( !mvs )
return;
// bail out if we have no forward motion vectors
let fwd_mvs = mvs["forward"];
if ( !fwd_mvs )
return;

// update variable holding forward motion vectors from previous
// frames. note that we perform a deep copy of the clean motion
// vector values before modifying them.
let json_str = JSON.stringify(fwd_mvs);
let deep_copy = JSON.parse(json_str);
// push to the end of array
prev_fwd_mvs.push(deep_copy);
// drop values from earliest frames to always keep the same tail
// length
if ( prev_fwd_mvs.length > delay )
prev_fwd_mvs = prev_fwd_mvs.slice(1);

// bail out if we still don't have enough frames
if ( prev_fwd_mvs.length != delay )
return;

// replace all motion vectors of current frame with an average
// of the motion vectors from the previous 10 frames
for ( let i = 0; i < fwd_mvs.length; i++ )
{
// loop through all rows
let row = fwd_mvs[i];
let delay_row = prev_fwd_mvs[0][i];
let insert_row = prev_fwd_mvs[delay-1][i];

for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];
let dmv = delay_row[j];
let imv = insert_row[j];
// THIS IS WHERE THE MAGIC HAPPENS

// temp copy of the incoming vectors
let x = mv[0];
let y = mv[1];
// pull their replacements out of the buffer
mv[0] = dmv[0];
mv[1] = dmv[1];
// feedback the 'old' with the 'new' for next time
imv[0] = (dmv[0] / divisor) + x;
imv[1] = (dmv[1] / divisor) + y;
// rinse and repeat

}
}
}
71 changes: 71 additions & 0 deletions Python Version/DatamoshLib/FFG_effects/jscripts/Delay.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// dd_delay.js
// works kinda like an audio delay
// stacks the previous n frames into a buffer

// global variable holding forward motion vectors from previous frames
var prev_fwd_mvs = [ ];

// change these values to use a smaller or greater number of frames to
// perform the average of motion vectors

// try making the delay long enough to overlap an edit in the content ...
var delay = 20;

function glitch_frame(frame)
{
// bail out if we have no motion vectors
let mvs = frame["mv"];
if ( !mvs )
return;
// bail out if we have no forward motion vectors
let fwd_mvs = mvs["forward"];
if ( !fwd_mvs )
return;

// update variable holding forward motion vectors from previous
// frames. note that we perform a deep copy of the clean motion
// vector values before modifying them.
let json_str = JSON.stringify(fwd_mvs);
let deep_copy = JSON.parse(json_str);
// push to the end of array
prev_fwd_mvs.push(deep_copy);
// drop values from earliest frames to always keep the same tail
// length
if ( prev_fwd_mvs.length > delay )
prev_fwd_mvs = prev_fwd_mvs.slice(1);

// bail out if we still don't have enough frames
if ( prev_fwd_mvs.length != delay )
return;

// replace all motion vectors of current frame with an average
// of the motion vectors from the previous 10 frames
for ( let i = 0; i < fwd_mvs.length; i++ )
{
// loop through all rows
let row = fwd_mvs[i];
let delay_row = prev_fwd_mvs[0][i];
let insert_row = prev_fwd_mvs[delay-1][i];

for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];
let dmv = delay_row[j];
let imv = insert_row[j];
// THIS IS WHERE THE MAGIC HAPPENS

// temp copy of the incoming vectors
let x = mv[0];
let y = mv[1];
// pull their replacements out of the buffer
mv[0] = dmv[0];
mv[1] = dmv[1];
// feedback the 'old' with the 'new' for next time
imv[0] = x;
imv[1] = y;
// rinse and repeat

}
}
}
58 changes: 58 additions & 0 deletions Python Version/DatamoshLib/FFG_effects/jscripts/Invert-Reverse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// dd_RandomDamage(invertRandomN).js
// invert x and y component of mv for random number of frames if threshold met for frame

let threshold = 95;
var TRIGGERED = 0;
var nFrames = 10;
var frameCount = 0;
var MAGNITUDE = 20;

function glitch_frame(frame)
{

var do_or_not = Math.random() * 100;
if(do_or_not > threshold){
if(TRIGGERED > 0){

}else{
TRIGGERED = 1;
frameCount = 0;
nFrames = Math.random() * MAGNITUDE;
}
}
// only do the glitch if our random number crosses the threshold
if(TRIGGERED > 0 & frameCount <= nFrames){
frameCount++;

// bail out if we have no motion vectors
let mvs = frame["mv"];
if ( !mvs )
return;
// bail out if we have no forward motion vectors
let fwd_mvs = mvs["forward"];
if ( !fwd_mvs )
return;

var M_H = fwd_mvs.length/2;
// clear horizontal element of all motion vectors
for ( let i = 0; i < fwd_mvs.length; i++ )
{
// loop through all rows
let row = fwd_mvs[i];
var M_W = row.length/2;

for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
let mv = row[j];

// THIS IS WHERE THE MAGIC HAPPENS
// STOP XY
mv[0] = 0 - mv[0];
mv[1] = 0 - mv[1];
}
}
}else{
TRIGGERED = 0;
}
}
Loading

0 comments on commit a964ecf

Please sign in to comment.