13 mjpg视频播放
作者:拓毅恒 | 最后修改:2026-06-04
一、视频播放功能概述
Air8000 工业引擎提供了视频播放功能,基于 AirUI 框架实现 MJPG 格式视频的流畅播放。视频播放系统支持以下主要功能:
- 本地视频播放:支持播放烧录到固件中的 MJPG 格式视频文件
- 网络视频播放:支持从 HTTP 服务器下载并播放视频
- AirUI 视频组件:基于 airui.video 组件实现视频渲染
- LCD 显示支持:适配 320x480 分辨率 LCD 屏幕
视频播放功能是嵌入式系统中多媒体应用的重要组成部分,掌握视频播放系统的使用方法对于实现视频展示、动态界面等应用至关重要。
二、准备硬件环境
参考:Air8000 硬件环境清单,准备好硬件环境。
2.1 Air8000 整机开发板 + LCD 屏幕
Air8000 开发板提供了丰富的显示接口资源,可通过开发板上的 LCD 接口连接显示屏进行视频播放测试。

2.2 Air8000 核心板 + AirLCD_1010 LCD 配件板

Air8000 核心板和 AirLCD_1010 配件板的硬件接线方式为:
| Air8000核心板 | AirLCD_1010配件板 |
| LCD_CLK | SCLK/CLK |
| LCD_CS | CS |
| LCD_RST | RES/RST |
| LCD_SDA | SDA/MOS |
| LCD_RS | DC/RS |
| GPIO1 | BLK |
| VBAT | VCC |
| I2C1_SCL | SCL |
| I2C1_SDA | SDA |
| WAKEUP0 | INT |
| GND | GND |
Air8000购买链接:Air8000_4G/WiFi/以太网-上海合宙LuatOS官方企业店-淘宝网
三、准备软件环境
3.1 工具 + 内核固件 + 脚本
1、Luatools 下载调试工具
2、本 demo 开发测试时使用的固件为 Air8000 V2034 版本固件(请选择支持 AirUI 功能的固件),所以你如果要测试本 demo 时,可以直接使用最新版本支持 AirUI 功能的内核固件;如果发现最新版本的内核固件测试有问题,可以使用我们开发本 demo 时使用的内核固件版本来对比测试;
3、luatos 需要的脚本和资源文件
- 脚本和资源文件点我浏览所有文件
- 准备好软件环境之后,接下来查看如何使用 LuaTools 烧录软件,将本篇文章中演示使用的项目文件烧录到 Air8000 核心板中,或者查看 Air8000 产品手册--Air8000 系列整机开发板使用手册 V2.0--使用说明,将本篇文章中演示使用的项目文件烧录到 Air8000 开发板中。
4、合宙 LuatIO 工具(GPIO 复用初始化配置)使用说明。
5、lib 脚本文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件;
3.2 API 介绍
这里仅介绍本篇文档所使用的 API,详情请查看:API - airui、API - lcd
airui.init(width, height)
初始化 AirUI 框架,设置显示区域尺寸
airui.container(config)
创建 AirUI 容器组件,用于布局和背景设置
airui.video(config)
创建视频播放组件,支持 MJPG 格式视频播放
lcd.init(driver, config)
初始化 LCD 显示屏驱动
lcd.getSize()
获取 LCD 屏幕的宽度和高度
四、视频播放功能实现概述
本小节详细介绍 Air8000 开发板上视频播放功能的实现方法和核心代码逻辑。
视频文件格式要求:
- 格式:MJPG (Motion JPEG)
- 分辨率:不超过 320x480(Air8000 LCD 分辨率)
- 帧率:默认 15fps,可通过
VIDEO_FPS变量调整
4.1 本地视频播放功能
本地视频播放功能用于播放烧录到固件中的 MJPG 格式视频文件。
- 自动播放 fly_man_80.mjpg 视频
- 支持 MJPG 格式视频文件播放
- 使用 AirUI 框架渲染视频
- 视频居中显示,自动适应屏幕尺寸
4.1.1 功能定义
配置 LCD 和 AirUI 参数,加载并播放指定路径的视频文件,视频将在屏幕中央显示。
4.1.2 代码示例
--[[
本地视频播放功能模块
核心业务逻辑:
1. 初始化 LCD 和 AirUI 框架
2. 从 /luadb/fly_man_80.mjpg 加载视频
3. 使用 airui.video 组件播放视频
4. 视频居中显示,支持循环播放
]]
local VIDEO_PATH = "/luadb/fly_man_80.mjpg" -- 视频文件路径
local VIDEO_FPS = 15 -- 视频播放帧率
-- 使用 AirUI 播放视频
local function play_video_with_airui()
log.info("播放器", "准备播放视频...")
-- 检查视频文件是否存在
if not io.exists(VIDEO_PATH) then
log.error("播放器", "视频文件不存在:", VIDEO_PATH)
return false
end
-- 获取 LCD 尺寸
local lcd_width, lcd_height = lcd.getSize()
log.info("播放器", "LCD尺寸:", lcd_width, "x", lcd_height)
-- 获取视频实际分辨率
local temp_player, err = videoplayer.open(VIDEO_PATH)
local video_width, video_height = 160, 160
if temp_player then
local info = videoplayer.info(temp_player)
if info then
video_width = info.width
video_height = info.height
log.info("播放器", "视频实际分辨率:", video_width, "x", video_height)
end
videoplayer.close(temp_player)
else
log.warn("播放器", "无法获取视频信息,使用默认尺寸:", err)
end
-- 计算居中显示位置
local x = math.floor((lcd_width - video_width) / 2)
local y = math.floor((lcd_height - video_height) / 2)
if x < 0 then x = 0 end
if y < 0 then y = 0 end
log.info("播放器", "视频显示位置:", x, y)
-- 创建全屏黑色背景容器
local screen_container = airui.container({
x = 0,
y = 0,
w = lcd_width,
h = lcd_height,
color = 0x000000,
})
if not screen_container then
log.error("播放器", "创建屏幕容器失败")
return false
end
-- 创建视频容器
local video_container = airui.container({
parent = screen_container,
x = x,
y = y,
w = video_width,
h = video_height,
color = 0x000000,
})
if not video_container then
log.error("播放器", "创建视频容器失败")
return false
end
-- 创建 airui.video 组件
local interval = math.floor(1000 / VIDEO_FPS)
local video_component = airui.video({
parent = video_container,
x = 0,
y = 0,
src = VIDEO_PATH,
format = "mjpg",
interval = interval,
loop = true
})
if not video_component then
log.error("播放器", "创建视频组件失败")
return false
end
log.info("播放器", "视频组件创建成功")
-- 开启背光
gpio.setup(1, 1)
log.info("播放器", "背光已开启")
-- 开始播放
video_component:play()
log.info("播放器", "视频开始播放")
-- 保持任务运行
while true do
sys.wait(1000)
end
end
-- 播放器初始化任务
local function player_task()
log.info("播放器", "初始化LCD和AirUI...")
if not lcd_drv_init() then
log.error("播放器", "LCD初始化失败")
return
end
-- 开始播放视频
play_video_with_airui()
end
-- 启动播放器任务
sys.taskInit(player_task)
4.2 网络视频播放功能
网络视频播放功能用于从 HTTP 服务器下载 MJPG 视频并播放。
4.2.1 功能定义
配置网络连接参数,从指定 URL 下载视频文件到本地,然后使用 AirUI 框架播放视频。
- 从服务器下载视频文件
- 支持 HTTP/HTTPS 协议
- 下载完成后自动播放
- 视频临时存储在 /ram/ 目录
4.2.2 代码示例
--[[
网络视频播放功能模块
核心业务逻辑:
1. 等待网络连接就绪
2. 从服务器下载视频到 /ram/server_video.mjpg
3. 使用 airui.video 组件播放视频
4. 支持循环播放
]]
local SERVER_VIDEO_URL = "https://appstoreoss.luatos.com/iot-apps/res/100197/video_160x160.mjpg"
local DOWNLOADED_VIDEO_PATH = "/ram/server_video.mjpg"
local VIDEO_FPS = 15
-- 从服务器下载视频
local function download_video()
log.info("播放器", "从服务器下载视频:", SERVER_VIDEO_URL)
-- 等待网络就绪
log.info("播放器", "等待网络连接...")
while not socket.adapter(socket.dft()) do
sys.waitUntil("IP_READY", 1000)
end
log.info("播放器", "网络已就绪")
-- 清理旧文件
if io.exists(DOWNLOADED_VIDEO_PATH) then
os.remove(DOWNLOADED_VIDEO_PATH)
log.info("播放器", "删除旧视频文件")
end
-- 下载视频文件
log.info("播放器", "开始下载...")
local code, headers, body_size = http.request("GET", SERVER_VIDEO_URL, nil, nil,
{dst = DOWNLOADED_VIDEO_PATH, timeout = 60000}).wait()
if code ~= 200 then
log.error("播放器", "下载失败, code:", code)
return false
end
log.info("播放器", "下载完成, 大小:", body_size, "字节")
-- 检查文件
local actual_size = io.fileSize(DOWNLOADED_VIDEO_PATH)
if actual_size ~= body_size then
log.error("播放器", "文件大小不一致, 预期:", body_size, "实际:", actual_size)
return false
end
return true
end
-- 使用 AirUI 播放视频
local function play_video_with_airui()
log.info("播放器", "准备播放视频...")
-- 下载视频
if not download_video() then
log.error("播放器", "下载视频失败")
return false
end
-- 获取 LCD 尺寸
local lcd_width, lcd_height = lcd.getSize()
log.info("播放器", "LCD尺寸:", lcd_width, "x", lcd_height)
-- 获取视频实际分辨率
local temp_player, err = videoplayer.open(DOWNLOADED_VIDEO_PATH)
local video_width, video_height = 160, 160
if temp_player then
local info = videoplayer.info(temp_player)
if info then
video_width = info.width
video_height = info.height
log.info("播放器", "视频实际分辨率:", video_width, "x", video_height)
end
videoplayer.close(temp_player)
else
log.warn("播放器", "无法获取视频信息,使用默认尺寸:", err)
end
-- 计算居中显示位置
local x = math.floor((lcd_width - video_width) / 2)
local y = math.floor((lcd_height - video_height) / 2)
if x < 0 then x = 0 end
if y < 0 then y = 0 end
log.info("播放器", "视频显示位置:", x, y)
-- 创建全屏黑色背景容器
local screen_container = airui.container({
x = 0,
y = 0,
w = lcd_width,
h = lcd_height,
color = 0x000000,
})
if not screen_container then
log.error("播放器", "创建屏幕容器失败")
return false
end
-- 创建视频容器
local video_container = airui.container({
parent = screen_container,
x = x,
y = y,
w = video_width,
h = video_height,
color = 0x000000,
})
if not video_container then
log.error("播放器", "创建视频容器失败")
return false
end
-- 创建 airui.video 组件
local interval = math.floor(1000 / VIDEO_FPS)
local video_component = airui.video({
parent = video_container,
x = 0,
y = 0,
src = DOWNLOADED_VIDEO_PATH,
format = "mjpg",
interval = interval,
loop = true
})
if not video_component then
log.error("播放器", "创建视频组件失败")
return false
end
log.info("播放器", "视频组件创建成功")
-- 开启背光
gpio.setup(1, 1)
log.info("播放器", "背光已开启")
-- 开始播放
video_component:play()
log.info("播放器", "视频开始播放")
-- 保持任务运行
while true do
sys.wait(1000)
end
end
-- 播放器初始化任务
local function player_task()
log.info("播放器", "初始化LCD和AirUI...")
if not lcd_drv_init() then
log.error("播放器", "LCD初始化失败")
return
end
-- 开始播放视频
play_video_with_airui()
end
-- 启动播放器任务
sys.taskInit(player_task)
4.3 LCD 驱动初始化
LCD 驱动初始化模块负责配置 ST7796 LCD 显示屏和 AirUI 框架。
4.3.1 功能定义
初始化 LCD 驱动,配置屏幕参数,并初始化 AirUI 框架。
- 初始化 ST7796 LCD 驱动
- 配置 320x480 分辨率
- 初始化 AirUI 框架
- GPIO141 控制 LCD 供电使能
4.3.2 代码示例
--[[
LCD 驱动初始化模块
核心业务逻辑:
1. 使能 LCD 供电 LDO
2. 初始化 ST7796 LCD 驱动
3. 初始化 AirUI 框架
4. 背光在初始化完成后再开启
]]
-- LCD 初始化函数
function lcd_drv_init()
-- Air8000 开发板上,使能 lcd 供电的 ldo 电源开关
gpio.setup(141, 1)
local result = lcd.init("st7796",
{
pin_pwr = nil, -- 背光控制引脚,先不开启
port = lcd.HWID_0, -- 驱动端口
pin_rst = 2, -- lcd 复位引脚
direction = 0, -- lcd 屏幕方向
w = 320, -- lcd 水平分辨率
h = 480, -- lcd 竖直分辨率
xoffset = 0,
yoffset = 0,
bus_speed = 80000000, -- SPI 总线速度
})
log.info("lcd.init", result)
if result then
-- 初始化 AirUI
local width, height = lcd.getSize()
local airui_result = airui.init(width, height)
if not airui_result then
log.error("airui", "init failed")
return false
end
log.info("airui", "init success", width, height)
end
return result
end
4.4 主程序入口
主程序入口负责加载 LCD 驱动和视频播放功能模块。
4.4.1 功能定义
配置项目信息,加载必要的模块,选择播放模式(本地播放或网络播放)。
4.4.2 代码示例
--[[
主程序入口
核心业务逻辑:
1. 定义项目信息(PROJECT、VERSION)
2. 加载 LCD 驱动模块
3. 选择视频播放模式(二选一)
- 播放本地烧录的视频:require "mjpg_player"
- 播放从服务器下载的视频:require "mjpg_player_server"
]]
PROJECT = "PLAY_MJPG"
VERSION = "001.999.000"
-- 在日志中打印项目名和项目版本号
log.info("main", PROJECT, VERSION)
-- 加载 LCD 驱动模块
require "lcd_drv"
-- 加载视频播放业务逻辑模块(二选一)
-- 场景一:播放本地烧录的视频(默认启用)
require "mjpg_player"
-- 场景二:播放从服务器下载的视频
-- 测试播放从服务器下载的视频功能,取消注释下一行
-- require "mjpg_player_server"
-- 用户代码已结束---------------------------------------------
sys.run()
-- sys.run()之后不要加任何语句!!!!!
五、功能演示
5.1 本地视频播放功能演示
确保 main.lua 中保留 require "mjpg_player" 语句,注释掉 require "mjpg_player_server"

使用 Luatools 将代码和视频文件烧录到 Air8000 开发板

烧录完毕后,日志中会打印视频播放的开始信息

0 开发板将自动播放本地视频文件,LCD 屏幕显示视频内容

5.2 网络视频播放功能演示
确保 main.lua 中保留 require "mjpg_player_server" 语句,注释掉 require "mjpg_player"

使用 Luatools 将代码烧录到 Air8000 开发板

开发板将连接网络并下载视频,日志中会打印下载和播放状态

视频下载完成后自动播放,LCD 屏幕显示视频内容
