K230基础-录放视频

第二十三章 录放视频-K230视频录制与回放能力

🎯 本章目标

掌握在 K230(CanMV 平台)上实现视频录制与回放的核心方法,学会将摄像头采集的图像帧保存为视频文件(如 MJPEG 流),并实现本地存储与回放,构建嵌入式监控、记录仪等应用。


1. 视频处理能力概述

1.1 K230 视频支持现状

  • ✅ 支持 摄像头实时采集
  • ✅ 支持 JPEG 图像编码(由摄像头硬件完成)
  • ✅ 支持 MJPEG 视频流(连续 JPEG 帧)
  • ❌ 不支持 H.264/HEVC 等高压缩编码
  • ✅ 支持 SD 卡存储
  • ❌ 无硬件视频编码器,依赖摄像头输出 JPEG

📌 结论

可通过 摄像头输出 MJPEG 流 + SD 卡存储 实现"类视频"录制。


2. 视频格式说明

2.1 MJPEG(Motion JPEG)

  • 将视频每一帧作为独立 JPEG 图像存储
  • 文件扩展名通常为 .avi.mjpeg
  • 优点:简单、兼容性好、无需复杂编码
  • 缺点:文件大、压缩率低

K230 最可行方案


3. 视频录制:将图像帧保存为 MJPEG

3.1 硬件准备

  • K230 开发板
  • 摄像头(OV2640 推荐)
  • SD 卡(≥8GB,Class 10)
  • FPIOA 映射 SPI 引脚(见 SPI 章节)

3.2 SD 卡挂载

python 复制代码
import os
import sdcard
from machine import SPI, Pin
from fpioa_manager import fm

# SPI 引脚定义
SCLK_PIN = 6
MOSI_PIN = 8
MISO_PIN = 9
CS_PIN   = 7

# FPIOA 映射
fm.register(SCLK_PIN, fm.fpioa.SPI1_SCLK)
fm.register(MOSI_PIN, fm.fpioa.SPI1_D0)
fm.register(MISO_PIN, fm.fpioa.SPI1_D1)
fm.register(CS_PIN,   fm.fpioa.GPIOHS0)

# 初始化 SPI
spi = SPI(SPI.SPI1, baudrate=20_000_000, polarity=0, phase=0)
cs = Pin(CS_PIN, Pin.OUT, value=1)

# 挂载 SD 卡
sd = sdcard.SDCard(spi, cs)
os.mount(sd, "/sd")
print("SD 卡已挂载")

3.3 视频录制主程序

python 复制代码
import sensor
import time
import os

# 初始化摄像头
sensor.reset()
sensor.set_pixformat(sensor.JPEG)      # 必须使用 JPEG 格式
sensor.set_framesize(sensor.VGA)      # 640x480
sensor.skip_frames(time=2000)

# 设置 JPEG 质量
sensor.set_quality(10)  # 1~63,越小质量越高

print("开始视频录制...")

# 创建视频目录
try:
    os.mkdir("/sd/video")
except:
    pass

# 视频文件名
filename = "/sd/video/vid_%d.mjpeg" % time.time()
f = open(filename, "wb")

# 录制时长(秒)
DURATION = 30
FPS = 10
INTERVAL = int(1000 / FPS)  # 毫秒

clock = time.clock()
start_time = time.ticks_ms()

try:
    while time.ticks_diff(time.ticks_ms(), start_time) < DURATION * 1000:
        clock.tick()

        # 拍摄一帧(JPEG 格式)
        img = sensor.snapshot()

        # 获取原始 JPEG 数据
        jpeg_data = img.compress_to_jpeg()  # 或直接使用 img.bytearray()

        # 写入文件
        f.write(jpeg_data)

        # 可选:显示进度
        elapsed = time.ticks_diff(time.ticks_ms(), start_time) / 1000
        print("录制中: %.1fs / %ds, FPS: %.1f" % (elapsed, DURATION, clock.fps()))

        # 控制帧率
        time.sleep_ms(max(1, INTERVAL - clock.fps()))

    print("✅ 视频录制完成:", filename)

except Exception as e:
    print("❌ 录制出错:", e)

finally:
    f.close()

🔧 说明

  • 生成的 .mjpeg 文件可在 VLC、FFmpeg 等工具中播放
  • 每帧为独立 JPEG,拼接成 MJPEG 流

4. 视频回放:从文件读取并显示

4.1 MJPEG 解码与显示(逐帧)

python 复制代码
import os
import image
from machine import Timer

# 视频文件路径
video_file = "/sd/video/vid_1717000000.mjpeg"

# 初始化 TFT 屏幕(见第13章)
# tft = st7789.ST7789(...)

