边转换边播放功能

This commit is contained in:
nnwang
2026-02-07 13:32:36 +08:00
parent cf0842a34b
commit 00e13e765e
2 changed files with 66 additions and 85 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.history

147
play.lua
View File

@@ -1,5 +1,5 @@
-- 简化版视频播放器
local gpu = peripheral.wrap("tm_gpu_2")
local gpu = peripheral.wrap("tm_gpu_0")
gpu.refreshSize()
gpu.setSize(64)
local w, h = gpu.getSize()
@@ -65,7 +65,7 @@ print("task_id: " .. task_id)
-- 用于记录已打印的日志数量,避免重复打印
local total_logs_printed = 0
speakerrun = true
while true do
@@ -97,10 +97,17 @@ while true do
total_logs_printed = total_logs_printed + #task_info.new_logs
end
if task_info.result.audio_urls and speakerrun then
speakerrun = false
shell.run("bg speakerlib play ".. server_url .. task_info.result.audio_urls.audio_dfpwm_url .." ".. server_url .. task_info.result.audio_urls.audio_dfpwm_left_url .." ".. server_url .. task_info.result.audio_urls.audio_dfpwm_right_url)
end
-- 检查是否完成
if task_info.status == "completed" then
if task_info.result.current_frames then
if task_info.result.current_frames >= 200 then
break
end
end
sleep(1)
end
@@ -111,18 +118,23 @@ local response = http.get(status_url, {["Content-Type"] = "application/json"})
local finalResp = textutils.unserialiseJSON(response.readAll())
response.close()
videoInfo = finalResp.result.result
videoInfo = finalResp.result
videoInfo.fps = 20
-- 此时 videoInfo 包含 frame_urls, audio_dfpwm_url 等字段
print("\nTask completed! Total frames: " .. #videoInfo.frame_urls)
videoInfo.frame_urls = {}
-- /frames/20116713/frame_000001.png
for i = 1, videoInfo.total_frames - 10 do
videoInfo.frame_urls[i] = "/frames/"..task_id.."/frame_" .. string.format("%06d", i) .. ".png"
end
-- 播放音频 单通道
--shell.run("bg speaker play", server_url .. videoInfo.audio_dfpwm_url)
-- server_url .. videoInfo.audio_dfpwm_url -- 音频单通道文件 URL
-- server_url .. videoInfo.audio_dfpwm_right_url -- 音频右通道文件 URL
-- server_url .. videoInfo.audio_dfpwm_left_url -- 音频左通道文件 URL
shell.run("bg speakerlib play ".. server_url .. videoInfo.audio_dfpwm_url .." ".. server_url .. videoInfo.audio_dfpwm_left_url .." ".. server_url .. videoInfo.audio_dfpwm_right_url)
-- server_url .. videoInfo.audio_urls.audio_dfpwm_url -- 音频单通道文件 URL
-- server_url .. videoInfo.audio_urls.audio_dfpwm_right_url -- 音频右通道文件 URL
-- server_url .. videoInfo.audio_urls.audio_dfpwm_left_url -- 音频左通道文件 URL
-- 下载和播放函数
frames = {}
local frameCount = 0
@@ -163,92 +175,73 @@ local function unpackFramePack(data)
return frames
end
-- 分批下载(每批 50 帧)
local BATCH_SIZE = 20
-- local totalFrames = #videoInfo.frame_urls
local totalFrames = videoInfo.fps * 10 -- 仅下载前10秒以节省时间
local allFrameData = {}
-- 第一步构建所有需要下载的批次仅前10秒
local initBatches = {}
for startIdx = 1, totalFrames, BATCH_SIZE do
local endIdx = math.min(startIdx + BATCH_SIZE - 1, totalFrames)
print("Downloading batch: " .. startIdx .. " - " .. endIdx)
-- 构造要下载的 URL 列表(相对路径)
local urls = {}
for i = startIdx, endIdx do
table.insert(urls, videoInfo.frame_urls[i])
end
-- 请求打包
while true do
resp1,err = http.post(
server_url .. "/api/framepack",
textutils.serializeJSON({ urls = urls }),
{ ["Content-Type"] = "application/json" },
true
)
if resp1 then break end
end
if not resp1 then error("Failed to download framepack "..err) end
local binData = resp1.readAll()
print(#binData .. " bytes received")
resp1.close()
-- 解包
local batchFrames = unpackFramePack(binData)
for i = 1, #batchFrames do
allFrameData[startIdx + i - 1] = batchFrames[i]
end
print("Loaded batch: " .. #batchFrames .. " frames")
sleep(0.1)
table.insert(initBatches, {
start = startIdx,
urls = urls
})
end
print("Pre-caching first " .. totalFrames .. " frames (" .. #initBatches .. " batches)...")
-- 第二步:并发下载所有初始化批次
local initTasks = {}
for _, batch in ipairs(initBatches) do
table.insert(initTasks, function()
while true do
local resp = http.post({
url = server_url .. "/api/framepack?" .. batch.urls[1],
headers = { ["Content-Type"] = "application/json" },
body = textutils.serializeJSON({ urls = batch.urls }),
timeout = 3,
binary = true
})
if resp then
local binData = resp.readAll()
resp.close()
-- -- 预加载前N帧
-- for i = 1, math.min(videoInfo.fps, #videoInfo.frame_urls) do
local batchFrames = unpackFramePack(binData)
for idx = 1, #batchFrames do
local globalIdx = batch.start + idx - 1
allFrameData[globalIdx] = batchFrames[idx]
end
-- if frameData[i] then
-- local data = frameData[i]
-- local imgBin = {}
-- for j = 1, #data do
-- imgBin[#imgBin + 1] = data:byte(j)
-- end
print("Cached init batch: " .. batch.start .. " - " .. (batch.start + #batchFrames - 1))
break
else
print("Retry init batch starting at " .. batch.start)
sleep(0.5)
end
end
end)
end
-- 执行并发下载
parallel.waitForAll(table.unpack(initTasks))
-- local success, image = pcall(function()
-- return gpu.decodeImage(table.unpack(imgBin))
-- end)
-- if success then
-- print("Loaded frame "..i .."/"..#videoInfo.frame_urls)
-- frames[i] = image
-- frameData[i] = nil
-- data = nil
-- frameCount = frameCount + 1
-- else
-- print(image)
-- end
-- end
-- end
print("Initial caching completed.")
-- 播放循环
local frameDelay = tonumber(string.format("%.3f",1 / videoInfo.fps))
print("Starting playback (FPS: " .. videoInfo.fps .. ")")
print(frameDelay * #videoInfo.frame_urls)
local starttime1 = os.clock()
sleep(1)
sleep(4)
@@ -311,11 +304,6 @@ local function cacheAhead()
table.insert(downloadTasks, function()
print("Downloading batch: " .. batch.start .. " - " .. (batch.start + #batch.urls - 1))
while true do
-- local resp = http.post(
-- server_url .. "/api/framepack?"..batch.urls[1],
-- textutils.serializeJSON({ urls = batch.urls }),
-- { ["Content-Type"] = "application/json" }
-- )
local resp = http.post({
url = server_url .. "/api/framepack?"..batch.urls[1],
headers = { ["Content-Type"] = "application/json" },
@@ -361,15 +349,6 @@ local function cacheAhead()
end
end
-- -- 音频播放协程
-- local function playAudio()
-- os.queueEvent("audio_start") -- 触发同步
-- shell.run("bg speakerlib play " ..
-- server_url .. videoInfo.audio_dfpwm_url .. " " ..
-- server_url .. videoInfo.audio_dfpwm_left_url .. " " ..
-- server_url .. videoInfo.audio_dfpwm_right_url)
-- end
-- 视频渲染协程
local function renderVideo()
local frameIndex2 = 0