你有没有过这样的经历?家里装了YCC365摄像头,结果插了存储卡后,想翻看录像视频,却发现要么只能在手机App上慢慢加载,要么上传到云端的视频看个几分钟就要付费,说实话,我自己一开始也折腾了好久,后来我发现,其实用Golang(Go语言)写个小工具,就能直接从存储卡里读取、管理这些视频文件,完全不用依赖那些花里胡哨的App。
这篇文章就是我这段时间自己摸索出来的经验,不搞那些复杂的理论,咱们直接上手。
第一步:理解YCC365存储卡里视频的存储结构
YCC365摄像头默认会把视频存储在TF卡(MicroSD卡)中,通常采用FAT32或exFAT文件系统,视频文件的格式大多是MP4,但文件名和目录结构可能看起来有点“奇怪”,比如像 RECORD/2024/12/15/15/30_001.mp4 这样的路径,时间戳和分段编号混在一起。
为什么要自己写工具?
- 离线查看:不需要网络,直接读卡。
- 批量导出:一键复制指定时间段的所有视频。
- 跳过加密:很多品牌摄像头会加密视频,但YCC365的本地文件其实只是普通MP4,直接用播放器就能打开。
- 自定义规则:比如只保留最近7天的录像,或者自动压缩成更小的格式。
第二步:用Golang读取存储卡目录
我们先写一个最简单的Golang程序,把存储卡挂载到电脑后(假设盘符是 D:),列出所有视频文件,这里我用的是Go标准库里的 os 和 path/filepath 包。
package main
import (
"fmt"
"os"
"path/filepath"
"strings"
)
func main() {
root := "D:\\RECORD" // 你的存储卡路径
filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// 只找MP4文件
if !info.IsDir() && strings.HasSuffix(info.Name(), ".mp4") {
fmt.Println(path)
}
return nil
})
}
跑一下这段代码,你就会看到所有MP4文件的完整路径,你可能发现文件名里包含了年月日时分秒,15_30_45.mp4 表示15点30分45秒开始的那段录像。
小贴士:如果卡里文件特别多(比如说32GB卡存了上千个文件),第一次遍历可能会慢一点,但Go的并发特性让我们之后可以优化。
第三步:解析文件名,按时间筛选视频
我们要按时间段筛选视频,我只想看今天下午3点到4点之间的录像。
我们需要从文件路径或文件名里提取时间信息,YCC365的命名规则一般是 YYYYMMDD_HHMMSS.mp4 加上摄像机编号,我们来写个解析函数:
import "time"
func parseTimeFromName(filename string) (time.Time, error) {
// 假设文件名格式:20241215_153045.mp4
parts := strings.Split(filename, "_")
if len(parts) != 2 {
return time.Time{}, fmt.Errorf("命名格式不对,请检查下")
}
datePart := parts[0]
timePart := strings.Split(parts[1], ".")[0]
// 拼接成标准时间
timeStr := datePart + " " + timePart[:2] + ":" + timePart[2:4] + ":" + timePart[4:6]
return time.Parse("20060102 15:04:05", timeStr)
}
如果卡里文件名格式和你家摄像头略有不同,别急,自己改改 time.Parse 的模板就行,像我家那个旧款,文件名里还多了个 _CH1 这样的通道标识(20241215_153045_CH1.mp4),那就先去掉后缀再解析。
第四步:用表格列出找到的视频
假设你要写一个简单的控制台输出,但我觉得还是表格看起来清楚,在Go里,可以用 text/tabwriter 包来对齐输出,但为了直观,我直接用 fmt 配合手动制表符:
func printVideoList(videos []string) {
fmt.Println("序号\t| 文件名\t\t\t| 时间\t\t\t| 大小")
fmt.Println("----\t| ------------------\t\t| ------------\t\t| ----")
for i, v := range videos {
info, _ := os.Stat(v)
sizeMB := float64(info.Size()) / 1024 / 1024
fmt.Printf("%d\t| %s\t| %s\t| %.2f MB\n", i+1, info.Name(), info.ModTime().Format("15:04:05"), sizeMB)
}
}
这里的 ModTime 可能不准,因为复制卡后修改时间会变,更靠谱还是从文件名里拿时间。
第五步:自动播放或打开视频(带点不完美的小技巧)
我们最直接的需求是“看视频”,在Windows上,你可以用Go调用系统默认播放器,这里用了 os/exec:
import "os/exec"
func openVideo(path string) {
cmd := exec.Command("cmd", "/c", "start", path)
err := cmd.Run()
if err != nil {
fmt.Println("打不开视频,可能路径有问题或没安装播放器")
}
}
在macOS上把命令改成 open,Linux改成 xdg-open,这段代码有个坑:如果视频文件在存储卡上被系统锁定了(比如Windows自动扫描时),可能播放失败,我遇到过一次,只能先复制到硬盘再打开,于是我在工具里加了个“先复制到临时目录”的选项:
func copyToTemp(path string) (string, error) {
// 生成临时文件名
tmpFile := filepath.Join(os.TempDir(), filepath.Base(path))
// 复制文件
data, err := os.ReadFile(path)
if err != nil {
return "", err
}
err = os.WriteFile(tmpFile, data, 0644)
return tmpFile, err
}
然后先复制再播放,这个办法虽然笨,但稳定。
第六步:让工具自动分组显示(用列表和加粗)
有时候存储卡里视频太多,一屏刷不完,我加了个简单分组,按天显示,还用了 加粗 的标题:
func groupByDay(videos []string) map[string][]string {
groups := make(map[string][]string)
for _, v := range videos {
// 从路径里截取日期,"20241215"
dateKey := strings.Split(filepath.Base(v), "_")[0]
groups[dateKey] = append(groups[dateKey], v)
}
return groups
}
输出的时候:
for date, list := range groupByDay(allVideos) {
fmt.Printf("\n** 日期:%s **\n", date)
for _, v := range list {
fmt.Printf(" - %s\n", filepath.Base(v))
}
}
给个生活化的例子:你老婆问你“前天下午宝宝在客厅爬的视频在哪”,你直接输日期 20241213,程序就只显示那天的视频,不用在几百个文件里瞎翻。
第七步:处理“卡里的视频在App上看不到”的情况
我遇到过几次:把卡插回摄像头后,App里某些旧视频不显示,但卡里实际有文件,这是因为YCC365的App只会索引最近一段时间录制的文件,或者文件系统碎片出了问题,用我们的Go工具,直接读卡,就不受App限制了。
你还可以写个小函数,把文件名里带“EVENT”或“ALARM”的标记出来,这些一般是移动侦测或报警录像,我习惯用 斜体 在列表里强调一下:
if strings.Contains(info.Name(), "EVENT") {
fmt.Printf("* [报警] %s\n", info.Name())
} else {
fmt.Printf(" %s\n", info.Name())
}
第八步:完整的代码结构和运行方式
我习惯把整个工具组织成几个文件:
| 文件 | 用途 |
|---|---|
| main.go | 入口,处理用户输入 |
| reader.go | 扫描卡上视频文件 |
| parser.go | 解析文件名时间 |
| player.go | 播放/复制功能 |
| display.go | 格式化输出,表格/列表 |
运行方式很简单,编译成 .exe 放在 D:\ 根目录:

