transferring several commands from private repo
This commit is contained in:
51
av/ffmpeg-magic
Executable file
51
av/ffmpeg-magic
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ "$1" = "-h" ]]; then
|
||||
echo This script prints out various ffmpeg commands
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
cat <<'EOF' | md-color
|
||||
# Basic Good Quality
|
||||
a) -hide_banner -q:v 0 -q:a 0
|
||||
b) -s hd720 -g 250 -c:v libx264 -crf 23 -c:a aac -movflags faststart -strict -2
|
||||
YIFY) -c:v libx264 -crf 27 -x264-params cabac=1:ref=5:analyse=0x133:me=umh:subme=9:chroma-me=1:deadzone-inter=21:deadzone-intra=11:b-adapt=2:rc-lookahead=60:vbv-maxrate=10000:vbv-bufsize=10000:qpmax=69:bframes=5:b-adapt=2:direct=auto:crf-max=51:weightp=2:merange=24:chroma-qp-offset=-1:sync-lookahead=2:psy-rd=1.00,0.15:trellis=2:min-keyint=23:partitions=all -c:a aac -ar 44100 -b:a 128k -map 0
|
||||
# Smooth slow motion
|
||||
-filter:v "minterpolate='mi_mode=mci:mc_mode=aobmc:vsbmc=1:fps=120'",setpts=1.5*PTS
|
||||
# BCS + unsharp (works also on -filter_complex)
|
||||
-vf unsharp,"eq=contrast=1.4:brightness=0.1:saturation=1.5"
|
||||
# More filters to try
|
||||
histeq=strength=0.1,normalize=blackpt=red:whitept=yellow:smoothing=150,hqdn3d=4:4:3:3"
|
||||
# Trim
|
||||
-vcodec copy -acodec copy -ss 00:01:30 -to 00:02:30
|
||||
-vcodec copy -acodec copy -ss 50 -to 65
|
||||
# Vertical2Horizontal
|
||||
-filter_complex "[0:v]scale=ih*16/9:-1,boxblur=luma_radius=min(h\,w)/20:luma_power=1:chroma_radius=min(cw\,ch)/20:chroma_power=1[bg];[bg][0:v]overlay=(W-w)/2:(H-h)/2,crop=h=iw*9/16"
|
||||
# Rotate 0=90CCW+flip,1=90CW,2=90CCW,3=90CW+flip. example 180 deg.
|
||||
-vf "transpose=2,transpose=2"
|
||||
# Antishake-Stabilize
|
||||
in=videofile.mp4
|
||||
ffmpeg -i "$in" -vf vidstabdetect=stepsize=32:shakiness=10:accuracy=10:result="$in".transforms.trf -f null -
|
||||
ffmpeg -i "$in" -vf vidstabtransform=input="$in".transforms.trf:zoom=0:smoothing=10,unsharp=5:5:0.8:3:3:0.4 -q:v 0 "$in".stabilized.mp4
|
||||
# To Stills
|
||||
-vf fps=10 "$1".%06d.png
|
||||
# From Stills
|
||||
-r 1/5 -start_number 0 -i img%03d.png -r 30 -pix_fmt yuv420p
|
||||
# Segment
|
||||
-segment_time 00:15:00 -f segment -reset_timestamps 1 "$in.%03d.480p.mp4"
|
||||
# Stacking
|
||||
-i input0 -i input1 -filter_complex vstack=inputs=2
|
||||
-i input0 -i input1 -filter_complex h stack=inputs=2
|
||||
# Chroma key
|
||||
-f lavfi -i color=c=green:s=1920x1080 -i input.mp4 -filter_complex "[1:v]chromakey=0x297141:0.1:0.0[ckout];[0:v][ckout]overlay[o]" -map [o] -map 1:a
|
||||
# View live
|
||||
-pix_fmt yuv420p -f matroska - | ffplay -i -
|
||||
# Concatenate
|
||||
find . -type f -printf "file '%P'\n" | sort -V > filelist.txt
|
||||
ffmpeg -f concat -safe 0 -i filelist.txt -c copy concatenated.mp4
|
||||
# Audio encode
|
||||
ffmpeg -i file.wav -codec:a libmp3lame -qscale:a 2 file.mp3
|
||||
# Audio map
|
||||
ffmpeg -i input.mp4 -i input.mp3 -c copy -map 0:0 -map 1:1 -shortest out.mp4
|
||||
EOF
|
||||
292
av/ffmpeg-parser
Executable file
292
av/ffmpeg-parser
Executable file
@@ -0,0 +1,292 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import parse
|
||||
from ansi import cursor
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class Chopper:
|
||||
def __init__(self, buf):
|
||||
self.buffer = buf
|
||||
self.memory = bytearray()
|
||||
self.eol1 = b"\r"
|
||||
self.eol2 = b"\n"
|
||||
self.leneol = len(self.eol1)
|
||||
|
||||
def read(self):
|
||||
line = bytearray()
|
||||
while True:
|
||||
c = self.buffer.read(1)
|
||||
if c:
|
||||
line += c
|
||||
if line[-self.leneol :] == self.eol1:
|
||||
break
|
||||
if line[-self.leneol :] == self.eol2:
|
||||
break
|
||||
else:
|
||||
break
|
||||
return bytes(line).decode("utf-8")
|
||||
|
||||
|
||||
class Progress:
|
||||
def __init__(self):
|
||||
self.started = time.time()
|
||||
self.duration = None
|
||||
self.framedata = {}
|
||||
self.parsable = (
|
||||
"frame",
|
||||
"fps",
|
||||
"bitrate",
|
||||
"total_size",
|
||||
"speed",
|
||||
"out_time_ms",
|
||||
)
|
||||
self.inputs = []
|
||||
self.inputs_full = []
|
||||
self.input = "NA"
|
||||
self.input_size = "NA"
|
||||
self.outputs = []
|
||||
self.output = "NA"
|
||||
|
||||
def parse(self, line):
|
||||
|
||||
if not self.parse_frame(line):
|
||||
print(line.rstrip())
|
||||
self.parse_input(line)
|
||||
self.parse_output(line)
|
||||
self.parse_duration(line)
|
||||
|
||||
self.print()
|
||||
|
||||
def parse_input(self, line):
|
||||
|
||||
# Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'VID_20210804_141045.mp4':
|
||||
parsed = parse.parse("Input #{:d}, {}, from '{}':", line.strip())
|
||||
try:
|
||||
self.inputs.append(os.path.basename(parsed[2]))
|
||||
self.inputs_full.append(parsed[2])
|
||||
self.input = ", ".join(self.inputs)
|
||||
self.input_size = ", ".join(
|
||||
[self._mbstr(os.stat(i).st_size) for i in self.inputs_full]
|
||||
)
|
||||
except Exception:
|
||||
return
|
||||
|
||||
def parse_output(self, line):
|
||||
|
||||
parsed = parse.parse("Output #{:d}, {}, to '{}':", line.strip())
|
||||
try:
|
||||
self.outputs.append(os.path.basename(parsed[2]))
|
||||
self.output = ", ".join(self.outputs)
|
||||
except Exception:
|
||||
return
|
||||
|
||||
def parse_duration(self, line):
|
||||
|
||||
if self.duration:
|
||||
return
|
||||
parsed = parse.parse(
|
||||
"Duration: {:d}:{:d}:{:d}.{:d}, start: {}, bitrate: {} kb/s", line.strip()
|
||||
)
|
||||
# ~ Duration: 00:00:48.21, start: 0.000000, bitrate: 17780 kb/s
|
||||
try:
|
||||
self.duration = 3600 * parsed[0] + 60 * parsed[1] + parsed[2]
|
||||
except Exception:
|
||||
return
|
||||
|
||||
def parse_frame(self, line):
|
||||
|
||||
try:
|
||||
values = len(line.strip().split("="))
|
||||
if values > 2: # and line.startswith("frame="):
|
||||
return True
|
||||
if values != 2:
|
||||
return False
|
||||
parsed = parse.parse("{}={}", line.strip())
|
||||
if not parsed:
|
||||
return False
|
||||
if parsed[0] in self.parsable:
|
||||
if parsed[0] == "out_time_ms":
|
||||
self.framedata["out_time_s"] = float(parsed[1]) / 1000000
|
||||
else:
|
||||
self.framedata[parsed[0]] = parsed[1]
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def print(self):
|
||||
|
||||
if len(self.framedata) == 0:
|
||||
return
|
||||
|
||||
self.framedata["time_elapsed"] = int(time.time() - self.started)
|
||||
if "out_time_s" in self.framedata:
|
||||
self.framedata["percent_done"] = round(
|
||||
100 * self.framedata["out_time_s"] / self.duration, 1
|
||||
)
|
||||
try:
|
||||
if self.framedata["percent_done"] > 100:
|
||||
self.framedata["time_remaining"] = "NA"
|
||||
else:
|
||||
self.framedata["time_remaining"] = int(
|
||||
(
|
||||
100
|
||||
* float(time.time() - self.started)
|
||||
/ self.framedata["percent_done"]
|
||||
)
|
||||
- self.framedata["time_elapsed"]
|
||||
)
|
||||
except Exception:
|
||||
self.framedata["time_remaining"] = "NA"
|
||||
try:
|
||||
self.framedata["projected_size"] = int(
|
||||
(
|
||||
100
|
||||
* float(self.framedata["total_size"])
|
||||
/ self.framedata["percent_done"]
|
||||
)
|
||||
)
|
||||
except Exception:
|
||||
self.framedata["time_remaining"] = "NA"
|
||||
else:
|
||||
self.framedata["percent_done"] = "NA"
|
||||
self.framedata["time_remaining"] = "NA"
|
||||
self.framedata["projected_size"] = "NA"
|
||||
|
||||
try:
|
||||
msg = """{cl}==== Q to exit ===============
|
||||
{cl}Input: {input_file}
|
||||
{cl}Output: {output_file}
|
||||
{cl}Progress: {progress}% Elapsed: H{elapsed}
|
||||
{cl}Finished in: H{left}
|
||||
{cl}Frame: {frame} = {out_time}
|
||||
{cl}Source duration: {duration}
|
||||
{cl}Processing speed: FPS {fps} / {speed}
|
||||
{cl}Bitrate: {bitrate}
|
||||
{cl}File size: {total_size}Mb -> {projected_size}Mb (Input: {input_size}Mb)
|
||||
{cl}{progress_bar}\r{up}""".format(
|
||||
input_file=self.input,
|
||||
input_size=self.input_size,
|
||||
output_file=self.output,
|
||||
progress=self.framedata["percent_done"],
|
||||
progress_bar=self._progress_bar(self.framedata["percent_done"]),
|
||||
elapsed=self._timestr(self.framedata["time_elapsed"]),
|
||||
left=self._timestr(self.framedata["time_remaining"]),
|
||||
duration=self._timestr(self.duration),
|
||||
out_time=self._timestr(self.framedata["out_time_s"]),
|
||||
frame=self.framedata.get("frame", "NA"),
|
||||
fps=self.framedata.get("fps", "NA"),
|
||||
bitrate=self.framedata["bitrate"],
|
||||
speed=self.framedata["speed"],
|
||||
total_size=self._mbstr(self.framedata["total_size"]),
|
||||
projected_size=self._mbstr(self.framedata["projected_size"]),
|
||||
up=cursor.up(10),
|
||||
cl=cursor.erase_line(),
|
||||
)
|
||||
|
||||
sys.stdout.write(msg)
|
||||
sys.stdout.flush()
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
def finish(self):
|
||||
|
||||
for i in range(len(self.framedata) + 3):
|
||||
sys.stdout.write("\n")
|
||||
sys.stdout.flush()
|
||||
|
||||
def _timestr(self, sec):
|
||||
|
||||
try:
|
||||
hours = int(sec) // 3600 % 24
|
||||
minutes = int(sec) // 60 % 60
|
||||
seconds = int(sec) % 60
|
||||
return "{:02d}:{:02d}:{:02d}".format(hours, minutes, seconds)
|
||||
except Exception:
|
||||
return sec
|
||||
|
||||
def _mbstr(self, b):
|
||||
|
||||
try:
|
||||
return "{:.1f}".format((float(b) / (1024 ** 2)))
|
||||
except Exception:
|
||||
return b
|
||||
|
||||
def _progress_bar(self, p):
|
||||
|
||||
try:
|
||||
done_chars = int(float(p) * 30 / 100)
|
||||
todo_chars = int(30 - done_chars)
|
||||
return (">" * done_chars + "-" * todo_chars)[0:30]
|
||||
except Exception:
|
||||
return ">" * 30
|
||||
|
||||
|
||||
def parse_output(args):
|
||||
return args[-1]
|
||||
|
||||
|
||||
def parse_overwrite(args):
|
||||
return "-y" in args
|
||||
|
||||
|
||||
def ask_for_overwrite(commands, path):
|
||||
|
||||
print("File {} exists. Overwrite or break? ([y]/n)".format(path))
|
||||
answer = input()
|
||||
if answer == "n":
|
||||
sys.exit(1)
|
||||
|
||||
commands.insert(-1, "-y")
|
||||
return commands
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
commands = sys.argv[1:]
|
||||
if len(commands) == 1:
|
||||
if commands[0] == "-h":
|
||||
print("This command passes all arguments to FFMPEG, and parses output to readable format with progress")
|
||||
sys.exit(0)
|
||||
try:
|
||||
has_overwrite = parse_overwrite(commands)
|
||||
if not has_overwrite:
|
||||
output_file = parse_output(commands)
|
||||
output_exists = os.path.exists(output_file)
|
||||
if output_exists:
|
||||
commands = ask_for_overwrite(commands, output_file)
|
||||
|
||||
process = subprocess.Popen(
|
||||
["", "-progress", "pipe:2", "-hide_banner"] + commands,
|
||||
executable="ffmpeg",
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
chopper = Chopper(process.stdout)
|
||||
progress = Progress()
|
||||
|
||||
started = time.time()
|
||||
duration = None
|
||||
while True:
|
||||
output = chopper.read()
|
||||
progress.parse(output)
|
||||
if not output:
|
||||
if process.poll() != None:
|
||||
break
|
||||
|
||||
rc = process.poll()
|
||||
progress.finish()
|
||||
print("Exit code: {}".format(rc))
|
||||
sys.exit(rc)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
process.terminate()
|
||||
progress.finish()
|
||||
while process.poll() != None:
|
||||
time.sleep(1)
|
||||
sys.exit(1)
|
||||
155
av/ffmpeg-screencapture
Executable file
155
av/ffmpeg-screencapture
Executable file
@@ -0,0 +1,155 @@
|
||||
#!/bin/bash
|
||||
|
||||
_help() {
|
||||
echo 'Commands:
|
||||
-o [filename] -s [size] -p [pos] -r [framerate] -d [delay] -i
|
||||
default filename: '$filename'
|
||||
default size: '$size'
|
||||
default pos: '$pos'
|
||||
default framerate: '$framerate'
|
||||
default delay: '$delay'
|
||||
-i for interactive selection using "slop"
|
||||
--shell to record current terminal
|
||||
|
||||
Hit "q" when finished!
|
||||
'
|
||||
}
|
||||
_helpexit(){
|
||||
_help
|
||||
exit
|
||||
}
|
||||
function animate() {
|
||||
x0=$( tput cols )
|
||||
pre=$( qolop eval "_qPos save; _qPos abs 1 $x0; _qCol R;" )
|
||||
post=$( qolop eval "_qCol Z; _qPos restore;" )
|
||||
while true; do
|
||||
{
|
||||
printf "%s*%s" "$pre" "$post"
|
||||
sleep 1
|
||||
printf "%s %s" "$pre" "$post"
|
||||
sleep 1
|
||||
} >&2
|
||||
done
|
||||
}
|
||||
|
||||
printf -v filename "grab-%(%FT%H-%M)T.mp4"
|
||||
size=$( xdpyinfo | awk "/dimensions/{print \$2}" )
|
||||
pos="0,0"
|
||||
framerate=15
|
||||
delay=0
|
||||
interact=0
|
||||
new_shell=0
|
||||
for (( i=1; i<=$#; i++ )); do
|
||||
[[ ${!i} = "-h"* ]] && _helpexit
|
||||
[[ ${!i} = "--h"* ]] && _helpexit
|
||||
[[ ${!i} = "help" ]] && _helpexit
|
||||
done
|
||||
for (( i=1; i<=$#; i++ )); do
|
||||
j=$(( $i + 1 ))
|
||||
if [[ ${!i} = "-o" ]]; then
|
||||
filename="${!j}"
|
||||
shift
|
||||
fi
|
||||
if [[ ${!i} = "-s" ]]; then
|
||||
size="${!j}"
|
||||
shift
|
||||
fi
|
||||
if [[ ${!i} = "-p" ]]; then
|
||||
pos="${!j}"
|
||||
shift
|
||||
fi
|
||||
if [[ ${!i} = "-r" ]]; then
|
||||
framerate="${!j}"
|
||||
shift
|
||||
fi
|
||||
if [[ ${!i} = "-d" ]]; then
|
||||
delay="${!j}"
|
||||
shift
|
||||
fi
|
||||
if [[ ${!i} = "-i" ]]; then
|
||||
interact=1
|
||||
fi
|
||||
if [[ ${!i} = "--shell" ]]; then
|
||||
new_shell=1
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
if [[ $new_shell -eq 0 ]]; then
|
||||
|
||||
if [[ $interact -eq 1 ]]; then
|
||||
slop=$( slop -b 10 -c 1.0,0.8,0.1,0.8 )
|
||||
size=$( echo $slop | cut -d+ -f1 )
|
||||
pos=$( echo $slop | cut -d+ -f2-3 )
|
||||
pos=${pos/+/,}
|
||||
else
|
||||
convert -size 256x256 xc:red PNG8:- | timeout 5 feh --geometry $size+${pos//,/+} -
|
||||
fi
|
||||
else
|
||||
eval $(xwininfo -id $(xdotool getactivewindow) |
|
||||
sed -n -e "s/^ \+Absolute upper-left X: \+\([0-9]\+\).*/x=\1/p" \
|
||||
-e "s/^ \+Absolute upper-left Y: \+\([0-9]\+\).*/y=\1/p" \
|
||||
-e "s/^ \+Width: \+\([0-9]\+\).*/w=\1/p" \
|
||||
-e "s/^ \+Height: \+\([0-9]\+\).*/h=\1/p" )
|
||||
size="${w}x${h}"
|
||||
pos="${x},${y}"
|
||||
fi
|
||||
|
||||
|
||||
if [[ $delay -gt 0 ]]; then
|
||||
echo Waiting.. for $delay seconds
|
||||
sleep $delay
|
||||
fi
|
||||
|
||||
|
||||
echo Grabbing: $filename ${size}+$pos
|
||||
|
||||
rm -f "$filename"
|
||||
|
||||
if [[ $new_shell -eq 1 ]]; then
|
||||
|
||||
echo Starting to record in 5 seconds, or press enter
|
||||
read -t 5 foo || true
|
||||
x0=$( tput cols )
|
||||
pre=$( qolop eval "_qPos save; _qPos abs 1 $x0; _qCol R;" )
|
||||
post=$( qolop eval "_qCol Z; _qPos restore;" )
|
||||
animate &
|
||||
animpid=$!
|
||||
trap 'trap - SIGTERM && kill -- $animpid' EXIT SIGINT SIGTERM
|
||||
ffmpeg \
|
||||
-video_size $size \
|
||||
-framerate $framerate \
|
||||
-f x11grab \
|
||||
-i $DISPLAY+${pos} \
|
||||
-vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" \
|
||||
-c:v libx264 -crf 23 -profile:v baseline -level 3.0 -pix_fmt yuv420p \
|
||||
-an \
|
||||
-movflags faststart \
|
||||
-loglevel panic \
|
||||
-hide_banner \
|
||||
"$filename" &
|
||||
ffpid=$!
|
||||
clear
|
||||
bash
|
||||
kill -INT $ffpid
|
||||
trap - EXIT SIGINT SIGTERM
|
||||
kill $animpid > /dev/null 2>&1
|
||||
#animate_clear
|
||||
printf "%s %s" "$pre" "$post" >&2
|
||||
|
||||
else
|
||||
ffmpeg \
|
||||
-video_size $size \
|
||||
-framerate $framerate \
|
||||
-f x11grab \
|
||||
-i $DISPLAY+${pos} \
|
||||
-vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" \
|
||||
-c:v libx264 -crf 23 -profile:v baseline -level 3.0 -pix_fmt yuv420p \
|
||||
-an \
|
||||
-movflags faststart \
|
||||
-loglevel panic \
|
||||
-hide_banner \
|
||||
"$filename"
|
||||
fi
|
||||
|
||||
echo "Saved to: $filename"
|
||||
216
av/video-compress
Executable file
216
av/video-compress
Executable file
@@ -0,0 +1,216 @@
|
||||
#!/bin/bash
|
||||
|
||||
. qolop
|
||||
|
||||
get_toggles() {
|
||||
toggles=$(
|
||||
echo "$@" | \
|
||||
smenu -m "Toggle with t" -n 10 -t 1 -a m:7,bu i:8 c:2 t:7/0 ct:2/0 -T ' '
|
||||
# -m title
|
||||
# -n rows
|
||||
# -t columns
|
||||
# -a styless: m title, i items, c cursor, t tagged, ct cursor on tagged
|
||||
# -T multiselect
|
||||
)
|
||||
}
|
||||
|
||||
get_choice() {
|
||||
choice=$(
|
||||
echo "$@" | \
|
||||
smenu -n 10 -t 1 -a c:10 -s "$lastchoice"
|
||||
# -m title
|
||||
# -n rows
|
||||
# -t columns
|
||||
# -a styless: m title, i items, c cursor, t tagged, ct cursor on tagged
|
||||
# -T multiselect
|
||||
)
|
||||
}
|
||||
|
||||
get_resize() {
|
||||
title Resize
|
||||
echo "$resize"
|
||||
echo ""
|
||||
|
||||
get_choice no-resize hd480 hd720 hd1080 640x360 356x200 manual
|
||||
case $choice in
|
||||
no-resize) resize="";;
|
||||
manual)
|
||||
echo "Type resolution WxH"
|
||||
read -e size
|
||||
resize="-s $size"
|
||||
;;
|
||||
*) resize="-s $choice";;
|
||||
esac
|
||||
}
|
||||
|
||||
get_compression() {
|
||||
title Compression
|
||||
echo "$compression"
|
||||
echo ""
|
||||
|
||||
get_choice x264 copy similar YIFY
|
||||
case $choice in
|
||||
x264)
|
||||
echo Video quality: 23 = good, 18 = insane, 30 = poor
|
||||
read -e -i "$crf" crf
|
||||
compression="-g 250 -c:v libx264 -crf $crf"
|
||||
;;
|
||||
copy) compression="-vcodec copy";;
|
||||
similar) compression="-c:v libx264 -q:v 0";;
|
||||
YIFY)
|
||||
compression="$yify_compression"
|
||||
audio=""
|
||||
;;
|
||||
*) return;;
|
||||
esac
|
||||
}
|
||||
|
||||
get_audio() {
|
||||
title Audio
|
||||
echo "$audio"
|
||||
echo ""
|
||||
|
||||
get_choice aac copy similar no-audio
|
||||
lastchoice="$choice"
|
||||
case $choice in
|
||||
aac)
|
||||
echo Audio quality: 64 poor, 128 good
|
||||
read -e -i "$abit" abit
|
||||
audio="-c:a aac -ar 44100 -b:a ${abit}k -strict -2"
|
||||
;;
|
||||
copy) audio="-acodec copy";;
|
||||
similar) audio="-q:a 0";;
|
||||
no-audio) audio="-an";;
|
||||
*) return;;
|
||||
esac
|
||||
}
|
||||
|
||||
title() {
|
||||
_qCol Y S; echo ""; echo "$1":; _qCol z
|
||||
}
|
||||
|
||||
helpexit() {
|
||||
echo "
|
||||
echo convert with ffmpeg: [preset] inputfile [outputfile]
|
||||
|
||||
Pressing q will stop, and you can use the command from the screen.
|
||||
|
||||
Presets do no ask questions:
|
||||
-low crf:27 abit:64k size:hd480
|
||||
-medium crf:23 abit:96k
|
||||
-high crf:18 abit:128k
|
||||
-yify
|
||||
-custom:crf:abit:[resolution]
|
||||
|
||||
-y overwrite existing files
|
||||
"
|
||||
exit
|
||||
}
|
||||
|
||||
# Defaults
|
||||
resize=""
|
||||
crf=23
|
||||
abit=128
|
||||
yify_compression="-c:v libx264 -crf 26 -x264-params cabac=1:ref=5:analyse=0x133:me=umh:subme=9:chroma-me=1:deadzone-inter=21:deadzone-intra=11:b-adapt=2:rc-lookahead=60:vbv-maxrate=10000:vbv-bufsize=10000:qpmax=69:bframes=5:b-adapt=2:direct=auto:crf-max=51:weightp=2:merange=24:chroma-qp-offset=-1:sync-lookahead=2:psy-rd=1.00,0.15:trellis=2:min-keyint=23:partitions=all -c:a aac -ar 44100 -b:a 128k -map 0"
|
||||
preset="compress"
|
||||
overwrite=""
|
||||
|
||||
if [[ -z "$1" ]]; then helpexit; fi
|
||||
for (( i=1; i<=$#; i++ )); do
|
||||
[[ ${!i} = "-h" ]] && helpexit
|
||||
[[ ${!i} = "-low" ]] && {
|
||||
FORCE=1
|
||||
crf=27
|
||||
abit=64
|
||||
resize="-s hd480"
|
||||
preset="low"
|
||||
shift 1
|
||||
}
|
||||
[[ ${!i} = "-med"* ]] && {
|
||||
FORCE=1
|
||||
crf=23
|
||||
abit=96
|
||||
preset="med"
|
||||
shift 1
|
||||
}
|
||||
[[ ${!i} = "-high" ]] && {
|
||||
FORCE=1
|
||||
crf=18
|
||||
abit=128
|
||||
preset="high"
|
||||
shift 1
|
||||
}
|
||||
[[ ${!i} = "-yify" ]] && {
|
||||
FORCE=1
|
||||
YIFY_PRESET=1
|
||||
preset="yify"
|
||||
shift 1
|
||||
}
|
||||
[[ ${!i} = "-custom"* ]] && {
|
||||
FORCE=1
|
||||
options="${!i}"
|
||||
option_array=( ${options//:/ } )
|
||||
crf=${option_array[1]}
|
||||
abit=${option_array[2]}
|
||||
resize=${option_array[3]}
|
||||
if [[ -n "$resize" ]]; then
|
||||
resize="-s $resize"
|
||||
fi
|
||||
shift 1
|
||||
}
|
||||
[[ ${!i} = "-y" ]] && {
|
||||
overwrite="-y"
|
||||
shift 1
|
||||
}
|
||||
done
|
||||
|
||||
compression="-g 250 -c:v libx264 -crf $crf"
|
||||
audio="-c:a aac -ar 44100 -b:a ${abit}k -strict -2"
|
||||
if [[ "$YIFY_PRESET" -eq 1 ]]; then
|
||||
compression="$yify_compression"
|
||||
audio=""
|
||||
fi
|
||||
inputfile="$1"
|
||||
outputfile="$2"
|
||||
inputname="${inputfile%.*}"
|
||||
if [[ -z "$outputfile" ]]; then outputfile="${inputname}.${preset}.mp4";fi
|
||||
if [[ ! -e "$inputfile" ]]; then echo "Inputfile '$inputfile' missing"; exit 1; fi
|
||||
|
||||
ffprobe -hide_banner "$inputfile"
|
||||
|
||||
while true; do
|
||||
command="ffmpeg-parser -i \"$inputfile\" $resize $compression $audio -movflags faststart $overwrite \"$outputfile\""
|
||||
if [[ $FORCE -eq 1 ]]; then
|
||||
choice=EXECUTE
|
||||
else
|
||||
title Command
|
||||
echo "# $command"
|
||||
echo ""
|
||||
get_choice EXECUTE resize compression audio
|
||||
fi
|
||||
|
||||
case $choice in
|
||||
EXECUTE)
|
||||
title Execute
|
||||
echo "# $command"
|
||||
echo ""
|
||||
echo -n "Frames: "
|
||||
ffprobe -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 "$inputfile"
|
||||
echo ""
|
||||
setterm --linewrap off
|
||||
trap "setterm --linewrap on" 0 1 9 15
|
||||
eval "$command"
|
||||
ec=$?
|
||||
setterm --linewrap on
|
||||
echo "# $command"
|
||||
exit $?
|
||||
;;
|
||||
|
||||
resize) get_resize;;
|
||||
compression) get_compression;;
|
||||
audio) get_audio;;
|
||||
|
||||
*) exit;;
|
||||
esac
|
||||
done
|
||||
|
||||
1
bin/2fa-menu
Symbolic link
1
bin/2fa-menu
Symbolic link
@@ -0,0 +1 @@
|
||||
../shell/2fa-menu
|
||||
@@ -1 +0,0 @@
|
||||
../shell/2fa-view
|
||||
1
bin/ffmpeg-magic
Symbolic link
1
bin/ffmpeg-magic
Symbolic link
@@ -0,0 +1 @@
|
||||
../av/ffmpeg-magic
|
||||
1
bin/ffmpeg-parser
Symbolic link
1
bin/ffmpeg-parser
Symbolic link
@@ -0,0 +1 @@
|
||||
../av/ffmpeg-parser
|
||||
1
bin/ffmpeg-screencapture
Symbolic link
1
bin/ffmpeg-screencapture
Symbolic link
@@ -0,0 +1 @@
|
||||
../av/ffmpeg-screencapture
|
||||
1
bin/rclone-mount
Symbolic link
1
bin/rclone-mount
Symbolic link
@@ -0,0 +1 @@
|
||||
../web/rclone-mount
|
||||
1
bin/ssh-nosave
Symbolic link
1
bin/ssh-nosave
Symbolic link
@@ -0,0 +1 @@
|
||||
../web/ssh-nosave
|
||||
1
bin/ssh-scan-lan
Symbolic link
1
bin/ssh-scan-lan
Symbolic link
@@ -0,0 +1 @@
|
||||
../web/ssh-scan-lan
|
||||
1
bin/sshfs-mount
Symbolic link
1
bin/sshfs-mount
Symbolic link
@@ -0,0 +1 @@
|
||||
../web/sshfs-mount
|
||||
1
bin/video-compress
Symbolic link
1
bin/video-compress
Symbolic link
@@ -0,0 +1 @@
|
||||
../av/video-compress
|
||||
101
shell/2fa-menu
Executable file
101
shell/2fa-menu
Executable file
@@ -0,0 +1,101 @@
|
||||
#!/bin/bash
|
||||
_help() {
|
||||
echo '
|
||||
2FA code viewer
|
||||
|
||||
Usage:
|
||||
- Create a (possible encrypted) folder for your service keys
|
||||
- When the service presents you the QRCode, you typically can
|
||||
view the actual code as text. It looks something like:
|
||||
I5XXIY3IMEWCA3LBMRSSA6LPOUQGY33PNMQQU===
|
||||
- Store this piece of text in a file: "Service name".key
|
||||
- Run 2fa-menu command in the folder
|
||||
|
||||
Viewer:
|
||||
- Codes and service names are printed on the screen
|
||||
|
||||
'
|
||||
|
||||
exit
|
||||
}
|
||||
|
||||
for (( i=1; i<=$#; i++ )); do
|
||||
value=${!i}
|
||||
j=$(( i + 1 ))
|
||||
[[ "$value" = "--help" ]] && _help
|
||||
[[ "${value}" = "-"* ]] && {
|
||||
[[ "$value" =~ -.*h ]] && { _help; }
|
||||
continue
|
||||
}
|
||||
done
|
||||
|
||||
which oathtool &> /dev/null || {
|
||||
echo Missing oathtool
|
||||
exit 1
|
||||
}
|
||||
which smenu &> /dev/null || {
|
||||
echo Missing smenu
|
||||
exit 1
|
||||
}
|
||||
|
||||
timeadjust=0
|
||||
update_frequency=30
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
_exit() {
|
||||
clear
|
||||
exit
|
||||
}
|
||||
_get_code() {
|
||||
oathtool -b --totp $( cat "$1" | tr -dc '[:print:]' )
|
||||
}
|
||||
_print_codes() {
|
||||
echo "Refresh"
|
||||
even=0
|
||||
for k in *key; do
|
||||
name=${k%.key}
|
||||
name=${name//_/ }
|
||||
printf "%-${PAD_LENGTH}s [ %s ] \n" \
|
||||
"$name" \
|
||||
$( _get_code "$k" )
|
||||
even=$(( 1 - $even ))
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
while true; do
|
||||
clear
|
||||
PAD_LENGTH=0
|
||||
for key in *key; do
|
||||
name=${key%.key}
|
||||
if [[ ${#name} -gt $PAD_LENGTH ]]; then
|
||||
PAD_LENGTH=${#name}
|
||||
fi
|
||||
done
|
||||
|
||||
set -e
|
||||
new_codes=$( _print_codes )
|
||||
set +e
|
||||
codes=$new_codes
|
||||
i=$(( ( $( date +%s ) - $timeadjust ) % $update_frequency ))
|
||||
left=$(( $update_frequency - $i ))
|
||||
when=$( date -d "now + $left seconds" +"%H:%M:%S" )
|
||||
selected=$( echo -e "$codes" | smenu \
|
||||
-M -m "Codes change in ${left}s at $when" -W $'\n' \
|
||||
-t 1 -n 30 -a c:0/2 i:3 \
|
||||
)
|
||||
|
||||
if [[ -z "$selected" ]]; then
|
||||
exit
|
||||
fi
|
||||
if [[ "$selected" = "Refresh" ]]; then
|
||||
continue
|
||||
fi
|
||||
code=$( echo "$selected" | rev | cut -d" " -f2 | rev )
|
||||
echo Copying $code to clipboard
|
||||
echo -n $code | xclip -selection clipboard 2> /dev/null
|
||||
echo -n $code | xclip 2> /dev/null
|
||||
countdown -n 15
|
||||
exit
|
||||
done
|
||||
288
shell/2fa-view
288
shell/2fa-view
@@ -1,288 +0,0 @@
|
||||
#!/bin/bash
|
||||
_help() {
|
||||
echo '
|
||||
2FA code viewer
|
||||
|
||||
Usage:
|
||||
- Create a (possible encrypted) folder for your service keys
|
||||
- When the service presents you the QRCode, you typically can
|
||||
view the actual code as text. It looks something like:
|
||||
I5XXIY3IMEWCA3LBMRSSA6LPOUQGY33PNMQQU===
|
||||
- Store this piece of text in a file: "Service name".key
|
||||
- Run 2fa-view command in the folder
|
||||
|
||||
Viewer:
|
||||
- Codes and service names are printed on the screen
|
||||
- The upper timer shows the 30 second interval when
|
||||
the code changes
|
||||
- The lower timer shows time left before the program exits
|
||||
|
||||
Options:
|
||||
--light to disable animations
|
||||
--color X to prefer a color for the skull. Choose color from:
|
||||
k r g b c m y w K R G B C M Y W
|
||||
'
|
||||
|
||||
|
||||
exit
|
||||
}
|
||||
|
||||
for (( i=1; i<=$#; i++ )); do
|
||||
value=${!i}
|
||||
j=$(( i + 1 ))
|
||||
[[ "$value" = "--help" ]] && _help
|
||||
[[ "$value" = "--light" ]] && { LIGHT=1; continue; }
|
||||
[[ "$value" = "--color" ]] && {
|
||||
TFA_COLOR_TITLE="${!j}"
|
||||
((i++))
|
||||
continue;
|
||||
}
|
||||
[[ "${value}" = "-"* ]] && {
|
||||
[[ "$value" =~ -.*h ]] && { _help; }
|
||||
continue
|
||||
}
|
||||
done
|
||||
|
||||
which oathtool &> /dev/null || {
|
||||
echo Missing oathtool
|
||||
exit 1
|
||||
}
|
||||
|
||||
timeadjust=0
|
||||
update_frequency=30
|
||||
exit_timeout=120
|
||||
if [ "$1" = "light" ]; then LIGHT=1; fi
|
||||
shopt -s nullglob
|
||||
. qolop
|
||||
|
||||
picture=" ..;;;::;:;::;;:;,.
|
||||
.:::::;;;:;:::::::;;;;::;:;:.
|
||||
.::::;;::;::;:;::::::::::;:;::;::.
|
||||
,::::;:::::::;;;::;:;;::::;::::::::.
|
||||
';:::::::::::::::;;;;;;;:::;;::;;;:..
|
||||
';;::::',',',;:::;:;;;,'.;::::;;:;...
|
||||
.'. . .,:,.. ..
|
||||
' @ .::;:;. @ ..
|
||||
.:' .;: .::. .::.
|
||||
..,;;;:;:;;:' ,;,'';;,..,,'
|
||||
. .;;. .. .,::, .
|
||||
';:;;;::;;:::..:::
|
||||
,:::...;:. . .,,
|
||||
..
|
||||
"
|
||||
picture_colors="kkKKwwbm$TFA_COLOR_TITLE$TFA_COLOR_TITLE$TFA_COLOR_TITLE$TFA_COLOR_TITLE$TFA_COLOR_TITLE$TFA_COLOR_TITLE"
|
||||
picture_color_codes=()
|
||||
for x in $( seq 0 $(( ${#picture_colors} - 1 )) ); do
|
||||
picture_color_codes+=( $( _qCol ${picture_colors:$x:1} ) )
|
||||
done
|
||||
picture_eye=$( _qCol R )
|
||||
|
||||
_skull() {
|
||||
if [ "$LIGHT" = 1 ]; then return; fi
|
||||
_qPos abs 4 1
|
||||
for x in $( seq 1 ${#picture} ); do
|
||||
chr="${picture:$x:1}"
|
||||
if [ "$chr" = " " ]; then _qPos right 1; continue; fi
|
||||
color="${picture_color_codes[$(( $RANDOM % ${#picture_colors} ))]}"
|
||||
if [ "$chr" = "@" ]; then color="$picture_eye"; chr="o"; fi
|
||||
printf "%s%s" \
|
||||
"$color" \
|
||||
"$chr"
|
||||
done
|
||||
|
||||
_qCol z
|
||||
}
|
||||
|
||||
flame=( )
|
||||
for x in $( seq 1 $(( 44 * 8 )) ); do
|
||||
flame+=( 0 )
|
||||
done
|
||||
flame_mask_array=( \
|
||||
"11111000000000000000000000000000000000001111" \
|
||||
"11000000000000000000000000000000000000000001" \
|
||||
"00000000000000000000000000000000000000000000" \
|
||||
"00000000000000000000000000000000000000000000" \
|
||||
"10000000000001110110111111001110000000000001" \
|
||||
"11100000010111111111011110111101100000000111" \
|
||||
"11100000011111111111111111111111110000000111" \
|
||||
"11110001111111111111111111111111110100011111" \
|
||||
)
|
||||
flame_mask=( )
|
||||
for y in {0..7}; do
|
||||
for x in {0..43}; do
|
||||
flame_mask+=( ${flame_mask_array[$y]:$x:1} )
|
||||
done
|
||||
done
|
||||
flame_chars=" .:##@"
|
||||
flame_colors="zzzmryYY"
|
||||
flame_color_codes=()
|
||||
for x in $( seq 0 $(( ${#flame_colors} - 1 )) ); do
|
||||
flame_color_codes+=( $( _qCol ${flame_colors:$x:1} ) )
|
||||
done
|
||||
flame_next=$( _qPos right 1 )
|
||||
flame_corner=$( _qPos abs 1 1 )
|
||||
|
||||
_flames() {
|
||||
if [ "$LIGHT" = 1 ]; then return; fi
|
||||
width=43
|
||||
height=7
|
||||
seq_x=$( seq 0 $width )
|
||||
for x in $seq_x; do
|
||||
pos=$(( ( $height ) * ( $width + 1 ) + $x ))
|
||||
flame[$pos]=$(( $RANDOM % 256 ))
|
||||
done
|
||||
|
||||
for y in $( seq 0 $(( $height - 1 )) ); do
|
||||
for x in $seq_x; do
|
||||
if [ $x -eq $width ]; then continue; fi
|
||||
if [ $x -eq 0 ]; then continue; fi
|
||||
pos=$(( $y * ( $width + 1 ) + $x ))
|
||||
pos_under=$(( ( $y + 1 ) * ( $width + 1 ) + $x ))
|
||||
new_value=$(( ( ( \
|
||||
${flame[$(( $pos_under ))]} + \
|
||||
${flame[$(( $pos_under + 1 ))]} + \
|
||||
${flame[$(( $pos_under - 1 ))]} \
|
||||
) * 17 ) / 48 ))
|
||||
|
||||
if [ $new_value -gt 255 ]; then
|
||||
new_value=255
|
||||
fi
|
||||
flame[$pos]=$new_value
|
||||
done
|
||||
done
|
||||
flame_buffer="${flame_corner}${flame_next}${flame_next}${flame_next}"
|
||||
for x in $( seq 0 $(( ( $width + 1 ) * ( $height + 1 ) - 1 )) ); do
|
||||
if [ $(( $x % ( $width + 1 ) )) -eq $width ]; then flame_buffer+="\n${flame_next}${flame_next}${flame_next}"; fi
|
||||
if [ ${flame_mask[$x]} -eq 1 ]; then flame_buffer+="${flame_next}"; continue; fi
|
||||
print_value=$(( flame[$x] / 32 ))
|
||||
flame_buffer+="${flame_color_codes[${print_value}]}${flame_chars:${print_value}:1}"
|
||||
done
|
||||
printf "$flame_buffer"
|
||||
_qPos abs 1 1
|
||||
}
|
||||
|
||||
_stars() {
|
||||
if [ "$LIGHT" = 1 ]; then return; fi
|
||||
wall_chars=" ,.'\`"
|
||||
wall_colors="kkkKKKzzzr"
|
||||
wall_color_codes=()
|
||||
for x in $( seq 0 $(( ${#wall_colors} - 1 )) ); do
|
||||
wall_color_codes+=( $( _qCol ${wall_colors:$x:1} ) )
|
||||
done
|
||||
|
||||
lines=$(( 25 + $KEY_FILES ))
|
||||
_qPos abs 1 1
|
||||
seq_x=$( seq 1 50 )
|
||||
for y in $( seq 1 $lines ); do
|
||||
for x in $seq_x; do
|
||||
chr="${wall_chars:$(( $RANDOM % ${#wall_chars} )):1}"
|
||||
if [ "$chr" = " " ]; then _qPos right 1; continue; fi
|
||||
color="${wall_color_codes[$(( $RANDOM % ${#wall_colors} ))]}"
|
||||
printf "%s%s" \
|
||||
"$color" \
|
||||
"$chr"
|
||||
done
|
||||
printf "\n"
|
||||
done
|
||||
_qCol z
|
||||
}
|
||||
|
||||
_exit() {
|
||||
clear
|
||||
_skull
|
||||
_qPos down 4
|
||||
exit
|
||||
}
|
||||
_get_code() {
|
||||
oathtool -b --totp $( cat "$1" | tr -dc '[:print:]' )
|
||||
}
|
||||
_print_codes() {
|
||||
#~ printf 'L%.0s' $( seq -1 $update_frequency )
|
||||
if [ "$LIGHT" = 1 ]; then
|
||||
_qPos abs 3 1;
|
||||
else
|
||||
_qPos abs 20 1
|
||||
fi
|
||||
even=0
|
||||
for k in *key; do
|
||||
if [ $even -eq 0 ]; then
|
||||
_qCol z Y
|
||||
else
|
||||
_qCol z G
|
||||
fi
|
||||
name=${k%.key}
|
||||
name=${name//_/ }
|
||||
_qPos right 6
|
||||
printf "[ %s ]%s %s \n" \
|
||||
$( _get_code "$k" ) \
|
||||
$( _qCol s ) \
|
||||
"$name"
|
||||
even=$(( 1 - $even ))
|
||||
done
|
||||
_qCol z
|
||||
}
|
||||
|
||||
_show_clock() {
|
||||
for foo in {1..1}; do
|
||||
i=$(( ( $( date +%s ) - $timeadjust ) % $update_frequency ))
|
||||
l=$(( $update_frequency - $i ))
|
||||
if [ "$LIGHT" = 1 ]; then
|
||||
_qPos abs $(( $KEY_FILES + 5 )) 1
|
||||
else
|
||||
_qPos abs $(( $KEY_FILES + 22 )) 1
|
||||
fi
|
||||
_qCol CLREND z g;_qPos right 5; date
|
||||
# seconds to code update
|
||||
_qCol z g
|
||||
printf "\r"; _qPos right 4; printf "[";
|
||||
printf ' %.0s' $( seq 1 $update_frequency )
|
||||
printf ']\r'; _qPos right 5
|
||||
if [ $l -gt 8 ]; then _qCol z G;
|
||||
elif [ $l -gt 3 ]; then _qCol z Y;
|
||||
else _qCol z R;
|
||||
fi
|
||||
printf '=%.0s' $( seq 1 $l )
|
||||
_qCol z c
|
||||
# seconds to this client shutdown
|
||||
left=$(( $update_frequency * ( $exit_timeout - $SECONDS ) / $exit_timeout ))
|
||||
printf "\n\r"; _qPos right 4; printf "[";
|
||||
printf ' %.0s' $( seq 1 $update_frequency )
|
||||
printf ']\r'; _qPos right 5
|
||||
if [ $left -gt 8 ]; then _qCol z c;
|
||||
elif [ $left -gt 3 ]; then _qCol z y;
|
||||
else _qCol z r;
|
||||
fi
|
||||
printf '#%.0s' $( seq 1 $left )
|
||||
_qCol z; printf "\n"
|
||||
_qCol CLREND
|
||||
# die if key pressed, or client open for exit_timeout length
|
||||
wait_for_second=$SECONDS
|
||||
for i in {1..10}; do
|
||||
read -t 0.1 foo
|
||||
[[ "$?" -eq 0 ]] && _exit
|
||||
[[ $SECONDS -gt $exit_timeout ]] && _exit
|
||||
_flames
|
||||
if [ $SECONDS -gt $wait_for_second ]; then break; fi
|
||||
done
|
||||
done
|
||||
}
|
||||
if [ -f "$1" ]; then _get_code "$1"; _get_code "$1" | xclip; exit; fi
|
||||
for key in *key; do ((KEY_FILES++)); done
|
||||
clear
|
||||
_print_codes
|
||||
_skull
|
||||
_flames; _flames; _flames; _flames
|
||||
|
||||
while :;do
|
||||
set -e
|
||||
new_codes=$( _print_codes )
|
||||
set +e
|
||||
[[ ! "$new_codes" = "$codes" ]] && {
|
||||
# print codes only if they change, this keeps selection in shell intact
|
||||
_stars
|
||||
codes=$new_codes
|
||||
echo -e "$codes"
|
||||
echo ''
|
||||
}
|
||||
_show_clock
|
||||
done
|
||||
129
web/rclone-mount
Executable file
129
web/rclone-mount
Executable file
@@ -0,0 +1,129 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
_helpexit() {
|
||||
printf "Usage: %s [-u] remote:[path]
|
||||
|
||||
remote from rclone config. Note, all remotes end with :
|
||||
-u will unmount all FUSE.rclone paths if no path given!
|
||||
|
||||
" "$( basename $0 )"
|
||||
echo Current mounts:
|
||||
cat /proc/mounts | grep fuse.rclone | awk '{ print $1 "\t" $2 }'
|
||||
exit 1
|
||||
}
|
||||
|
||||
_menu() {
|
||||
echo Current mounts:
|
||||
cat /proc/mounts | grep fuse.rclone | awk '{ print $1 "\t" $2 }'
|
||||
_askpass
|
||||
choice=$( rclone --ask-password=false listremotes | \
|
||||
sort | \
|
||||
smenu -t 1 -a c:0/2 i:3 -n 25 -m "Select remote" \
|
||||
-N -D n:1 i:1 )
|
||||
|
||||
echo $choice
|
||||
if [[ -z "$choice" ]]; then
|
||||
_helpexit
|
||||
fi
|
||||
remote="$choice"
|
||||
}
|
||||
|
||||
_askpass() {
|
||||
if [[ -n "$RCLONE_CONFIG_PASS" ]]; then
|
||||
# password already set
|
||||
return
|
||||
fi
|
||||
if grep -q ^"# Encrypted rclone configuration File" "$HOME/.config/rclone/rclone.conf"; then
|
||||
read -s -p "rclone config password: " RCLONE_CONFIG_PASS
|
||||
export RCLONE_CONFIG_PASS
|
||||
else
|
||||
RCLONE_CONFIG_PASS="not-required"
|
||||
true
|
||||
fi
|
||||
}
|
||||
|
||||
_check_mount() {
|
||||
if [[ -d "$valid_name" ]]; then
|
||||
device1=$( stat -c "%d" ~/mnt/"$valid_name" )
|
||||
device2=$( stat -c "%d" ~/mnt )
|
||||
else
|
||||
device1=valid
|
||||
device2=valid
|
||||
fi
|
||||
}
|
||||
|
||||
[[ -z "$1" ]] && _menu
|
||||
for (( i=1; i<=$#; i++ )); do
|
||||
[[ ${!i} = "-h" ]] && _helpexit
|
||||
[[ ${!i} = "--help" ]] && _helpexit
|
||||
done
|
||||
unmount=false
|
||||
for (( i=1; i<=$#; i++ )); do
|
||||
[[ ${!i} = "-u" ]] && { unmount=true; continue; }
|
||||
if [[ -z "$remote" ]]; then
|
||||
remote="${!i}"
|
||||
fi
|
||||
done
|
||||
|
||||
mkdir -p ~/mnt
|
||||
|
||||
valid_name=$( echo "${remote%:}" | sed -e 's/:/-/g' | sed -e 's/[^A-Za-z0-9._@-]//g' )
|
||||
|
||||
if [[ "$unmount" = true ]]; then
|
||||
cd ~/mnt
|
||||
if [[ -n "$remote" ]]; then
|
||||
fusermount -u -z ~/mnt/$valid_name
|
||||
rmdir --ignore-fail-on-non-empty ~/mnt/$valid_name &>/dev/null
|
||||
else
|
||||
# no path, unmount all
|
||||
cat /proc/mounts | grep fuse.rclone | awk '{ print $2 }' | while read dir; do
|
||||
echo Unmounting $dir
|
||||
fusermount -u -z "$dir"
|
||||
rmdir --ignore-fail-on-non-empty "$dir" &>/dev/null
|
||||
done
|
||||
fi
|
||||
exit
|
||||
fi
|
||||
|
||||
if [[ -z "$remote" ]]; then
|
||||
echo "No remote given"
|
||||
_helpexit
|
||||
fi
|
||||
|
||||
_check_mount
|
||||
tries=20
|
||||
|
||||
if [[ $device1 = $device2 ]]; then
|
||||
echo "Mounting $remote in ~/mnt/$valid_name"
|
||||
_askpass
|
||||
cd ~/mnt
|
||||
mkdir -p "$valid_name"
|
||||
|
||||
echo ""
|
||||
rclone --ask-password=false mount --daemon "${remote}" ~/mnt/"$valid_name"
|
||||
if [[ $? -gt 0 ]]; then
|
||||
tries=1
|
||||
fi
|
||||
echo "Waiting for mount to finish ..."
|
||||
else
|
||||
echo "~/mnt/$valid_name is already mounted"
|
||||
exit
|
||||
fi
|
||||
|
||||
while [[ $tries -gt 0 ]]; do
|
||||
read -t 1 -n 1 key
|
||||
_check_mount
|
||||
if [[ $device1 = $device2 ]]; then
|
||||
tries=$(( $tries - 1 ))
|
||||
else
|
||||
df -h "$valid_name"
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
echo $remote was not mounted
|
||||
fusermount -u -z ~/mnt/$valid_name &>/dev/null
|
||||
rmdir --ignore-fail-on-non-empty ~/mnt/$valid_name &>/dev/null
|
||||
exit 1
|
||||
|
||||
9
web/ssh-nosave
Executable file
9
web/ssh-nosave
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ "$1" = "-h" ]]; then
|
||||
echo "Set options to not use host key checking, and pass all commands to 'ssh'."
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
exec ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$@"
|
||||
71
web/ssh-scan-lan
Executable file
71
web/ssh-scan-lan
Executable file
@@ -0,0 +1,71 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ "$1" = "-h" ]]; then
|
||||
echo This scans your LAN for SSH servers.
|
||||
echo 'Requires: nmap; ifconfig or nmcli'
|
||||
exit
|
||||
fi
|
||||
|
||||
PATH=$PATH:/sbin/:/usr/sbin
|
||||
|
||||
which nmap &>/dev/null || {
|
||||
echo nmap required
|
||||
exit 1
|
||||
}
|
||||
|
||||
which ifconfig &>/dev/null && {
|
||||
IPLIST="ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*'"
|
||||
ifmask() {
|
||||
ifconfig | grep $1 | \
|
||||
grep -Eo 'netmask (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*'
|
||||
}
|
||||
}
|
||||
which nmcli &>/dev/null && {
|
||||
IPLIST="nmcli | grep -Eo 'inet4 ([0-9]*\.){3}[0-9]*'"
|
||||
ifmask() {
|
||||
cidr=$( nmcli | grep 'inet4 ' | grep $1 | \
|
||||
grep -Eo '([0-9]*$)' )
|
||||
value=$(( 0xffffffff ^ ((1 << (32 - $cidr)) - 1) ))
|
||||
echo "$(( (value >> 24) & 0xff )).$(( (value >> 16) & 0xff )).$(( (value >> 8) & 0xff )).$(( value & 0xff ))"
|
||||
}
|
||||
}
|
||||
servers_found=""
|
||||
|
||||
while read myip; do
|
||||
ip_base=$( echo $myip | cut -d. -f 1-3 )
|
||||
|
||||
mymask=$( ifmask $myip )
|
||||
|
||||
IFS=. read -r i1 i2 i3 i4 <<< "$myip"
|
||||
IFS=. read -r m1 m2 m3 m4 <<< "$mymask"
|
||||
|
||||
f1=$((i1 & m1))
|
||||
f2=$((i2 & m2))
|
||||
f3=$((i3 & m3))
|
||||
f4=$(((i4 & m4)+1))
|
||||
l1=$((i1 & m1 | 255-m1))
|
||||
l2=$((i2 & m2 | 255-m2))
|
||||
l3=$((i3 & m3 | 255-m3))
|
||||
l4=$(((i4 & m4 | 255-m4)-1))
|
||||
|
||||
first_ip="$f1.$f2.$f3.$f4"
|
||||
last_ip="$l1.$l2.$l3.$l4"
|
||||
|
||||
printf "IP: %15s/%-15s scan: %15s - %-15s\n" \
|
||||
"$myip" "$mymask" "$first_ip" "$last_ip"
|
||||
|
||||
while read line; do
|
||||
if [[ "$line" = "#"* ]]; then continue; fi
|
||||
ip=$( echo $line | grep -Eo '([0-9]*\.){3}[0-9]*' )
|
||||
if [[ $ip = $myip ]]; then continue; fi
|
||||
ssh_server=$( ssh-keyscan -p 22 -t rsa -T 1 "$ip" 2>&1 | grep ^# | sed 's/:\([0-9]\+\)/ -p \1/' )
|
||||
printf -v servers_found "%s%s\n" "$servers_found" "$ssh_server"
|
||||
done < <( nmap -T5 -sP "$f1-$l1.$f2-$l2.$f3-$l3.$f4-$l4" -oG - )
|
||||
|
||||
done < <( eval $IPLIST | \
|
||||
grep -Eo '([0-9]*\.){3}[0-9]*' | \
|
||||
grep -v 127.0.0.1 | \
|
||||
grep -v ^172. )
|
||||
|
||||
echo "SSH Servers found:"
|
||||
printf "%s" "$servers_found" | sort -n | grep -v "^$"
|
||||
107
web/sshfs-mount
Executable file
107
web/sshfs-mount
Executable file
@@ -0,0 +1,107 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
_helpexit() {
|
||||
printf "Usage: %s [-u] [-nosave] host [path]
|
||||
|
||||
host can be from ssh config
|
||||
path is the remote path. Defaults to remote home.
|
||||
-u will unmount all FUSE.sshfs paths if no path given!
|
||||
-nosave will not use host key checking, nor save it anywhere. potentially dangerous.
|
||||
|
||||
" "$( basename $0 )"
|
||||
echo Current mounts:
|
||||
cat /proc/mounts | grep fuse.sshfs | awk '{ print $1 "\t" $2 }'
|
||||
exit 1
|
||||
}
|
||||
|
||||
_menu() {
|
||||
echo Current mounts:
|
||||
cat /proc/mounts | grep fuse.sshfs | awk '{ print $1 "\t" $2 }'
|
||||
choice=$( grep -Pi "^host ([^*]+)$" $HOME/.ssh/config | \
|
||||
sed 's/host //i' | tr ' ' '\n' | sort | \
|
||||
smenu -t 1 -a c:0/2 i:3 -n 25 -m "Select server" \
|
||||
-N -D n:1 i:1 )
|
||||
|
||||
echo $choice
|
||||
if [[ -z "$choice" ]]; then
|
||||
_helpexit
|
||||
fi
|
||||
host="$choice"
|
||||
}
|
||||
|
||||
|
||||
[[ -z "$1" ]] && _menu
|
||||
for (( i=1; i<=$#; i++ )); do
|
||||
[[ ${!i} = "-h" ]] && _helpexit
|
||||
[[ ${!i} = "--help" ]] && _helpexit
|
||||
done
|
||||
unmount=false
|
||||
nosave=false
|
||||
for (( i=1; i<=$#; i++ )); do
|
||||
[[ ${!i} = "-u" ]] && { unmount=true; continue; }
|
||||
[[ ${!i} = "-nosave" ]] && { nosave=true; continue; }
|
||||
if [[ -z "$host" ]]; then
|
||||
host="${!i}"
|
||||
else
|
||||
localpath="${!i}"
|
||||
fi
|
||||
done
|
||||
|
||||
mkdir -p ~/mnt
|
||||
|
||||
valid_name=$( echo "$host" | sed -e 's/[^A-Za-z0-9._@-]//g')
|
||||
path=:"${localpath}"
|
||||
|
||||
if [[ "$nosave" = true ]]; then
|
||||
NOSAVE="-o ssh_command='ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'"
|
||||
fi
|
||||
|
||||
if [[ "$unmount" = true ]]; then
|
||||
cd ~/mnt
|
||||
if [[ -n "$host" ]]; then
|
||||
fusermount -u -z ~/mnt/$valid_name
|
||||
rmdir --ignore-fail-on-non-empty ~/mnt/$valid_name &>/dev/null
|
||||
else
|
||||
# no path, unmount all
|
||||
cat /proc/mounts | grep fuse.sshfs | awk '{ print $2 }' | while read dir; do
|
||||
echo Unmounting $dir
|
||||
fusermount -u -z "$dir"
|
||||
rmdir --ignore-fail-on-non-empty "$dir" &>/dev/null
|
||||
done
|
||||
fi
|
||||
exit
|
||||
fi
|
||||
|
||||
if [[ -z "$host" ]]; then
|
||||
echo "No host given"
|
||||
_helpexit
|
||||
fi
|
||||
|
||||
if [[ -d "$valid_name" ]]; then
|
||||
device1=$( stat -c "%d" "$valid_name" )
|
||||
device2=$( stat -c "%d" . )
|
||||
else
|
||||
device1=valid
|
||||
device2=valid
|
||||
fi
|
||||
|
||||
if [[ $device1 = $device2 ]]; then
|
||||
echo "Mounting $valid_name$path in ~/mnt/$valid_name"
|
||||
cd ~/mnt
|
||||
mkdir -p "$valid_name"
|
||||
|
||||
eval sshfs \
|
||||
-o reconnect \
|
||||
-o ServerAliveInterval=45,ServerAliveCountMax=2 \
|
||||
$NOSAVE \
|
||||
-o follow_symlinks "$valid_name$path" "$valid_name"
|
||||
if [[ $? -gt 0 ]]; then
|
||||
rmdir "$valid_name"
|
||||
else
|
||||
df -h "$valid_name"
|
||||
fi
|
||||
else
|
||||
echo "~/mnt/$valid_name is already mounted"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user