• 纯Golang获取MP4视频时长信息


    主要原理是根据MP4文档格式取到moov结构,然后获取时长

    已上传到github https://github.com/akkuman/mp4info

    package main
    
    import (
    	"bytes"
    	"encoding/binary"
    	"fmt"
    	"io"
    	"os"
    	"path/filepath"
    )
    
    // BoxHeader 信息头
    type BoxHeader struct {
    	Size       uint32
    	FourccType [4]byte
    	Size64     uint64
    }
    
    func main() {
    	file, err := os.Open(os.Args[1])
    	if err != nil {
    		panic(err)
    	}
    	duration, err := GetMP4Duration(file)
    	if err != nil {
    		panic(err)
    	}
    	fmt.Println(filepath.Base(os.Args[1]), duration)
    }
    
    // GetMP4Duration 获取视频时长,以秒计
    func GetMP4Duration(reader io.ReaderAt) (lengthOfTime uint32, err error) {
    	var info = make([]byte, 0x10)
    	var boxHeader BoxHeader
    	var offset int64 = 0
    	// 获取moov结构偏移
    	for {
    		_, err = reader.ReadAt(info, offset)
    		if err != nil {
    			return
    		}
    		boxHeader = getHeaderBoxInfo(info)
    		fourccType := getFourccType(boxHeader)
    		if fourccType == "moov" {
    			break
    		}
    		// 有一部分mp4 mdat尺寸过大需要特殊处理
    		if fourccType == "mdat" {
    			if boxHeader.Size == 1 {
    				offset += int64(boxHeader.Size64)
    				continue
    			}
    		}
    		offset += int64(boxHeader.Size)
    	}
    	// 获取moov结构开头一部分
    	moovStartBytes := make([]byte, 0x100)
    	_, err = reader.ReadAt(moovStartBytes, offset)
    	if err != nil {
    		return
    	}
    	// 定义timeScale与Duration偏移
    	timeScaleOffset := 0x1C
    	durationOffest := 0x20
    	timeScale := binary.BigEndian.Uint32(moovStartBytes[timeScaleOffset : timeScaleOffset+4])
    	Duration := binary.BigEndian.Uint32(moovStartBytes[durationOffest : durationOffest+4])
    	lengthOfTime = Duration / timeScale
    	return
    }
    
    // getHeaderBoxInfo 获取头信息
    func getHeaderBoxInfo(data []byte) (boxHeader BoxHeader) {
    	buf := bytes.NewBuffer(data)
    	binary.Read(buf, binary.BigEndian, &boxHeader)
    	return
    }
    
    // getFourccType 获取信息头类型
    func getFourccType(boxHeader BoxHeader) (fourccType string) {
    	fourccType = string(boxHeader.FourccType[:])
    	return
    }
    
    
  • 相关阅读:
    liunx 解压与压缩
    缓存设计与优化
    易混乱javascript知识点简要记录
    初识RedisCluster集群
    Redis Sentinel(哨兵模式)
    JavaScript作用域简单记录
    JavaScript引用类型简单记录
    redis主从复制初识
    javascript基础知识点
    持久化的一些问题
  • 原文地址:https://www.cnblogs.com/Akkuman/p/12371838.html
Copyright © 2020-2023  润新知