go build -o ycc365-tool.exe
然后双击运行,或者命令行里加参数:
ycc365-tool.exe --path D:\RECORD --date 20241215 --list
第九步:意外情况的处理——卡没插好或只读
这工具不是万能的,如果存储卡被写保护(那滑动开关),或者读卡器接触不良,filepath.Walk 会直接报错,我在代码里加了重试机制和友好的提示:
func safeWalk(root string) {
for i := 0; i < 3; i++ {
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
fmt.Println("读文件出错,重试中...", err)
return nil // 跳过这个文件
}
// 正常处理...
return nil
})
if err != nil {
fmt.Printf("第%d次尝试失败:%v\n", i+1, err)
time.Sleep(2 * time.Second)
} else {
break
}
}
}
实际使用时,偶尔会遇到某个MP4文件损坏打不开,我就直接跳过它,不会中断整个扫描。
第十步:小进阶——对视频文件做快速转码
有些播放器比较老,不支持H.265编码的视频(YCC365新款可能用这个格式),你可以通过Go调用FFmpeg来转码,这个功能我暂时没集成进去,因为需要用户先装FFmpeg,不过我写了个示例代码:
func transcodeToH264(input, output string) {
cmd := exec.Command("ffmpeg", "-i", input, "-c:v", "libx264", "-preset", "fast", output)
err := cmd.Run()
if err != nil {
fmt.Println("转码失败,可能没装FFmpeg或者输入文件有问题")
}
}
加了这个,就可以一键把存储卡里所有H.265视频转成通用格式,然后传到手机上看。
写在最后
说实话,写这个Golang小工具,一开始只是想省点事,结果发现折腾得比手工翻卡还久,但用顺了之后,感觉挺值的——不依赖App、不联网、不花钱,随时能在电脑上管理几百个视频文件,而且Golang编译出来的文件就一个exe,丢到U盘里给朋友用,他们双击就跑,完全不需要装环境。
如果你只是想快速看一两个视频,用手机App就够,但如果你像我一样,家里摄像头每天录十几个文件,定期要翻看、备份、删除旧片段,那这个工具绝对是解放双手的利器。
卡片还在转,代码就不停了。
本文来自作者[kyadmin]投稿,不代表be365立场,如若转载,请注明出处:http://www.hljbesthome.com/qiche/1494.html
评论列表(4条)
我是be365的签约作者“kyadmin”!
希望本篇文章《从零开始,用Golang写一个工具,轻松查看YCC365存储卡里的视频》能对你有所帮助!
本站[be365]内容主要涵盖:be365,be365网站,be365网址,ball365体育,Be365排名
本文概览:你有没有过这样的经历?家里装了YCC365摄像头,结果插了存储卡后,想翻看录像视频,却发现要么只能在手机App上慢慢加载,要么上传到云端...