go服务通过mediainfo获取媒体信息(图片、音/视频)

一、安装mediainfo

文档地址

二、go 程序

package shellservice

import (
    "bytes"
    "encoding/json"
    "errors"
    "fmt"
    "log" //todo 需要替换为自己的日志库
    "math"
    "os/exec"
    "context"
    "strconv"
    "time"
)

func ShellExec(ctx context.Context, cmd string, timeout time.Duration) ([]byte, error) {
    if timeout < 1 {
        timeout = 600*time.Second //默认十分钟后超时取消
    }
    cctx, cancel := context.WithTimeout(context.Background(), timeout)
    defer cancel()

    process := exec.CommandContext(cctx, "/bin/bash", "-c", cmd)
    var b bytes.Buffer
    process.Stdout = &b
    process.Stderr = &b
    err := process.Run()
    if err != nil {
        log.InfoWithCtx(ctx, "ShellExec exec.Command err:%s, out:%s", err, string(b.Bytes()))
        return nil, err
    }
    return b.Bytes(), nil
}

type MediaInfoResp struct {
    VideoMeta *VideoMeta `json:"video_meta"`
    ImageMeta *ImageMeta `json:"image_meta"`
    FileMeta *FileMeta `json:"file_meta"`
}

type ImageMeta struct {
    Width  int `json:"width"`
    Height int `json:"height"`
}

type FileMeta struct {
    FileSize int64 `json:"file_size"`
    FileExt string `json:"file_ext"`
}

type VideoMeta struct {
    Duration float64 `json:"duration"`
}

type MediaInfo struct {
    Media *MediaItem `json:"media"`
}

type MediaItem struct {
    Track []map[string]interface{} `json:"track"`
}

//cmd := fmt.Sprintf(`ffprobe -v quiet -print_format json=compact=1 -show_format -show_streams -i "%s"`, param.FileUrl) func MediaInfoTask(ctx context.Context, fileUri
string) (*MediaInfoResp, error) { cmd := fmt.Sprintf(`mediainfo --output="JSON" "%s"`, fileUri) body, err := ShellExec(ctx, cmd, 0) if err != nil { errMsg := fmt.Sprintf(`{"code":"98", "msg":"Process exception, info:%v"}`, err.Error()) return nil, errors.New(errMsg) } log.InfoWithCtx(ctx, "mediaInfoTask info: %s", string(body)) info := &MediaInfo{} err = json.Unmarshal(body, info) if err != nil { errMsg := fmt.Sprintf(`{"code":"98", "msg":"Process exception, info:%v"}`, err.Error()) return nil, errors.New(errMsg) } if info.Media == nil || len(info.Media.Track) < 1 { return nil, errors.New(`{"code":"98", "msg":"Process exception, mediainfo is nil"}`) } result := &MediaInfoResp{VideoMeta: &VideoMeta{}} for _, mi := range info.Media.Track { mediaType, ok := mi["@type"] if !ok { continue } var duration float64 mType, ok := mediaType.(string) if !ok { continue } var width, height int if mType == "Video" { if _, ok := mi["Duration"]; ok { duration, _ = strconv.ParseFloat(mi["Duration"].(string), 64) duration = duration * 1000 //转成毫秒 duration = math.Floor(duration) } result.VideoMeta = &VideoMeta{ Duration: duration, } } else if mType == "Image" { if _, ok := mi["Width"]; ok { width, _ = strconv.Atoi(mi["Width"].(string)) } if _, ok := mi["Height"]; ok { height, _ = strconv.Atoi(mi["Height"].(string)) } result.ImageMeta = &ImageMeta{ Width: width, Height: height, } } else if mType == "General" { var fileSize int64 var fileExt string if _, ok := mi["FileSize"]; ok { fileSize, _ = strconv.ParseInt(mi["FileSize"].(string), 10, 64) } if _, ok := mi["FileExtension"]; ok { fileExt = mi["FileExtension"].(string) } result.FileMeta = &FileMeta{ FileSize: fileSize, FileExt: fileExt, } } } return result, nil }

 

posted @ 2025-06-04 20:25  划水的猫  阅读(33)  评论(0)    收藏  举报