Sample code

import (
    "crypto/md5"
    "encoding/json"
    "fmt"
    "io"
    "os"
    "os/exec"
    "runtime"
    "smartcloud/common"
    "smartcloud/log"
    "smartcloud/models"
    "strconv"
    "strings"
    //"time"
    "net/url"
)

type TranscodeServiceController struct {
    TranscodeBaseController
}

type Element struct {
    PlayList    string
    Sn          string
    ChannelName string
    OssType     int
    Country     string
    Ptstr       string
}

const (
    QueueNum       = 100
    TransCodingNum = 10
)

排队数目

var Queue = make(chan Element, QueueNum)
var md5key string = "videotranscode_1232017321"

func init() {
    go Transcoding()
}

func (this *TranscodeServiceController) TransCode() {
    playList := this.GetString("play_list")
    signature := this.GetString("cylansignature")
    sn := this.GetString("sn")
    channel_name := this.GetString("channel_name")
    ossType := this.GetString("oss_type")
    country := this.GetString("country")
    //三个平台都使用一个转码服务器,需要知道是哪个平台调用的,转完码后才知道往哪个Bucket上传
    ptstr := this.GetString("ptstr")
    if playList == "" || signature == "" || sn == "" ||
        channel_name == "" || ossType == "" || country == "" || ptstr == "" {
        this.jsonStandardResult(-1, "参数错误,有参数为空", "")
        return
    }
    ossType_i, _ := strconv.Atoi(ossType)
    var t Element
    t.ChannelName = channel_name
    t.Country = country
    t.OssType = ossType_i
    t.PlayList = playList
    t.Ptstr = ptstr
    t.Sn = sn
    js, _ := json.Marshal(t)
    if md5Sign(string(js), md5key) != signature {
        this.jsonStandardResult(-2, "签名错误", "")
        return
    }
    if len(Queue) < QueueNum {
        Queue <- t
    } else {
        //队列满
        this.jsonStandardResult(-3, "系统忙,请稍后再试!", "")
        return
    }
    this.jsonStandardResult(0, "ok", "")
    return
}

云存储转码服务器数据:

CPU 四核开启 10 个转码服务 每个视频长度 22 分 18 秒(720*1152) 转码后文件每个大小 344M 耗时 2 分 11 秒

var TransChan = make(chan int, TransCodingNum) //同时转码个数
func Transcoding() {
    for {
        TransChan <- 1
        t := <-Queue
        go func() {
            var where int
            if strings.EqualFold(runtime.GOOS, "windows") {
                where = 0
            } else { //linux
                where = 1
            }
            _, _, _, OssApiBucket := common.GetOssApiUploadPara2(t.Ptstr, t.Country, t.OssType, where)
            loclPath := "/mnt/" + OssApiBucket + "/" + t.ChannelName + "/"
            loclPath = strings.Replace(loclPath, "//", "/", -1)
            u, err := url.ParseRequestURI(t.PlayList)
            name := ""
            localFile := ""
            if u != nil {
                name = u.Path[strings.LastIndex(u.Path, "/")+1 : strings.LastIndex(u.Path, ".m3u8")]
                localFile = loclPath + u.Path[strings.LastIndex(u.Path, "/")+1:]
            } else {
                writelog.WriteError("解析播放列表错误,err:%s", err.Error())
                <-TransChan
                return
            }
            localFile = strings.Replace(localFile, "//", "/", -1)
            name = name + ".mp4"
            outPutFile := common.GetCurrentDirectory() + "/" + t.Sn + "_" + name
            outPutFile = strings.Replace(outPutFile, "//", "/", -1)
            _, err = os.Stat(localFile)
            //判断文件是否已经挂载在本地了
            if !os.IsExist(err) { //文件不存在
                //writelog.WriteDebug("文件不在本地")
                _, err = exec.Command("ffmpeg", "-i", t.PlayList, "-vcodec", "copy", "-strict", "-2", "-f", "mp4", outPutFile).Output()
                if err != nil {
                    writelog.WriteError("视屏转码失败,playList:%s,err:%s", t.PlayList, err.Error())
                    //os.Remove(outPutFile)
                    <-TransChan
                    return
                }
                contentDisposition := fmt.Sprintf(`attachment; filename="%s"`, t.Sn+"_"+name)
                err = models.OssApiUploadFileFromLocal(t.OssType, where, t.ChannelName, t.Country, name, outPutFile, t.Ptstr, contentDisposition)
                if err != nil {
                    writelog.WriteError("将转码后的视频上传到OSS出错,err:%s", err.Error())
                    os.Remove(outPutFile)
                    <-TransChan
                    return
                }
            } else { //文件存在
                //writelog.WriteDebug("文件在本地")
                _, err = exec.Command("ffmpeg", "-i", localFile, "-vcodec", "copy", "-strict", "-2", "-f", "mp4", outPutFile).Output()
                if err != nil {
                    writelog.WriteError("视屏转码失败,localFile:%s,err:%s", localFile, err.Error())
                    //os.Remove(outPutFile)
                    <-TransChan
                    return
                }
                dstfile := loclPath + "/" + name
                dstfile = strings.Replace(dstfile, "//", "/", -1)
                _, err = exec.Command("cp", "-f", outPutFile, dstfile).Output()
                if err != nil {
                    writelog.WriteError("将转码后的视频上传到OSS出错,localFile:%s,dstfile:%s,err:%s", localFile, dstfile, err.Error())
                    os.Remove(outPutFile)
                    <-TransChan
                    return
                }
            }
            <-TransChan
            os.Remove(outPutFile) //上传完了,将本地的文件删除
        }()
    }
}

func md5Sign(str, key string) string {
    h := md5.New()
    io.WriteString(h, str)
    io.WriteString(h, key)
    return fmt.Sprintf("%x", h.Sum(nil))
}

results matching ""

    No results matching ""