def play_video():
    try:
        f = open(video_file, "rb")
        print("开始回放视频...")

        frame_count = 0
        start_time = time.ticks_ms()

        while True:
            # 尝试读取 JPEG 帧(查找 0xFFD8 和 0xFFD9)
            data = f.read(1024)
            if not data:
                break

            # 查找 JPEG 起始与结束
            start = data.find(b'\xFF\xD8')
            end = data.find(b'\xFF\xD9')

            if start != -1 and end != -1 and end > start:
                jpeg_frame = data[start:end+2]

                # 创建图像对象并显示
                try:
                    img = image.Image(jpeg_frame)
                    # 缩放显示到 TFT
                    # tft.blit_buffer(img.bytearray(), ...)
                    frame_count += 1
                except:
                    continue

        duration = time.ticks_diff(time.ticks_ms(), start_time) / 1000
        print(f"✅ 回放完成,共 {frame_count} 帧,耗时 {duration:.1f}s")

    except Exception as e:
        print("❌ 回放失败:", e)
    finally:
        f.close()

# 开始回放
play_video()

⚠️ 限制:K230 无硬件 MJPEG 解码,需逐帧解析,效率较低。


5. 实战项目:带状态显示的视频记录仪

python 复制代码
# 结合 OLED 或 TFT 显示录制状态

import sensor
import lcd  # 假设有 lcd 模块
import time
import os

sensor.reset()
sensor.set_pixformat(sensor.JPEG)
sensor.set_framesize(sensor.QVGA)  # 320x240
sensor.set_quality(12)
sensor.skip_frames(time=2000)

# 录制函数
def record_video(duration=10):
    filename = f"/sd/vid_{time.time()}.mjpeg"
    f = open(filename, "wb")

    lcd.fill(0)
    lcd.draw_string(10, 10, "REC", color=(255,0,0))
    lcd.draw_string(10, 30, filename, color=(255,255,255))

    start = time.ticks_ms()
    frame_count = 0

    while time.ticks_diff(time.ticks_ms(), start) < duration * 1000:
        img = sensor.snapshot()
        f.write(img.compress_to_jpeg())
        frame_count += 1

        # 更新显示
        lcd.draw_string(10, 50, f"Frame: {frame_count}", color=(0,255,0))
        time.sleep_ms(100)

    f.close()
    lcd.draw_string(10, 80, "SAVED", color=(0,255,0))

6. 高级技巧与优化

6.1 控制录制大小

python 复制代码
MAX_SIZE = 100 * 1024 * 1024  # 100MB
if f.tell() > MAX_SIZE:
    print("视频达到最大尺寸,停止")
    break

6.2 使用环形缓冲(覆盖最旧视频)

python 复制代码
# 策略:删除最早生成的视频文件
files = os.listdir("/sd/video")
if len(files) > 10:
    files.sort()
    os.remove("/sd/video/" + files[0])

6.3 添加时间戳水印

python 复制代码
img = sensor.snapshot()
timestamp = "%02d:%02d:%02d" % (time.localtime()[3:6])
img.draw_string(200, 220, timestamp, color=(255,255,255))
f.write(img.compress_to_jpeg())

7. 常见问题与调试

❌ 问题1:视频文件无法播放

解决

  • 使用 VLC 播放器FFmpeg

    bash 复制代码
    ffplay -f mjpeg -i vid_1717000000.mjpeg
  • 确保每帧以 0xFFD8 开始、0xFFD9 结束

  • 检查文件是否完整

❌ 问题2:录制帧率低

优化

  • 使用 QVGAQQVGA 分辨率
  • 降低 JPEG 质量(set_quality(20)
  • 使用高速 SD 卡

❌ 问题3:SD 卡写入失败

排查

  • 检查 SPI 接线
  • 确认 SD 卡已格式化为 FAT32
  • 避免频繁打开/关闭文件

8. 性能与存储估算

分辨率 质量 每帧大小 10fps 下每分钟存储
QVGA (320x240) 10 ~8KB ~4.8MB
VGA (640x480) 10 ~20KB ~12MB
SVGA (800x600) 10 ~35KB ~21MB

建议:使用 32GB SD 卡可录制数小时 QVGA 视频。


本章你已掌握

  • K230 视频录制原理(MJPEG 流)
  • 摄像头配置为 JPEG 输出
  • SD 卡存储视频帧
  • 视频回放与显示
  • 性能优化与问题排查

相关推荐
陈敬雷-充电了么-CEO兼CTO2 小时前
DeepSeek vs ChatGPT 技术架构、成本与场景全解析
人工智能·chatgpt·架构
MarvinP2 小时前
《Seq2Time: Sequential Knowledge Transfer for Video LLMTemporal Grounding》
人工智能·计算机视觉
AORO20253 小时前
适合户外探险、物流、应急、工业,五款三防智能手机深度解析
网络·人工智能·5g·智能手机·制造·信息与通信
white-persist3 小时前
XXE 注入漏洞全解析:从原理到实战
开发语言·前端·网络·安全·web安全·网络安全·信息可视化
风清再凯3 小时前
01-iptables防火墙安全
服务器·网络·安全
wearegogog1233 小时前
基于块匹配的MATLAB视频去抖动算法
算法·matlab·音视频
铉铉这波能秀3 小时前
如何在Android Studio中使用Gemini进行AI Coding
android·java·人工智能·ai·kotlin·app·android studio
rongqing20193 小时前
Google 智能体设计模式:探索与发现
人工智能·设计模式
李永奉4 小时前
STM32-STM32最小系统板介绍
stm32·单片机·嵌入式硬件