国产久操视频-国产久草视频-国产久热精品-国产久热香蕉在线观看-青青青青娱乐-青青青青在线成人视99

  • 正文
    • 準備工作
    • 調(diào)試錄像
    • 寫個代碼錄像
    • 錄像文件播放
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

海納思(Hi3798MV300)機頂盒遇到海思攝像機

05/12 17:00
797
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

周末折騰了一下這個海思機頂盒,家里還有個海思的攝像機模組開發(fā)板,結(jié)合機頂盒來做個錄像。

準備工作

    1. 海納斯機頂盒2. 攝像機模組3. 兩根網(wǎng)線、兩個電源、路由器4. 一塊64G固態(tài)硬盤

攝像機模組和機頂盒都接入路由器的LAN口,確保網(wǎng)絡(luò)正常通信

道具

攝像機模組

調(diào)試錄像

攝像機模組

攝像機模組里的程序其實是基于海思的SDK里的demo稍作修改而成,沒有做太復(fù)雜的功能,只加入了RTSP,對外提供RTSP接口服務(wù)。
這里用的rtsp服務(wù)的庫代碼比較好用,源碼鏈接:https://gitee.com/fensnote/RtspServer

在電腦上用VLC測試拉流播放:

VLC

海納斯盒子錄像

關(guān)于錄像,這里只是實現(xiàn)簡單的文件存儲、循環(huán)覆蓋,并不是專業(yè)的錄像,專業(yè)錄像里會做的比較復(fù)雜。

    1. 直接用Ffmpeg命令行錄取數(shù)據(jù)到文件里,為了方便播放保存為MP4文件。2. 寫代碼實現(xiàn)rtsp拉流存儲,可以自己定義傳參。

Ffmpeg錄像

這個比較簡單,一條命令即可,不過直接采用命令錄像沒法指定實現(xiàn)循環(huán)覆蓋,要想實現(xiàn)可以再寫個腳本取定時檢測錄像文件的個數(shù)。
首先需要先下載安裝Ffmpeg:

sudo?apt install ffmpeg

安裝日志

我這里已經(jīng)安裝過了。

接下來就用可以執(zhí)行錄像了:

ffmpeg -rtsp_transport tcp -i rtsp://192.168.2.168:41667/live -c copy -f segment -segment_time 60 stream_piece_%d.mp4

這條命令里是指定了錄像時長60秒,即一分鐘切換一個文件。

ffmpeg

如下截圖,錄取一分鐘后已切換文件,1分鐘錄像數(shù)據(jù)15M,數(shù)據(jù)量挺大了:

錄像上傳上來播放一下看看:

上傳

播放:

使用win11的系統(tǒng)播放器就可以播放

播放

寫個代碼錄像

這里選用了go語言來寫這個錄像代碼,是因為go語言的音視頻、網(wǎng)絡(luò)相關(guān)的庫實在太多,比較好用,代碼量也不大,可以提需求讓AI去寫,AI寫的基本上稍作修改測試幾次就可以用了。
Go還有個好處就是靜態(tài)編譯,真正的跨平臺,一次編譯,CPU架構(gòu)一樣都可以運行,感覺缺點就是可執(zhí)行文件比較大。

這里采用的gortsplib,源碼地址:https://gitee.com/fensnote/gortsplib.git

可以基于gortsplib/examples下的client-play-format-h264-save-to-disk示例代碼做修改:

復(fù)制

我復(fù)制了命名為client-play-format-h264-save-to-disk-file,在這里修改,下面代碼是調(diào)試完成的代碼:

package?main

import?(
? ??"flag"
? ??"fmt"
? ??"log"
? ??"os"
? ??"os/signal"
? ??"syscall"
? ??"time"

? ??"github.com/bluenviron/gortsplib/v4"
? ??"github.com/bluenviron/gortsplib/v4/pkg/base"
? ??"github.com/bluenviron/gortsplib/v4/pkg/format"
? ??"github.com/bluenviron/gortsplib/v4/pkg/format/rtph264"
? ??"github.com/pion/rtp"
)

const?(
? ? filePrefix =?"rec"? ??// 文件名前綴
? ? fileSuffix =?".mp4"? ?// 文件名后綴
)

