-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Now python users can also enjoy the easy UI
- Loading branch information
Showing
37 changed files
with
2,546 additions
and
0 deletions.
There are no files selected for viewing
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.
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.
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
1.8 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
58
Python Version/DatamoshLib/FFG_effects/jscripts/Invert-Reverse.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
Oops, something went wrong.