Added input path to mediafile and seek using TS option for input

This commit is contained in:
Rohit Garg
2018-05-21 10:44:12 +05:30
parent 6ad5399a15
commit ca3027d8b9
3 changed files with 400 additions and 370 deletions

View File

@@ -1,10 +1,10 @@
package models package models
import ( import (
"strings" "strings"
"strconv" "strconv"
"fmt" "fmt"
"reflect" "reflect"
) )
type Mediafile struct { type Mediafile struct {
@@ -24,341 +24,380 @@ type Mediafile struct {
audioChannels int audioChannels int
bufferSize int bufferSize int
threads int threads int
preset string preset string
target string target string
duration string duration string
seekTime string seekTime string
quality int quality int
metadata Metadata metadata Metadata
muxDelay int
seekUsingTsInput bool
inputPath string
} }
/*** SETTERS ***/ /*** SETTERS ***/
func (m *Mediafile) SetAspect(v string) { func (m *Mediafile) SetAspect(v string) {
m.aspect = v m.aspect = v
} }
func (m *Mediafile) SetResolution(v string) { func (m *Mediafile) SetResolution(v string) {
m.resolution = v m.resolution = v
} }
func (m *Mediafile) SetVideoBitRate(v int) { func (m *Mediafile) SetVideoBitRate(v int) {
m.videoBitRate = v m.videoBitRate = v
} }
func (m *Mediafile) SetVideoBitRateTolerance(v int) { func (m *Mediafile) SetVideoBitRateTolerance(v int) {
m.videoBitRateTolerance = v m.videoBitRateTolerance = v
} }
func (m *Mediafile) SetVideoMaxBitrate(v int) { func (m *Mediafile) SetVideoMaxBitrate(v int) {
m.videoMaxBitRate = v m.videoMaxBitRate = v
} }
func (m *Mediafile) SetVideoMinBitRate(v int) { func (m *Mediafile) SetVideoMinBitRate(v int) {
m.videoMinBitrate = v m.videoMinBitrate = v
} }
func (m *Mediafile) SetVideoCodec(v string) { func (m *Mediafile) SetVideoCodec(v string) {
m.videoCodec = v m.videoCodec = v
} }
func (m *Mediafile) SetFrameRate(v int) { func (m *Mediafile) SetFrameRate(v int) {
m.frameRate = v m.frameRate = v
} }
func (m *Mediafile) SetMaxKeyFrame(v int) { func (m *Mediafile) SetMaxKeyFrame(v int) {
m.maxKeyframe = v m.maxKeyframe = v
} }
func (m *Mediafile) SetMinKeyFrame(v int) { func (m *Mediafile) SetMinKeyFrame(v int) {
m.minKeyframe = v m.minKeyframe = v
} }
func (m *Mediafile) SetKeyframeInterval(v int) { func (m *Mediafile) SetKeyframeInterval(v int) {
m.keyframeInterval = v m.keyframeInterval = v
} }
func (m *Mediafile) SetAudioCodec(v string) { func (m *Mediafile) SetAudioCodec(v string) {
m.audioCodec = v m.audioCodec = v
} }
func (m *Mediafile) SetAudioBitRate(v int) { func (m *Mediafile) SetAudioBitRate(v int) {
m.audioBitrate = v m.audioBitrate = v
} }
func (m *Mediafile) SetAudioChannels(v int) { func (m *Mediafile) SetAudioChannels(v int) {
m.audioChannels = v m.audioChannels = v
} }
func (m *Mediafile) SetBufferSize(v int) { func (m *Mediafile) SetBufferSize(v int) {
m.bufferSize = v m.bufferSize = v
} }
func (m *Mediafile) SetThreads(v int) { func (m *Mediafile) SetThreads(v int) {
m.threads = v m.threads = v
} }
func (m *Mediafile) SetPreset(v string) { func (m *Mediafile) SetPreset(v string) {
m.preset = v m.preset = v
} }
func (m *Mediafile) SetDuration(v string) { func (m *Mediafile) SetDuration(v string) {
m.duration = v m.duration = v
} }
func (m *Mediafile) SetSeekTime(v string) { func (m *Mediafile) SetSeekTime(v string) {
m.seekTime = v m.seekTime = v
} }
func (m *Mediafile) SetQuality(v int) { func (m *Mediafile) SetQuality(v int) {
m.quality = v m.quality = v
}
func (m *Mediafile) SetSeekUsingTsInput(val bool) {
m.seekUsingTsInput = val
}
func (m *Mediafile) SetInputPath(val string) {
m.inputPath = val
} }
func (m *Mediafile) SetMetadata(v Metadata) { func (m *Mediafile) SetMetadata(v Metadata) {
m.metadata = v m.metadata = v
} }
/*** GETTERS ***/ /*** GETTERS ***/
func (m Mediafile) Aspect() string { func (m Mediafile) Aspect() string {
return m.aspect return m.aspect
} }
func (m Mediafile) Resolution() string { func (m Mediafile) Resolution() string {
return m.resolution return m.resolution
} }
func (m Mediafile) VideoBitrate() int { func (m Mediafile) VideoBitrate() int {
return m.videoBitRate return m.videoBitRate
} }
func (m Mediafile) VideoBitRateTolerance() int { func (m Mediafile) VideoBitRateTolerance() int {
return m.videoBitRateTolerance return m.videoBitRateTolerance
} }
func (m Mediafile) VideoMaxBitRate() int { func (m Mediafile) VideoMaxBitRate() int {
return m.videoMaxBitRate return m.videoMaxBitRate
} }
func (m Mediafile) VideoMinBitRate() int { func (m Mediafile) VideoMinBitRate() int {
return m.videoMinBitrate return m.videoMinBitrate
} }
func (m Mediafile) VideoCodec() string { func (m Mediafile) VideoCodec() string {
return m.videoCodec return m.videoCodec
} }
func (m Mediafile) FrameRate() int { func (m Mediafile) FrameRate() int {
return m.frameRate return m.frameRate
} }
func (m Mediafile) MaxKeyFrame() int { func (m Mediafile) MaxKeyFrame() int {
return m.maxKeyframe return m.maxKeyframe
} }
func (m Mediafile) MinKeyFrame() int { func (m Mediafile) MinKeyFrame() int {
return m.minKeyframe return m.minKeyframe
} }
func (m Mediafile) KeyFrameInterval() int { func (m Mediafile) KeyFrameInterval() int {
return m.keyframeInterval return m.keyframeInterval
} }
func (m Mediafile) AudioCodec() string { func (m Mediafile) AudioCodec() string {
return m.audioCodec return m.audioCodec
} }
func (m Mediafile) AudioBitrate() int { func (m Mediafile) AudioBitrate() int {
return m.audioBitrate return m.audioBitrate
} }
func (m Mediafile) AudioChannels() int { func (m Mediafile) AudioChannels() int {
return m.audioChannels return m.audioChannels
} }
func (m Mediafile) BufferSize() int { func (m Mediafile) BufferSize() int {
return m.bufferSize return m.bufferSize
} }
func (m Mediafile) Threads() int { func (m Mediafile) Threads() int {
return m.threads return m.threads
} }
func (m Mediafile) Target() string { func (m Mediafile) Target() string {
return m.target return m.target
} }
func (m Mediafile) Duration() string { func (m Mediafile) Duration() string {
return m.duration return m.duration
} }
func (m Mediafile) SeekTime() string { func (m Mediafile) SeekTime() string {
return m.seekTime return m.seekTime
} }
func (m Mediafile) Quality() int { func (m Mediafile) Quality() int {
return m.quality return m.quality
}
func (m Mediafile) MuxDelay() int {
return m.muxDelay
}
func (m Mediafile) SeekUsingTsInput() bool {
return m.seekUsingTsInput
}
func (m Mediafile) InputPath() string {
return m.inputPath
} }
func (m Mediafile) Metadata() Metadata { func (m Mediafile) Metadata() Metadata {
return m.metadata return m.metadata
} }
/** OPTS **/ /** OPTS **/
func (m Mediafile) ToStrCommand() string { func (m Mediafile) ToStrCommand() string {
var strCommand string var strCommand string
opts := []string{"Aspect", "VideoCodec", "FrameRate", "Resolution", "VideoBitRate", "VideoBitRateTolerance", "AudioCodec", "AudioBitRate", "AudioChannels", "VideoMaxBitRate", "VideoMinBitRate", "BufferSize", "Threads", "Preset", "Target", "Duration", "KeyframeInterval", "SeekTime", "Quality"} opts := []string{"SeekUsingTsInput", "InputPath", "Aspect", "VideoCodec", "FrameRate", "Resolution", "VideoBitRate", "VideoBitRateTolerance", "AudioCodec", "AudioBitRate", "AudioChannels", "VideoMaxBitRate", "VideoMinBitRate", "BufferSize", "Threads", "Preset", "Target", "Duration", "KeyframeInterval", "SeekTime", "Quality", "ObtainMuxDelay"}
for _, name := range opts { for _, name := range opts {
opt := reflect.ValueOf(&m).MethodByName(fmt.Sprintf("Obtain%s", name)) opt := reflect.ValueOf(&m).MethodByName(fmt.Sprintf("Obtain%s", name))
if (opt != reflect.Value{}) { if (opt != reflect.Value{}) {
result := opt.Call([]reflect.Value{}) result := opt.Call([]reflect.Value{})
if result[0].String() != "" { if result[0].String() != "" {
strCommand += " " strCommand += " "
strCommand += result[0].String() strCommand += result[0].String()
} }
} }
} }
return strCommand return strCommand
} }
func (m *Mediafile) ObtainAspect() string { func (m *Mediafile) ObtainAspect() string {
// Set aspect // Set aspect
if m.resolution != "" { if m.resolution != "" {
resolution := strings.Split(m.resolution, "x") resolution := strings.Split(m.resolution, "x")
if len(resolution) != 0 { if len(resolution) != 0 {
width, _ := strconv.ParseFloat(resolution[0], 64) width, _ := strconv.ParseFloat(resolution[0], 64)
height, _ := strconv.ParseFloat(resolution[1], 64) height, _ := strconv.ParseFloat(resolution[1], 64)
return fmt.Sprintf("-aspect %f", width/height) return fmt.Sprintf("-aspect %f", width/height)
} }
} }
if m.aspect != "" { if m.aspect != "" {
return fmt.Sprintf("-aspect %s", m.aspect) return fmt.Sprintf("-aspect %s", m.aspect)
} else { } else {
return "" return ""
} }
}
func (m *Mediafile) ObtainInputPath() string {
return fmt.Sprintf("-i \"%s\"", m.inputPath)
} }
func (m *Mediafile) ObtainVideoCodec() string { func (m *Mediafile) ObtainVideoCodec() string {
if m.videoCodec != "" { if m.videoCodec != "" {
return fmt.Sprintf("-vcodec %s", m.videoCodec) return fmt.Sprintf("-vcodec %s", m.videoCodec)
} }
return "" return ""
} }
func (m *Mediafile) ObtainFrameRate() string { func (m *Mediafile) ObtainFrameRate() string {
if m.frameRate != 0 { if m.frameRate != 0 {
return fmt.Sprintf("-r %d", m.frameRate) return fmt.Sprintf("-r %d", m.frameRate)
} }
return "" return ""
} }
func (m *Mediafile) ObtainResolution() string { func (m *Mediafile) ObtainResolution() string {
if m.resolution != "" { if m.resolution != "" {
return fmt.Sprintf("-s %s", m.resolution) return fmt.Sprintf("-s %s", m.resolution)
} }
return "" return ""
} }
func (m *Mediafile) ObtainVideoBitRate() string { func (m *Mediafile) ObtainVideoBitRate() string {
if m.videoBitRate != 0 { if m.videoBitRate != 0 {
return fmt.Sprintf("-b:v %d", m.videoBitRate) return fmt.Sprintf("-b:v %d", m.videoBitRate)
} }
return "" return ""
} }
func (m *Mediafile) ObtainAudioCodec() string { func (m *Mediafile) ObtainAudioCodec() string {
if m.audioCodec != "" { if m.audioCodec != "" {
return fmt.Sprintf("-acodec %s", m.audioCodec) return fmt.Sprintf("-acodec %s", m.audioCodec)
} }
return "" return ""
} }
func (m *Mediafile) ObtainAudioBitRate() string { func (m *Mediafile) ObtainAudioBitRate() string {
if m.audioBitrate != 0 { if m.audioBitrate != 0 {
return fmt.Sprintf("-b:a %d", m.audioBitrate) return fmt.Sprintf("-b:a %d", m.audioBitrate)
} }
return "" return ""
} }
func (m *Mediafile) ObtainAudioChannels() string { func (m *Mediafile) ObtainAudioChannels() string {
if m.audioChannels != 0 { if m.audioChannels != 0 {
return fmt.Sprintf("-ac %d", m.audioChannels) return fmt.Sprintf("-ac %d", m.audioChannels)
} }
return "" return ""
} }
func (m *Mediafile) ObtainVideoMaxBitRate() string { func (m *Mediafile) ObtainVideoMaxBitRate() string {
if m.videoMaxBitRate != 0 { if m.videoMaxBitRate != 0 {
return fmt.Sprintf("-maxrate %dk", m.videoMaxBitRate) return fmt.Sprintf("-maxrate %dk", m.videoMaxBitRate)
} }
return "" return ""
} }
func (m *Mediafile) ObtainVideoMinBitRate() string { func (m *Mediafile) ObtainVideoMinBitRate() string {
if m.videoMinBitrate != 0 { if m.videoMinBitrate != 0 {
return fmt.Sprintf("-minrate %dk", m.videoMinBitrate) return fmt.Sprintf("-minrate %dk", m.videoMinBitrate)
} }
return "" return ""
} }
func (m *Mediafile) ObtainBufferSize() string { func (m *Mediafile) ObtainBufferSize() string {
if m.bufferSize != 0 { if m.bufferSize != 0 {
return fmt.Sprintf("-bufsize %dk", m.bufferSize) return fmt.Sprintf("-bufsize %dk", m.bufferSize)
} }
return "" return ""
} }
func (m *Mediafile) ObtainVideoBitRateTolerance() string { func (m *Mediafile) ObtainVideoBitRateTolerance() string {
if m.videoBitRateTolerance != 0 { if m.videoBitRateTolerance != 0 {
return fmt.Sprintf("-bt %dk", m.videoBitRateTolerance) return fmt.Sprintf("-bt %dk", m.videoBitRateTolerance)
} }
return "" return ""
} }
func (m *Mediafile) ObtainThreads() string { func (m *Mediafile) ObtainThreads() string {
if m.threads != 0 { if m.threads != 0 {
return fmt.Sprintf("-threads %d", m.threads) return fmt.Sprintf("-threads %d", m.threads)
} }
return "" return ""
} }
func (m *Mediafile) ObtainTarget() string { func (m *Mediafile) ObtainTarget() string {
if m.target != "" { if m.target != "" {
return fmt.Sprintf("-target %s", m.target) return fmt.Sprintf("-target %s", m.target)
} }
return "" return ""
} }
func (m *Mediafile) ObtainDuration() string { func (m *Mediafile) ObtainDuration() string {
if m.duration != "" { if m.duration != "" {
return fmt.Sprintf("-t %s", m.duration) return fmt.Sprintf("-t %s", m.duration)
} }
return "" return ""
} }
func (m *Mediafile) ObtainKeyframeInterval() string { func (m *Mediafile) ObtainKeyframeInterval() string {
if m.keyframeInterval != 0 { if m.keyframeInterval != 0 {
return fmt.Sprintf("-g %d", m.keyframeInterval) return fmt.Sprintf("-g %d", m.keyframeInterval)
} }
return "" return ""
} }
func (m *Mediafile) ObtainSeekTime() string { func (m *Mediafile) ObtainSeekTime() string {
if m.seekTime != "" { if m.seekTime != "" {
return fmt.Sprintf("-ss %s", m.seekTime) return fmt.Sprintf("-ss %s", m.seekTime)
} }
return "" return ""
} }
func (m *Mediafile) ObtainPreset() string { func (m *Mediafile) ObtainPreset() string {
if m.preset != "" { if m.preset != "" {
return fmt.Sprintf("-preset %s", m.preset) return fmt.Sprintf("-preset %s", m.preset)
} }
return "" return ""
}
func (m *Mediafile) ObtainMuxDelay() string {
return fmt.Sprintf("-muxdelay %d", m.muxDelay)
}
func (m *Mediafile) ObtainSeekUsingTsInput() string {
if m.seekUsingTsInput {
return "-seek_timestamp 1"
} else {
return ""
}
} }

View File

@@ -1,79 +1,79 @@
package models package models
type Ffmpeg struct { type Ffmpeg struct {
FfmpegBinPath string FfmpegBinPath string
FfprobeBinPath string FfprobeBinPath string
} }
type Metadata struct { type Metadata struct {
Streams []Streams `json:"streams"` Streams []Streams `json:"streams"`
Format Format `json:"format"` Format Format `json:"format"`
} }
type Streams struct { type Streams struct {
Index int Index int
CodecName string `json:"codec_name"` CodecName string `json:"codec_name"`
CodecLongName string `json:"codec_long_name"` CodecLongName string `json:"codec_long_name"`
Profile string `json:"profile"` Profile string `json:"profile"`
CodecType string `json:"codec_type"` CodecType string `json:"codec_type"`
CodecTimeBase string `json:"codec_time_base"` CodecTimeBase string `json:"codec_time_base"`
CodecTagString string `json:"codec_tag_string"` CodecTagString string `json:"codec_tag_string"`
CodecTag string `json:"codec_tag"` CodecTag string `json:"codec_tag"`
Width int `json:"width"` Width int `json:"width"`
Height int `json:"height"` Height int `json:"height"`
CodedWidth int `json:"coded_width"` CodedWidth int `json:"coded_width"`
CodedHeight int `json:"coded_height"` CodedHeight int `json:"coded_height"`
HasBFrames int `json:"has_b_frames"` HasBFrames int `json:"has_b_frames"`
SampleAspectRatio string `json:"sample_aspect_ratio"` SampleAspectRatio string `json:"sample_aspect_ratio"`
DisplayAspectRatio string `json:"display_aspect_ratio"` DisplayAspectRatio string `json:"display_aspect_ratio"`
PixFmt string `json:"pix_fmt"` PixFmt string `json:"pix_fmt"`
Level int `json:"level"` Level int `json:"level"`
ChromaLocation string `json:"chroma_location"` ChromaLocation string `json:"chroma_location"`
Refs int `json:"refs"` Refs int `json:"refs"`
QuarterSample string `json:"quarter_sample"` QuarterSample string `json:"quarter_sample"`
DivxPacked string `json:"divx_packed"` DivxPacked string `json:"divx_packed"`
RFrameRrate string `json:"r_frame_rate"` RFrameRrate string `json:"r_frame_rate"`
AvgFrameRate string `json:"avg_frame_rate"` AvgFrameRate string `json:"avg_frame_rate"`
TimeBase string `json:"time_base"` TimeBase string `json:"time_base"`
DurationTs int `json:"duration_ts"` DurationTs int `json:"duration_ts"`
Duration string `json:"duration"` Duration string `json:"duration"`
Disposition Disposition `json:"disposition"` Disposition Disposition `json:"disposition"`
BitRate string `json:"bit_rate"` BitRate string `json:"bit_rate"`
} }
type Disposition struct { type Disposition struct {
Default int `json:"default"` Default int `json:"default"`
Dub int `json:"dub"` Dub int `json:"dub"`
Original int `json:"original"` Original int `json:"original"`
Comment int `json:"comment"` Comment int `json:"comment"`
Lyrics int `json:"lyrics"` Lyrics int `json:"lyrics"`
Karaoke int `json:"karaoke"` Karaoke int `json:"karaoke"`
Forced int `json:"forced"` Forced int `json:"forced"`
HearingImpaired int `json:"hearing_impaired"` HearingImpaired int `json:"hearing_impaired"`
VisualImpaired int `json:"visual_impaired"` VisualImpaired int `json:"visual_impaired"`
CleanEffects int `json:"clean_effects"` CleanEffects int `json:"clean_effects"`
} }
type Format struct { type Format struct {
Filename string Filename string
NbStreams int `json:"nb_streams"` NbStreams int `json:"nb_streams"`
NbPrograms int `json:"nb_programs"` NbPrograms int `json:"nb_programs"`
FormatName string `json:"format_name"` FormatName string `json:"format_name"`
FormatLongName string `json:"format_long_name"` FormatLongName string `json:"format_long_name"`
Duration string `json:"duration"` Duration string `json:"duration"`
Size string `json:"size"` Size string `json:"size"`
BitRate string `json:"bit_rate"` BitRate string `json:"bit_rate"`
ProbeScore int `json:"probe_score"` ProbeScore int `json:"probe_score"`
Tags Tags `json:"tags"` Tags Tags `json:"tags"`
} }
type Progress struct { type Progress struct {
FramesProcessed string FramesProcessed string
CurrentTime string CurrentTime string
CurrentBitrate string CurrentBitrate string
Progress float64 Progress float64
} }
type Tags struct { type Tags struct {
Encoder string `json:"ENCODER"` Encoder string `json:"ENCODER"`
} }

View File

@@ -1,87 +1,78 @@
package transcoder package transcoder
import ( import (
"errors" "errors"
"os" "os"
"goffmpeg/models" "goffmpeg/models"
"os/exec" "os/exec"
"fmt" "fmt"
"goffmpeg/ffmpeg" "goffmpeg/ffmpeg"
"goffmpeg/utils" "goffmpeg/utils"
"bytes" "bytes"
"encoding/json" "encoding/json"
"bufio" "bufio"
"strings" "strings"
"regexp" "regexp"
"strconv" "strconv"
) )
type Transcoder struct { type Transcoder struct {
process *exec.Cmd process *exec.Cmd
inputPath string outputPath string
outputPath string mediafile *models.Mediafile
mediafile *models.Mediafile configuration ffmpeg.Configuration
configuration ffmpeg.Configuration
} }
func (t *Transcoder) SetProccess(v *exec.Cmd) { func (t *Transcoder) SetProccess(v *exec.Cmd) {
t.process = v t.process = v
}
func (t *Transcoder) SetInputPath(v string) {
t.inputPath = v
} }
func (t *Transcoder) SetOutputPath(v string) { func (t *Transcoder) SetOutputPath(v string) {
t.outputPath = v t.outputPath = v
} }
func (t *Transcoder) SetMediaFile(v *models.Mediafile) { func (t *Transcoder) SetMediaFile(v *models.Mediafile) {
t.mediafile = v t.mediafile = v
} }
func (t *Transcoder) SetConfiguration(v ffmpeg.Configuration) { func (t *Transcoder) SetConfiguration(v ffmpeg.Configuration) {
t.configuration = v t.configuration = v
} }
/*** GETTERS ***/ /*** GETTERS ***/
func (t Transcoder) Process() *exec.Cmd { func (t Transcoder) Process() *exec.Cmd {
return t.process return t.process
}
func (t Transcoder) InputPath() string {
return t.inputPath
} }
func (t Transcoder) OutputPath() string { func (t Transcoder) OutputPath() string {
return t.outputPath return t.outputPath
} }
func (t Transcoder) MediaFile() *models.Mediafile { func (t Transcoder) MediaFile() *models.Mediafile {
return t.mediafile return t.mediafile
} }
func (t Transcoder) FFmpegExec() string { func (t Transcoder) FFmpegExec() string {
return t.configuration.FfmpegBin return t.configuration.FfmpegBin
} }
func (t Transcoder) FFprobeExec() string { func (t Transcoder) FFprobeExec() string {
return t.configuration.FfprobeBin return t.configuration.FfprobeBin
} }
func (t Transcoder) GetCommand() string { func (t Transcoder) GetCommand() string {
var rcommand string var rcommand string
rcommand = fmt.Sprintf("%s -y -i \"%s\" ", t.configuration.FfmpegBin, t.inputPath) rcommand = fmt.Sprintf("%s -y ", t.configuration.FfmpegBin)
media := t.mediafile media := t.mediafile
rcommand += media.ToStrCommand() rcommand += media.ToStrCommand()
rcommand += " \"" + t.outputPath + "\"" rcommand += " \"" + t.outputPath + "\""
return rcommand return rcommand
} }
@@ -89,194 +80,194 @@ func (t Transcoder) GetCommand() string {
func (t *Transcoder) Initialize(inputPath string, outputPath string) (error) { func (t *Transcoder) Initialize(inputPath string, outputPath string) (error) {
configuration, err := ffmpeg.Configure() configuration, err := ffmpeg.Configure()
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return err return err
} }
if inputPath == "" { if inputPath == "" {
return errors.New("error: transcoder.Initialize -> inputPath missing") return errors.New("error: transcoder.Initialize -> inputPath missing")
} }
_, err = os.Stat(inputPath) _, err = os.Stat(inputPath)
if os.IsNotExist(err) { if os.IsNotExist(err) {
return errors.New("error: transcoder.Initialize -> input file not found") return errors.New("error: transcoder.Initialize -> input file not found")
} }
command := fmt.Sprintf("%s -i \"%s\" -print_format json -show_format -show_streams -show_error", configuration.FfprobeBin, inputPath) command := fmt.Sprintf("%s -i \"%s\" -print_format json -show_format -show_streams -show_error", configuration.FfprobeBin, inputPath)
cmd := exec.Command(configuration.ExecCmd, configuration.ExecArgs, command) cmd := exec.Command(configuration.ExecCmd, configuration.ExecArgs, command)
fmt.Println("FFprobe command: " + command) fmt.Println("FFprobe command: " + command)
var out bytes.Buffer var out bytes.Buffer
cmd.Stdout = &out cmd.Stdout = &out
err = cmd.Start() err = cmd.Start()
if err != nil { if err != nil {
return err return err
} }
_, err = cmd.Process.Wait() _, err = cmd.Process.Wait()
if err != nil { if err != nil {
return err return err
} }
var Metadata models.Metadata var Metadata models.Metadata
if err = json.Unmarshal([]byte(out.String()), &Metadata); err != nil { if err = json.Unmarshal([]byte(out.String()), &Metadata); err != nil {
return err return err
} }
// Set new Mediafile // Set new Mediafile
MediaFile := new(models.Mediafile) MediaFile := new(models.Mediafile)
MediaFile.SetMetadata(Metadata) MediaFile.SetMetadata(Metadata)
MediaFile.SetInputPath(inputPath)
// Set transcoder configuration // Set transcoder configuration
t.SetInputPath(inputPath)
t.SetOutputPath(outputPath) t.SetOutputPath(outputPath)
t.SetMediaFile(MediaFile) t.SetMediaFile(MediaFile)
t.SetConfiguration(configuration) t.SetConfiguration(configuration)
return nil return nil
} }
func (t *Transcoder) Run() (<-chan bool, error) { func (t *Transcoder) Run() (<-chan bool, error) {
done := make(chan bool) done := make(chan bool)
var err error var err error
command := t.GetCommand() command := t.GetCommand()
fmt.Println("FFmpeg command: " + command) fmt.Println("FFmpeg command: " + command)
proc := exec.Command(t.configuration.ExecCmd, t.configuration.ExecArgs, command) proc := exec.Command(t.configuration.ExecCmd, t.configuration.ExecArgs, command)
t.SetProccess(proc) t.SetProccess(proc)
go func() { go func() {
err := proc.Start() err := proc.Start()
if err != nil { if err != nil {
return return
} }
proc.Wait() proc.Wait()
done <- true done <- true
close(done) close(done)
}() }()
return done, err return done, err
} }
func (t Transcoder) Output() (<-chan models.Progress, error) { func (t Transcoder) Output() (<-chan models.Progress, error) {
out := make(chan models.Progress) out := make(chan models.Progress)
var err error var err error
go func() { go func() {
defer close(out) defer close(out)
stderr, stderror := t.Process().StderrPipe() stderr, stderror := t.Process().StderrPipe()
if err != nil { if err != nil {
err = stderror err = stderror
return return
} }
scanner := bufio.NewScanner(stderr) scanner := bufio.NewScanner(stderr)
filetype := utils.CheckFileType(t.MediaFile().Metadata().Streams) filetype := utils.CheckFileType(t.MediaFile().Metadata().Streams)
split := func(data []byte, atEOF bool) (advance int, token []byte, spliterror error) { split := func(data []byte, atEOF bool) (advance int, token []byte, spliterror error) {
if atEOF && len(data) == 0 { if atEOF && len(data) == 0 {
return 0, nil, nil return 0, nil, nil
} }
Iframe := strings.Index(string(data), "frame=") Iframe := strings.Index(string(data), "frame=")
if filetype == "video" { if filetype == "video" {
if Iframe > 0 { if Iframe > 0 {
return Iframe + 1, data[Iframe:], nil return Iframe + 1, data[Iframe:], nil
} }
} else { } else {
if i := bytes.IndexByte(data, '\n'); i >= 0 { if i := bytes.IndexByte(data, '\n'); i >= 0 {
// We have a full newline-terminated line. // We have a full newline-terminated line.
return i + 1, data[0:i], nil return i + 1, data[0:i], nil
} }
} }
if atEOF { if atEOF {
return len(data), data, nil return len(data), data, nil
} }
return 0, nil, nil return 0, nil, nil
} }
scanner.Split(split) scanner.Split(split)
buf := make([]byte, 2) buf := make([]byte, 2)
scanner.Buffer(buf, bufio.MaxScanTokenSize) scanner.Buffer(buf, bufio.MaxScanTokenSize)
var lastProgress float64 var lastProgress float64
for scanner.Scan() { for scanner.Scan() {
Progress := new(models.Progress) Progress := new(models.Progress)
line := scanner.Text() line := scanner.Text()
if strings.Contains(line, "time=") && strings.Contains(line, "bitrate=") { if strings.Contains(line, "time=") && strings.Contains(line, "bitrate=") {
var re= regexp.MustCompile(`=\s+`) var re= regexp.MustCompile(`=\s+`)
st := re.ReplaceAllString(line, `=`) st := re.ReplaceAllString(line, `=`)
f := strings.Fields(st) f := strings.Fields(st)
var framesProcessed string var framesProcessed string
var currentTime string var currentTime string
var currentBitrate string var currentBitrate string
for j := 0; j < len(f); j++ { for j := 0; j < len(f); j++ {
field := f[j] field := f[j]
fieldSplit := strings.Split(field, "=") fieldSplit := strings.Split(field, "=")
if len(fieldSplit) > 1 { if len(fieldSplit) > 1 {
fieldname := strings.Split(field, "=")[0] fieldname := strings.Split(field, "=")[0]
fieldvalue := strings.Split(field, "=")[1] fieldvalue := strings.Split(field, "=")[1]
if fieldname == "frame" { if fieldname == "frame" {
framesProcessed = fieldvalue framesProcessed = fieldvalue
} }
if fieldname == "time" { if fieldname == "time" {
currentTime = fieldvalue currentTime = fieldvalue
} }
if fieldname == "bitrate" { if fieldname == "bitrate" {
currentBitrate = fieldvalue currentBitrate = fieldvalue
} }
} }
} }
timesec := utils.DurToSec(currentTime) timesec := utils.DurToSec(currentTime)
dursec, _ := strconv.ParseFloat(t.MediaFile().Metadata().Format.Duration, 64) dursec, _ := strconv.ParseFloat(t.MediaFile().Metadata().Format.Duration, 64)
// Progress calculation // Progress calculation
progress := (timesec * 100) / dursec progress := (timesec * 100) / dursec
Progress.Progress = progress Progress.Progress = progress
Progress.CurrentBitrate = currentBitrate Progress.CurrentBitrate = currentBitrate
Progress.FramesProcessed = framesProcessed Progress.FramesProcessed = framesProcessed
Progress.CurrentTime = currentTime Progress.CurrentTime = currentTime
if progress != lastProgress { if progress != lastProgress {
lastProgress = progress lastProgress = progress
out <- *Progress out <- *Progress
} }
} }
} }
if scerror := scanner.Err(); err != nil { if scerror := scanner.Err(); err != nil {
err = scerror err = scerror
} }
}() }()
return out, err return out, err
} }