func?main()?{
? ??// Define command line flags
? ? rtspURL := flag.String("r",?"",?"RTSP URL")
? ? maxFilesPtr := flag.Int("c",?0,?"文件數(shù)")
? ? startFileNumPtr := flag.Int("s",?0,?"起始文件編號")
? ? durationPtr := flag.Int("t",?60,?"單個文件錄像時長")
? ? modePtr := flag.String("m",?"loop",?"錄像模式,單次模式:"once",循環(huán)模式:"loop", 注意要加雙引號")

? ??// Parse command line flags
? ? flag.Parse()

? ??// Check if the required arguments are provided
? ??if?*rtspURL ==?""?|| *maxFilesPtr ==?0?{?//|| *startFileNumPtr == 0 ? ??
? ? ? ? flag.PrintDefaults()?// Print usage information
? ? ? ? log.Fatal("Missing required command line arguments")
? ? }

? ??if?*startFileNumPtr <?0?|| *startFileNumPtr > *maxFilesPtr {
? ? ? ? log.Fatalf("起始文件編號必須是0~%d", *maxFilesPtr)
? ? }

? ??// Check if the RTSP URL is valid
? ? u, err := base.ParseURL(*rtspURL)
? ??if?err !=?nil?{
? ? ? ? log.Fatalf("無效的RTSP URL: %v", err)
? ? }

? ? c := gortsplib.Client{}

? ??// Connect to the server
? ? err = c.Start(u.Scheme, u.Host)
? ??if?err !=?nil?{
? ? ? ? log.Fatalf("連接 RTSP server 失敗: %v", err)
? ? }
// ? ?defer c.Close()

? ??// Find available medias
? ? desc, _, err := c.Describe(u)
? ??if?err !=?nil?{
? ? ? ? log.Fatalf("Failed to describe RTSP stream: %v", err)
? ? }

? ??// Find the H264 media and format
? ??var?forma *format.H264
? ? medi := desc.FindFormat(&forma)
? ??if?medi ==?nil?{
? ? ? ? log.Fatal("H264 media not found")
? ? }

? ??// Setup RTP -> H264 decoder
? ? rtpDec, err := forma.CreateDecoder()
? ??if?err !=?nil?{
? ? ? ? log.Fatalf("Failed to create H264 decoder: %v", err)
? ? }

? ??var?mpegtsMuxer *mpegtsMuxer
? ??var?fileCounter?int
? ??var?recordingStartTime time.Time
? ??// var bakPts int64;
? ??// var sub int

? ??// Create the first file immediately when the program starts
? ? fileCounter = *startFileNumPtr
? ? newFileName := fmt.Sprintf("%s%03d%s", filePrefix, fileCounter, fileSuffix)
? ? mpegtsMuxer = newMpegtsMuxer(newFileName, forma.SPS, forma.PPS)
? ? err = mpegtsMuxer.initialize()
? ??if?err !=?nil?{
? ? ? ? log.Fatalf("Failed to initialize MPEG-TS muxer: %v", err)
? ? }
? ? log.Printf("New file created: %s", newFileName)
? ? recordingStartTime = time.Now()

? ??// Setup a single media
? ? _, err = c.Setup(desc.BaseURL, medi,?0,?0)
? ??if?err !=?nil?{
? ? ? ? log.Fatalf("Failed to setup media: %v", err)
? ? }

? ??// Create a ticker to create a new file based on the specified duration
? ? duration := time.Duration(*durationPtr) * time.Second
? ? ticker := time.NewTicker(duration)
? ? duration = duration +?100000000// Add 200ms to the duration to ensure the ticker fires after the duration
? ??defer?ticker.Stop()

? ??// bakPts = 0
? ??// Called when a RTP packet arrives
? ? c.OnPacketRTP(medi, forma,?func(pkt *rtp.Packet)?{
? ? ? ??// Decode timestamp
? ? ? ? pts, ok := c.PacketPTS2(medi, pkt)
? ? ? ??if?!ok {
? ? ? ? ? ??//log.Printf("Waiting for timestamp")
? ? ? ? ? ? pts =?int64(pkt.Timestamp)
? ? ? ? ? ??//return
? ? ? ? }
? ? ? ??// if bakPts == 0 {
? ? ? ??// ? ? bakPts = pts
? ? ? ??// }

? ? ? ??// Extract access unit from RTP packets
? ? ? ? au, err := rtpDec.Decode(pkt)
? ? ? ??if?err !=?nil?{
? ? ? ? ? ??if?err != rtph264.ErrNonStartingPacketAndNoPrevious && err != rtph264.ErrMorePacketsNeeded {
? ? ? ? ? ? ? ? log.Printf("ERR: %v", err)
? ? ? ? ? ? }
? ? ? ? ? ??return
? ? ? ? }
? ? ? ??
? ? ? ??// sub = (int)(pts - bakPts)/100000
? ? ? ??// Encode the access unit into MPEG-TS
? ? ? ??if?mpegtsMuxer !=?nil?{
? ? ? ? ? ? err = mpegtsMuxer.writeH264(au, pts)
? ? ? ? ? ??if?err !=?nil?{
? ? ? ? ? ? ? ? log.Printf("ERR: %v", err)
? ? ? ? ? ? ? ??return
? ? ? ? ? ? }
? ? ? ? ? ??// log.Printf("Saved TS packet, pts: %d,sub:%d",pts,sub)
? ? ? ? }

? ? ? ??// Check if it's time to create a new file or exit
? ? ? ??// if sub >= *durationPtr {
? ? ? ??if?time.Since(recordingStartTime) >= duration {
? ? ? ? ? ? mpegtsMuxer.close()
? ? ? ? ? ??if?*modePtr ==?"once"?{
? ? ? ? ? ? ? ? log.Println("Recording duration reached, exiting...")
? ? ? ? ? ? ? ? c.Close()?// Close the RTSP client connection
? ? ? ? ? ? ? ? os.Exit(0)?// Exit the program immediately
? ? ? ? ? ? }?else?{
? ? ? ? ? ? fileCounter = (fileCounter +?1) % *maxFilesPtr
? ? ? ? ? ? newFileName := fmt.Sprintf("%s%03d%s", filePrefix, fileCounter, fileSuffix)
? ? ? ? ? ? mpegtsMuxer = newMpegtsMuxer(newFileName, forma.SPS, forma.PPS)
? ? ? ? ? ? err = mpegtsMuxer.initialize()
? ? ? ? ? ??if?err !=?nil?{
? ? ? ? ? ? ? ? log.Fatalf("ERR: %v", err)
? ? ? ? ? ? ? ? c.Close()?// Close the RTSP client connection
? ? ? ? ? ? ? ? os.Exit(-1)?// Exit the program immediately
? ? ? ? ? ? }
? ? ? ? ? ? log.Printf("New file created: %s", newFileName)
? ? ? ? ? ? recordingStartTime = time.Now()
? ? ? ? ? ??//bakPts = pts
? ? ? ? }
? ? ? ? }

? ? })

? ??// Start playing
? ? _, err = c.Play(nil)
? ??if?err !=?nil?{
? ? ? ? log.Fatalf("Failed to play RTSP stream: %v", err)
? ? }

? ??// Wait for interrupt signal or recording duration
? ? sigChan :=?make(chan?os.Signal,?1)
? ? signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
? ??gofunc()?{
? ? ? ??for?{
? ? ? ? ? ??select?{
? ? ? ? ? ??case?<-ticker.C:
? ? ? ? ? ? ? ??if?*modePtr ==?"once"?{
? ? ? ? ? ? ? ? ? ? log.Println("Recording duration reached, exiting...")
? ? ? ? ? ? ? ? ? ? c.Close()
? ? ? ? ? ? ? ? ? ? os.Exit(0)
? ? ? ? ? ? ? ? }
? ? ? ? ? ??case?<-sigChan:
? ? ? ? ? ? ? ? log.Println("Interrupt signal received, exiting...")
? ? ? ? ? ? ? ? c.Close()
? ? ? ? ? ? ? ? os.Exit(0)
? ? ? ? ? ? }
? ? ? ? }
? ? }()

? ??// Block main goroutine forever
? ??select?{}
}

代碼編譯

export?GOOS=linux
export?GOARCH=arm
export?GOARM=5
#export CGO_ENABLED=1

go build -ldflags?'-s -w'

錄像測試

?vrec
? -c int
? ? ? ? 文件數(shù)
? -m string
? ? ? ? 錄像模式,單次模式:"once",循環(huán)模式:"loop", 注意要加雙引號 (default?"loop")
? -r string
? ? ? ? RTSP URL
? -s int
? ? ? ? 起始文件編號
? -t int
? ? ? ? 單個文件錄像時長 (default 60)
2025/05/10 09:30:59 Missing required?command?line arguments
#錄像命令參數(shù):
vrec -c 1200 -m?"loop"?-s 0 -t 60 ?-r rtsp://192.168.2.168:41667/live

錄像文件播放

錄像文件查看,這是錄了一晚上的,文件比較多:

測試

通過電腦查看

在海納思的內(nèi)置web頁面查看錄像文件,首頁還是挺好看的:

首頁
文件管理器錄像文件
錄像文件可以直接點擊播放:

通過手機查看

手機
文件管理錄像列表
點擊播放播放

海思

海思

海思面向智能終端、顯示面板、家電、汽車電子等行業(yè)提供感知、聯(lián)接、計算、顯示等端到端的板級芯片和模組解決方案,覆蓋PLC、8K、NB-IoT、SoC和XR等技術(shù)領(lǐng)域,是全球領(lǐng)先的Fabless半導(dǎo)體芯片公司。

海思面向智能終端、顯示面板、家電、汽車電子等行業(yè)提供感知、聯(lián)接、計算、顯示等端到端的板級芯片和模組解決方案,覆蓋PLC、8K、NB-IoT、SoC和XR等技術(shù)領(lǐng)域,是全球領(lǐng)先的Fabless半導(dǎo)體芯片公司。收起

查看更多

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄
北流市| 防城港市| 罗城| 长兴县| 夏邑县| 漳平市| 轮台县| 四川省| 昭通市| 镇雄县| 阿图什市| 宁都县| 枝江市| 崇仁县| 长顺县| 祁东县| 盐亭县| 恭城| 东乌珠穆沁旗| 会同县| 道真| 新泰市| 海口市| 水富县| 宁国市| 博乐市| 玉龙| 盐城市| 灵山县| 英吉沙县| 宝鸡市| 莱州市| 南部县| 闻喜县| 清徐县| 佛坪县| 昌都县| 建水县| 霸州市| 白山市| 黔江区|