1
0
Fork 0

Compare commits

..

6 Commits

3 changed files with 41 additions and 26 deletions

View File

@ -74,13 +74,14 @@ class Converter:
MAX_DIFF = 3 * 255
def __init__(self, image: Image.Image, palette: list[int] | int = PALETTE_ADAPTIVE):
def __init__(self, image: Image.Image, palette: list[int] | int = PALETTE_ADAPTIVE, dither: bool = True):
dither_mode = Image.Dither.FLOYDSTEINBERG if dither else Image.Dither.NONE
if isinstance(palette, list):
img_pal = Image.new("P", (1, 1))
img_pal.putpalette(palette)
self._img = image.quantize(len(palette) // 3, palette=img_pal)
self._img = image.quantize(len(palette) // 3, palette=img_pal, dither=dither_mode)
else:
self._img = image.convert("P", palette=palette, colors=16)
self._img = image.convert("P", palette=palette, colors=16, dither=dither_mode)
self._imgdata = self._img.load()
self._palette: list[int] = self._img.getpalette() or []
@ -221,6 +222,12 @@ def main():
action="store_true",
help="Output a Lua script instead of binary image",
)
parser.add_argument(
"-D",
dest="nodither",
action="store_true",
help="Disable dithering"
)
parser.add_argument(
"-W",
dest="width",
@ -391,7 +398,7 @@ def main():
else:
raise ValueError(f"invalid palette identifier: {args.palette!r}")
converter = Converter(canv, palette)
converter = Converter(canv, palette, dither=not args.nodither)
converter._img.save("/tmp/_ccpictmp.png")
if args.textmode:
with open(args.output_path, "w") as fp:

View File

@ -10,8 +10,8 @@ cleanup() {
trap cleanup EXIT
export URL="$1";
export NAME="$2";
export INPUT="$1";
export OUTPUT="$(realpath "$2")";
export BASE_URL="$3"
if [ -z "${BASE_URL}" ]; then
@ -19,24 +19,21 @@ if [ -z "${BASE_URL}" ]; then
fi
mkdir -p "${NAME}"
mkdir -p "${OUTPUT}"
export ORIG="$(pwd)";
cd "${TMP_DIR}"
yt-dlp "${URL}" -S "+height:720" -f "b" -o "${NAME}"
ffmpeg -i "${INPUT}" -filter_complex "[0:a]channelsplit=channel_layout=stereo[left][right]" -map '[left]' -f s8 -ac 1 -ar 48k "${OUTPUT}/left.s8" -map '[right]' -f s8 -ac 1 -ar 48k "${OUTPUT}/right.s8"
ffmpeg -i "${INPUT}" -vf fps=20 frame%04d.png
ffmpeg -i $2* -filter_complex "[0:a]channelsplit=channel_layout=stereo[left][right]" -map '[left]' -f s8 -ac 1 -ar 48k "${ORIG}/${NAME}/left.s8" -map '[right]' -f s8 -ac 1 -ar 48k "${ORIG}/${NAME}/right.s8"
ffmpeg -i $2* -vf fps=20 frame%04d.png
rm $2*
ls frame*.png | parallel 'echo {}; python3 ${ORIG}/cc-pic.py -W 164 -H 81 -p full {} ${ORIG}/${NAME}/{.}.cpi'
ls frame*.png | parallel 'echo {}; python3 ${ORIG}/cc-pic.py -W 164 -H 81 -p cover {} ${OUTPUT}/{.}.cpi'
rm frame*.png
cd "${ORIG}"
export FRAME_COUNT="$(ls ${NAME}/*.cpi | wc -l)";
export FRAME_COUNT="$(ls ${OUTPUT}/*.cpi | wc -l)";
printf '{"frame_time": 0.05, "frame_count": %d, "video": "%s", "audio": {"l": "%s", "r": "%s"}}\n' "${FRAME_COUNT}" "${BASE_URL}/frame%04d.cpi" "${BASE_URL}/left.s8" "${BASE_URL}/right.s8" > "${OUTPUT}/info.json"
#'{"frame_time": 0.05,"frame_count": ${FRAME_COUNT},"video": "${BASE_URL}/${NAME}/frame%04d.cpi","audio": {"l": "${BASE_URL}/${NAME}/left.s8", "r": "${BASE_URL}/${NAME}/right.s8"}}' > "${NAME}/${NAME}.json"
printf '{"frame_time": 0.05, "frame_count": %d, "video": "%s", "audio": {"l": "%s", "r": "%s"}}\n' "${FRAME_COUNT}" "${BASE_URL}/${NAME}/frame%04d.cpi" "${BASE_URL}/${NAME}/left.s8" "${BASE_URL}/${NAME}/right.s8" > "${NAME}/${NAME}.json"

View File

@ -2,6 +2,8 @@ local args = { ... }
local dfpwm = require("cc.audio.dfpwm")
local ccpi = require("ccpi")
local EV_NONCE = math.floor(0xFFFFFFFF * math.random())
settings.define("video.speaker.left", {
description = "Speaker ID for left audio channel",
default = peripheral.getName(peripheral.find("speaker")),
@ -86,7 +88,8 @@ if not n_frames and not video_url and not audio_url_l then
end
end
print(string.format("Using monitor %s", peripheral.getName(monitor)))
local mon_w, mon_h = monitor.getSize()
print(string.format("Using monitor %s (%dx%d)", peripheral.getName(monitor), mon_w, mon_h))
if speakers.r then
print(string.format("Stereo sound: L=%s R=%s", peripheral.getName(speakers.l), peripheral.getName(speakers.r)))
else
@ -183,11 +186,11 @@ for i = 1, loading_concurrency do
end
table.insert(subthreads, function()
while #frames ~= n_frames or #audio_frames.l < n_audio_samples do
repeat
draw_bar(ty - 3, colors.blue, colors.gray, #frames / n_frames, "Loading video [%5d / %5d]", #frames, n_frames)
draw_bar(ty - 2, colors.red, colors.gray, #audio_frames.l / n_audio_samples, "Loading audio [%5d / %5d]", #audio_frames.l, n_audio_samples)
os.sleep(0.25)
end
until #frames >= n_frames and #audio_frames.l >= n_audio_samples
print()
end)
@ -208,14 +211,16 @@ table.insert(subthreads, function()
break
end
end
os.queueEvent("playback_ready")
os.queueEvent("playback_ready", EV_NONCE)
end)
table.insert(subthreads, function()
local is_dfpwm = ({ audio_url_l:find("%.dfpwm") })[2] == #audio_url_l
local decode = use_dfpwm and dfpwm.make_decoder() or decode_s8
os.pullEvent("playback_ready")
repeat
local _, nonce = os.pullEvent("playback_ready")
until nonce == EV_NONCE
for i = 1, n_audio_samples do
local buffer = decode(audio_frames.l[i])
@ -232,7 +237,9 @@ table.insert(subthreads, function()
local is_dfpwm = ({ audio_url_r:find("%.dfpwm") })[2] == #audio_url_r
local decode = use_dfpwm and dfpwm.make_decoder() or decode_s8
os.pullEvent("playback_ready")
repeat
local _, nonce = os.pullEvent("playback_ready")
until nonce == EV_NONCE
for i = 1, n_audio_samples do
local buffer = decode(audio_frames.r[i])
@ -244,8 +251,9 @@ table.insert(subthreads, function()
end)
table.insert(subthreads, function()
os.pullEvent("playback_ready")
repeat
local _, nonce = os.pullEvent("playback_ready")
until nonce == EV_NONCE
local start_t = os.clock()
while not playback_done do
local frame = math.floor((os.clock() - start_t) / math.max(0.05, delay))
@ -253,8 +261,11 @@ table.insert(subthreads, function()
term.setBackgroundColor(frame >= #frames and colors.red or colors.gray)
term.clearLine()
term.write(string.format("Playing frame: %d/%d", frame + 1, #frames))
if frames[frame + 1] then
ccpi.draw(frames[frame + 1], 1, 1, monitor)
local img = frames[frame + 1]
if img ~= nil then
local x = math.max(math.floor((mon_w - img.w) / 2), 1)
local y = math.max(math.floor((mon_h - img.h) / 2), 1)
ccpi.draw(img, x, y, monitor)
end
os.sleep(delay)
end