-
-
Save vizv/93944436425b7b7eef7f1eeaea4fc6c6 to your computer and use it in GitHub Desktop.
QR code video encoder / decoder
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
#!/bin/sh -e | |
# preflight & usage | |
CMD="$1" | |
FILE="$2" | |
[ -z "$CMD" ] || [ -z "$FILE" ] && { | |
cat >&2 <<EOF | |
usage: $(basename "$0") encode FILE | |
$(basename "$0") decode FILE | |
EOF | |
exit 1 | |
} | |
# command check | |
case "$CMD" in | |
encode) | |
FILE_OUT="$FILE.webm" | |
;; | |
decode) | |
FILE_OUT="$(dirname "$FILE")/recreated-$(basename "${FILE%.*}")" | |
;; | |
*) | |
echo "[-] Command \"$CMD\" is invalid" >&2 | |
exit 1 | |
;; | |
esac | |
FILE_OUT_BASE="$(basename "$FILE_OUT")" | |
# set default configuration | |
[ -z "$CHUNK_PREFIX" ] && CHUNK_PREFIX='chunk' | |
[ -z "$CHUNK_SIZE" ] && CHUNK_SIZE=512 | |
[ -z "$DOT_PIXEL" ] && DOT_PIXEL=8 | |
# calculate chunk length | |
FILE_SIZE="$(stat --printf='%s' "$FILE")" | |
CHUNKS=$(((FILE_SIZE - 1) / CHUNK_SIZE + 1)) | |
CHUNK_SUFFIX_LEN="${#CHUNKS}" | |
# create temporary for processing | |
TMP_DIR="$(mktemp -u)" | |
mkdir -p "$TMP_DIR" | |
# setup trap | |
cleanup() { echo "[+] cleaning up..." >&2; rm -rf "$TMP_DIR"; } | |
trap cleanup HUP INT QUIT ABRT | |
# encode | |
[ "$CMD" = 'encode' ] && { | |
echo "[+] Splitting file..." | |
split --suffix-length="$CHUNK_SUFFIX_LEN" \ | |
--numeric-suffixes=1 \ | |
--bytes="$CHUNK_SIZE" \ | |
"$FILE" \ | |
"${TMP_DIR}/${CHUNK_PREFIX}-" | |
echo "[+] Generating QR codes..." | |
for CHUNK in "${TMP_DIR}/${CHUNK_PREFIX}"-*; do | |
echo " [+] Generating QR code for ${CHUNK}" | |
qrencode --8bit \ | |
--size="$DOT_PIXEL" \ | |
--read-from="$CHUNK" \ | |
--output="${CHUNK}.png" | |
done | |
echo "[+] Creating video..." | |
ffmpeg -loglevel 16 \ | |
-i "${TMP_DIR}/${CHUNK_PREFIX}-%0${CHUNK_SUFFIX_LEN}d.png" \ | |
"${TMP_DIR}/${FILE_OUT_BASE}" | |
# set output file as FILE chunks for decode test | |
ORIGINAL_FILE="$FILE" | |
FILE="${TMP_DIR}/${FILE_OUT_BASE}" | |
FILE_OUT_BASE="$(basename "$ORIGINAL_FILE")" | |
# clean up | |
rm -f "${TMP_DIR}/${CHUNK_PREFIX}"-* | |
} | |
# decode / decode test | |
[ "$CMD" = 'decode' ] || [ "$CMD" = 'encode' ] && { | |
echo "[+] Extract QR codes from the video..." | |
ffmpeg -loglevel 16 \ | |
-i "$FILE" \ | |
"${TMP_DIR}/${CHUNK_PREFIX}-%0${CHUNK_SUFFIX_LEN}d.png" | |
echo "[+] Scanning QR codes..." | |
for QRCODE in "${TMP_DIR}/${CHUNK_PREFIX}"-*.png; do | |
echo " [+] Scanning QR code for ${QRCODE}" | |
zbarimg --quiet \ | |
--raw "$QRCODE" \ | |
| iconv --from=UTF-8 \ | |
--to=ISO-8859-1 \ | |
| head --bytes="$((CHUNK_SIZE + 1))" \ | |
| head --bytes=-1 >"${QRCODE}.bin" | |
done | |
echo "[+] Rebuilding file..." | |
cat "${TMP_DIR}/${CHUNK_PREFIX}"-*.png.bin > "${TMP_DIR}/${FILE_OUT_BASE}" | |
# clean up | |
rm -f "${TMP_DIR}/${CHUNK_PREFIX}"-* | |
# for decode, move recreated file back directly | |
[ "$CMD" = 'decode' ] && mv "${TMP_DIR}/${FILE_OUT_BASE}" "${FILE_OUT}" | |
} | |
# compare and save video | |
[ "$CMD" = 'encode' ] && { | |
echo "[+] Comparing outputs..." | |
RECREATED_FILE="${TMP_DIR}/${FILE_OUT_BASE}" | |
cmp "$RECREATED_FILE" "$ORIGINAL_FILE" || { | |
echo "[-] Error: created file and original file are different!" | |
exit 1 | |
} | |
echo "[+] Saving video..." | |
mv "$FILE" "$FILE_OUT" | |
} | |
cleanup | |
echo "[+] Done." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment