mirror of
https://github.com/xfrr/goffmpeg.git
synced 2025-10-04 23:52:40 +08:00
Fixing execution model and making compatible with windows
This commit is contained in:
17
README.md
17
README.md
@@ -39,10 +39,11 @@ func main() {
|
|||||||
// Handle error...
|
// Handle error...
|
||||||
|
|
||||||
// Start transcoder process
|
// Start transcoder process
|
||||||
done, err := trans.Run()
|
done := trans.Run()
|
||||||
|
|
||||||
// This channel is used to wait for the process to end
|
// This channel is used to wait for the process to end
|
||||||
<-done
|
err = <-done
|
||||||
|
// Handle error...
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -59,10 +60,10 @@ func main() {
|
|||||||
// Handle error...
|
// Handle error...
|
||||||
|
|
||||||
// Start transcoder process
|
// Start transcoder process
|
||||||
done, err := trans.Run()
|
done := trans.Run()
|
||||||
|
|
||||||
// Returns a channel to get the transcoding progress
|
// Returns a channel to get the transcoding progress
|
||||||
progress, err := trans.Output()
|
progress := trans.Output()
|
||||||
|
|
||||||
// Example of printing transcoding progress
|
// Example of printing transcoding progress
|
||||||
for msg := range progress {
|
for msg := range progress {
|
||||||
@@ -70,7 +71,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This channel is used to wait for the transcoding process to end
|
// This channel is used to wait for the transcoding process to end
|
||||||
<-done
|
err = <-done
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -139,10 +140,10 @@ func main() {
|
|||||||
trans.MediaFile().SetPreset("ultrafast")
|
trans.MediaFile().SetPreset("ultrafast")
|
||||||
|
|
||||||
// Start transcoder process
|
// Start transcoder process
|
||||||
done, err := trans.Run()
|
done := trans.Run()
|
||||||
|
|
||||||
// Returns a channel to get the transcoding progress
|
// Returns a channel to get the transcoding progress
|
||||||
progress, err := trans.Output()
|
progress := trans.Output()
|
||||||
|
|
||||||
// Example of printing transcoding progress
|
// Example of printing transcoding progress
|
||||||
for msg := range progress {
|
for msg := range progress {
|
||||||
@@ -150,7 +151,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This channel is used to wait for the transcoding process to end
|
// This channel is used to wait for the transcoding process to end
|
||||||
<-done
|
err = <-done
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@@ -10,49 +10,33 @@ import (
|
|||||||
type Configuration struct {
|
type Configuration struct {
|
||||||
FfmpegBin string
|
FfmpegBin string
|
||||||
FfprobeBin string
|
FfprobeBin string
|
||||||
ExecCmd string
|
|
||||||
ExecArgs string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Configure() (Configuration, error) {
|
func Configure() (Configuration, error) {
|
||||||
var outFFmpeg bytes.Buffer
|
var outFFmpeg bytes.Buffer
|
||||||
var outProbe bytes.Buffer
|
var outProbe bytes.Buffer
|
||||||
|
|
||||||
execCmd := utils.GetExec()
|
|
||||||
execFFmpegCommand := utils.GetFFmpegExec()
|
execFFmpegCommand := utils.GetFFmpegExec()
|
||||||
execFFprobeCommand := utils.GetFFprobeExec()
|
execFFprobeCommand := utils.GetFFprobeExec()
|
||||||
execArgs := utils.GetExecArgs()
|
|
||||||
|
|
||||||
cmdFFmpeg := exec.Command(execCmd, execArgs, execFFmpegCommand)
|
cmdFFmpeg := exec.Command(execFFmpegCommand[0], execFFmpegCommand[1])
|
||||||
cmdProbe := exec.Command(execCmd, execArgs, execFFprobeCommand)
|
cmdProbe := exec.Command(execFFprobeCommand[0], execFFprobeCommand[1])
|
||||||
|
|
||||||
cmdFFmpeg.Stdout = &outFFmpeg
|
cmdFFmpeg.Stdout = &outFFmpeg
|
||||||
cmdProbe.Stdout = &outProbe
|
cmdProbe.Stdout = &outProbe
|
||||||
|
|
||||||
err := cmdFFmpeg.Start()
|
err := cmdFFmpeg.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Configuration{}, err
|
return Configuration{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = cmdFFmpeg.Process.Wait()
|
err = cmdProbe.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Configuration{}, err
|
return Configuration{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cmdProbe.Start()
|
ffmpeg := strings.Replace(outFFmpeg.String(), utils.LineSeparator(), "", -1)
|
||||||
if err != nil {
|
fprobe := strings.Replace(outProbe.String(), utils.LineSeparator(), "", -1)
|
||||||
return Configuration{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = cmdProbe.Process.Wait()
|
|
||||||
if err != nil {
|
|
||||||
return Configuration{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ffmpeg := strings.Replace(outFFmpeg.String(), "\n", "", -1)
|
|
||||||
fprobe := strings.Replace(outProbe.String(), "\n", "", -1)
|
|
||||||
|
|
||||||
cnf := Configuration{ffmpeg, fprobe, execCmd, execArgs}
|
|
||||||
|
|
||||||
|
cnf := Configuration{ffmpeg, fprobe}
|
||||||
return cnf, nil
|
return cnf, nil
|
||||||
}
|
}
|
||||||
|
228
models/media.go
228
models/media.go
@@ -362,10 +362,10 @@ func (m *Mediafile) Metadata() Metadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** OPTS **/
|
/** OPTS **/
|
||||||
func (m *Mediafile) ToStrCommand() string {
|
func (m *Mediafile) ToStrCommand() []string {
|
||||||
var strCommand string
|
var strCommand []string
|
||||||
|
|
||||||
opts := [] string {
|
opts := []string {
|
||||||
"SeekTimeInput",
|
"SeekTimeInput",
|
||||||
"SeekUsingTsInput",
|
"SeekUsingTsInput",
|
||||||
"NativeFramerateInput",
|
"NativeFramerateInput",
|
||||||
@@ -409,278 +409,276 @@ func (m *Mediafile) ToStrCommand() string {
|
|||||||
if (opt != reflect.Value{}) {
|
if (opt != reflect.Value{}) {
|
||||||
result := opt.Call([]reflect.Value{})
|
result := opt.Call([]reflect.Value{})
|
||||||
|
|
||||||
if result[0].String() != "" {
|
if val, ok := result[0].Interface().([]string); ok {
|
||||||
strCommand += " "
|
strCommand = append(strCommand, val...)
|
||||||
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 []string{"-aspect", fmt.Sprintf("%f", width/height)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.aspect != "" {
|
if m.aspect != "" {
|
||||||
return fmt.Sprintf("-aspect %s", m.aspect)
|
return []string{"-aspect", m.aspect}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainInputPath() string {
|
func (m *Mediafile) ObtainInputPath() []string {
|
||||||
return fmt.Sprintf("-i \"%s\"", m.inputPath)
|
return []string{"-i", m.inputPath}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainNativeFramerateInput() string {
|
func (m *Mediafile) ObtainNativeFramerateInput() []string {
|
||||||
if m.nativeFramerateInput {
|
if m.nativeFramerateInput {
|
||||||
return "-re"
|
return []string{"-re"}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainOutputPath() string {
|
func (m *Mediafile) ObtainOutputPath() []string {
|
||||||
return fmt.Sprintf("\"%s\"", m.outputPath)
|
return []string{m.outputPath}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainVideoCodec() string {
|
func (m *Mediafile) ObtainVideoCodec() []string {
|
||||||
if m.videoCodec != "" {
|
if m.videoCodec != "" {
|
||||||
return fmt.Sprintf("-c:v %s", m.videoCodec)
|
return []string{"-c:v", m.videoCodec}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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 []string{"-r",fmt.Sprintf("%d", m.frameRate)}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainResolution() string {
|
func (m *Mediafile) ObtainResolution() []string {
|
||||||
if m.resolution != "" {
|
if m.resolution != "" {
|
||||||
return fmt.Sprintf("-s %s", m.resolution)
|
return []string{"-s", m.resolution}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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 []string{"-b:v", fmt.Sprintf("%d", m.videoBitRate)}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainAudioCodec() string {
|
func (m *Mediafile) ObtainAudioCodec() []string {
|
||||||
if m.audioCodec != "" {
|
if m.audioCodec != "" {
|
||||||
return fmt.Sprintf("-c:a %s", m.audioCodec)
|
return []string{"-c:a", m.audioCodec}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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 []string{"-b:a", fmt.Sprintf("%d", m.audioBitrate)}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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 []string{"-ac",fmt.Sprintf("%d", m.audioChannels)}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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 []string{"-maxrate",fmt.Sprintf("%dk", m.videoMaxBitRate)}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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 []string{"-minrate",fmt.Sprintf("%dk", m.videoMinBitrate)}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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 []string{"-bufsize",fmt.Sprintf("%dk", m.bufferSize)}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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 []string{"-bt",fmt.Sprintf("%dk", m.videoBitRateTolerance)}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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 []string{"-threads",fmt.Sprintf("%d", m.threads)}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainTarget() string {
|
func (m *Mediafile) ObtainTarget() []string {
|
||||||
if m.target != "" {
|
if m.target != "" {
|
||||||
return fmt.Sprintf("-target %s", m.target)
|
return []string{"-target",m.target}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainDuration() string {
|
func (m *Mediafile) ObtainDuration() []string {
|
||||||
if m.duration != "" {
|
if m.duration != "" {
|
||||||
return fmt.Sprintf("-t %s", m.duration)
|
return []string{"-t",m.duration}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainDurationInput() string {
|
func (m *Mediafile) ObtainDurationInput() []string {
|
||||||
if m.durationInput != "" {
|
if m.durationInput != "" {
|
||||||
return fmt.Sprintf("-t %s", m.durationInput)
|
return []string{"-t",m.durationInput}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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 []string{"-g",fmt.Sprintf("%d", m.keyframeInterval)}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainSeekTime() string {
|
func (m *Mediafile) ObtainSeekTime() []string {
|
||||||
if m.seekTime != "" {
|
if m.seekTime != "" {
|
||||||
return fmt.Sprintf("-ss %s", m.seekTime)
|
return []string{"-ss",m.seekTime}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainSeekTimeInput() string {
|
func (m *Mediafile) ObtainSeekTimeInput() []string {
|
||||||
if m.seekTimeInput != "" {
|
if m.seekTimeInput != "" {
|
||||||
return fmt.Sprintf("-ss %s", m.seekTimeInput)
|
return []string{"-ss",m.seekTimeInput}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainPreset() string {
|
func (m *Mediafile) ObtainPreset() []string {
|
||||||
if m.preset != "" {
|
if m.preset != "" {
|
||||||
return fmt.Sprintf("-preset %s", m.preset)
|
return []string{"-preset",m.preset}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainTune() string {
|
func (m *Mediafile) ObtainTune() []string {
|
||||||
if m.tune != "" {
|
if m.tune != "" {
|
||||||
return fmt.Sprintf("-tune %s", m.tune)
|
return []string{"-tune",m.tune}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainQuality() string {
|
func (m *Mediafile) ObtainQuality() []string {
|
||||||
if m.quality != 0 {
|
if m.quality != 0 {
|
||||||
return fmt.Sprintf("-crf %d", m.quality)
|
return []string{"-crf",fmt.Sprintf("%d", m.quality)}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainVideoProfile() string {
|
func (m *Mediafile) ObtainVideoProfile() []string {
|
||||||
if m.videoProfile != "" {
|
if m.videoProfile != "" {
|
||||||
return fmt.Sprintf("-profile:v %s", m.videoProfile)
|
return []string{"-profile:v",m.videoProfile}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainAudioProfile() string {
|
func (m *Mediafile) ObtainAudioProfile() []string {
|
||||||
if m.audioProfile != "" {
|
if m.audioProfile != "" {
|
||||||
return fmt.Sprintf("-profile:a %s", m.audioProfile)
|
return []string{"-profile:a", m.audioProfile}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainCopyTs() string {
|
func (m *Mediafile) ObtainCopyTs() []string {
|
||||||
if m.copyTs {
|
if m.copyTs {
|
||||||
return "-copyts"
|
return []string{"-copyts"}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainOutputFormat() string {
|
func (m *Mediafile) ObtainOutputFormat() []string {
|
||||||
if m.outputFormat != "" {
|
if m.outputFormat != "" {
|
||||||
return fmt.Sprintf("-f %s", m.outputFormat)
|
return []string{"-f",m.outputFormat}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainMuxDelay() string {
|
func (m *Mediafile) ObtainMuxDelay() []string {
|
||||||
if m.muxDelay != "" {
|
if m.muxDelay != "" {
|
||||||
return fmt.Sprintf("-muxdelay %s", m.muxDelay)
|
return []string{"-muxdelay",m.muxDelay}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainSeekUsingTsInput() string {
|
func (m *Mediafile) ObtainSeekUsingTsInput() []string {
|
||||||
if m.seekUsingTsInput {
|
if m.seekUsingTsInput {
|
||||||
return "-seek_timestamp 1"
|
return []string{"-seek_timestamp", "1"}
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainRtmpLive() string {
|
func (m *Mediafile) ObtainRtmpLive() []string {
|
||||||
if m.rtmpLive != "" {
|
if m.rtmpLive != "" {
|
||||||
return fmt.Sprintf("-rtmp_live %s", m.rtmpLive)
|
return []string{"-rtmp_live",m.rtmpLive}
|
||||||
} else {
|
} else {
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainHlsPlaylistType() string {
|
func (m *Mediafile) ObtainHlsPlaylistType() []string {
|
||||||
if m.hlsPlaylistType != "" {
|
if m.hlsPlaylistType != "" {
|
||||||
return fmt.Sprintf("-hls_playlist_type %s", m.hlsPlaylistType)
|
return []string{"-hls_playlist_type",m.hlsPlaylistType}
|
||||||
} else {
|
} else {
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainInputInitialOffset() string {
|
func (m *Mediafile) ObtainInputInitialOffset() []string {
|
||||||
if m.inputInitialOffset != "" {
|
if m.inputInitialOffset != "" {
|
||||||
return fmt.Sprintf("-itsoffset %s", m.inputInitialOffset)
|
return []string{"-itsoffset",m.inputInitialOffset}
|
||||||
} else {
|
} else {
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainHlsSegmentDuration() string {
|
func (m *Mediafile) ObtainHlsSegmentDuration() []string {
|
||||||
if m.hlsSegmentDuration != 0 {
|
if m.hlsSegmentDuration != 0 {
|
||||||
return fmt.Sprintf("-hls_time %d", m.hlsSegmentDuration)
|
return []string{"-hls_time",fmt.Sprintf("%d", m.hlsSegmentDuration)}
|
||||||
} else {
|
} else {
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mediafile) ObtainStreamIds() string {
|
func (m *Mediafile) ObtainStreamIds() []string {
|
||||||
if m.streamIds != nil && len(m.streamIds) != 0 {
|
if m.streamIds != nil && len(m.streamIds) != 0 {
|
||||||
result := []string{}
|
result := []string{}
|
||||||
for i, val := range m.streamIds {
|
for i, val := range m.streamIds {
|
||||||
result = append(result, fmt.Sprintf("-streamid %d:%s", i, val))
|
result = append(result, []string{"-streamid", fmt.Sprintf("%d:%s", i, val)}...)
|
||||||
}
|
}
|
||||||
return strings.Join(result, " ")
|
return result
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@ package test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"goffmpeg/transcoder"
|
"github.com/xfrr/goffmpeg/transcoder"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInputNotFound(t *testing.T) {
|
func TestInputNotFound(t *testing.T) {
|
||||||
@@ -31,13 +31,12 @@ func TestTranscoding3GP(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
done, err := trans.Run()
|
done := trans.Run()
|
||||||
|
err = <- done
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
<-done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTranscodingAVI(t *testing.T) {
|
func TestTranscodingAVI(t *testing.T) {
|
||||||
@@ -53,13 +52,12 @@ func TestTranscodingAVI(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
done, err := trans.Run()
|
done := trans.Run()
|
||||||
|
err = <- done
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
<-done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTranscodingFLV(t *testing.T) {
|
func TestTranscodingFLV(t *testing.T) {
|
||||||
@@ -75,13 +73,12 @@ func TestTranscodingFLV(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
done, err := trans.Run()
|
done := trans.Run()
|
||||||
|
err = <- done
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
<-done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTranscodingMKV(t *testing.T) {
|
func TestTranscodingMKV(t *testing.T) {
|
||||||
@@ -97,13 +94,12 @@ func TestTranscodingMKV(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
done, err := trans.Run()
|
done := trans.Run()
|
||||||
|
err = <-done
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
<-done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTranscodingMOV(t *testing.T) {
|
func TestTranscodingMOV(t *testing.T) {
|
||||||
@@ -119,13 +115,12 @@ func TestTranscodingMOV(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
done, err := trans.Run()
|
done := trans.Run()
|
||||||
|
err = <-done
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
<-done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTranscodingMPEG(t *testing.T) {
|
func TestTranscodingMPEG(t *testing.T) {
|
||||||
@@ -141,13 +136,12 @@ func TestTranscodingMPEG(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
done, err := trans.Run()
|
done := trans.Run()
|
||||||
|
err = <-done
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
<-done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTranscodingOGG(t *testing.T) {
|
func TestTranscodingOGG(t *testing.T) {
|
||||||
@@ -163,13 +157,12 @@ func TestTranscodingOGG(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
done, err := trans.Run()
|
done := trans.Run()
|
||||||
|
err = <- done
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
<-done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTranscodingWAV(t *testing.T) {
|
func TestTranscodingWAV(t *testing.T) {
|
||||||
@@ -185,13 +178,12 @@ func TestTranscodingWAV(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
done, err := trans.Run()
|
done := trans.Run()
|
||||||
|
err = <- done
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
<-done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTranscodingWEBM(t *testing.T) {
|
func TestTranscodingWEBM(t *testing.T) {
|
||||||
@@ -207,13 +199,12 @@ func TestTranscodingWEBM(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
done, err := trans.Run()
|
done := trans.Run()
|
||||||
|
err = <- done
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
<-done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTranscodingWMV(t *testing.T) {
|
func TestTranscodingWMV(t *testing.T) {
|
||||||
@@ -229,11 +220,10 @@ func TestTranscodingWMV(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
done, err := trans.Run()
|
done := trans.Run()
|
||||||
|
err = <- done
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
<-done
|
|
||||||
}
|
}
|
||||||
|
@@ -1,29 +0,0 @@
|
|||||||
package transcoder
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os/exec"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Worker struct {
|
|
||||||
Command string
|
|
||||||
Args string
|
|
||||||
Output chan string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cmd *Worker) Run() {
|
|
||||||
out, err := exec.Command(cmd.Command, cmd.Args).Output()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Output <- string(out)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Collect(c chan string) {
|
|
||||||
for {
|
|
||||||
msg := <-c
|
|
||||||
fmt.Printf("The command result is %s\n", msg)
|
|
||||||
}
|
|
||||||
}
|
|
@@ -14,16 +14,17 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Transcoder struct {
|
type Transcoder struct {
|
||||||
process *exec.Cmd
|
stdErrPipe io.ReadCloser
|
||||||
mediafile *models.Mediafile
|
mediafile *models.Mediafile
|
||||||
configuration ffmpeg.Configuration
|
configuration ffmpeg.Configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transcoder) SetProccess(v *exec.Cmd) {
|
func (t *Transcoder) SetProcessStderrPipe(v io.ReadCloser) {
|
||||||
t.process = v
|
t.stdErrPipe = v
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transcoder) SetMediaFile(v *models.Mediafile) {
|
func (t *Transcoder) SetMediaFile(v *models.Mediafile) {
|
||||||
@@ -36,10 +37,6 @@ func (t *Transcoder) SetConfiguration(v ffmpeg.Configuration) {
|
|||||||
|
|
||||||
/*** GETTERS ***/
|
/*** GETTERS ***/
|
||||||
|
|
||||||
func (t Transcoder) Process() *exec.Cmd {
|
|
||||||
return t.process
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t Transcoder) MediaFile() *models.Mediafile {
|
func (t Transcoder) MediaFile() *models.Mediafile {
|
||||||
return t.mediafile
|
return t.mediafile
|
||||||
}
|
}
|
||||||
@@ -52,17 +49,10 @@ 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
|
|
||||||
|
|
||||||
rcommand = fmt.Sprintf("%s -y ", t.configuration.FfmpegBin)
|
|
||||||
|
|
||||||
media := t.mediafile
|
media := t.mediafile
|
||||||
|
rcommand := append([]string{"-y"}, media.ToStrCommand()...)
|
||||||
rcommand += media.ToStrCommand()
|
|
||||||
|
|
||||||
return rcommand
|
return rcommand
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** FUNCTIONS ***/
|
/*** FUNCTIONS ***/
|
||||||
@@ -84,25 +74,16 @@ func (t *Transcoder) Initialize(inputPath string, outputPath string) (error) {
|
|||||||
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 := []string{"-i", inputPath, "-print_format", "json", "-show_format", "-show_streams", "-show_error"}
|
||||||
|
|
||||||
cmd := exec.Command(configuration.ExecCmd, configuration.ExecArgs, command)
|
cmd := exec.Command(configuration.FfprobeBin, 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.Run()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("Failed FFPROBE (%s) with %s, message %s", command, err, out.String())
|
||||||
}
|
|
||||||
|
|
||||||
_, err = cmd.Process.Wait()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var Metadata models.Metadata
|
var Metadata models.Metadata
|
||||||
@@ -125,48 +106,55 @@ func (t *Transcoder) Initialize(inputPath string, outputPath string) (error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transcoder) Run() (<-chan bool, error) {
|
func (t *Transcoder) Run() <-chan error {
|
||||||
done := make(chan bool)
|
done := make(chan error)
|
||||||
var err error
|
|
||||||
|
|
||||||
command := t.GetCommand()
|
command := t.GetCommand()
|
||||||
|
|
||||||
fmt.Println("FFmpeg command: " + command)
|
proc := exec.Command(t.configuration.FfmpegBin, command...)
|
||||||
|
|
||||||
proc := exec.Command(t.configuration.ExecCmd, t.configuration.ExecArgs, command)
|
errStream, err := proc.StderrPipe()
|
||||||
|
|
||||||
t.SetProccess(proc)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
err := proc.Start()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
fmt.Println("Progress not available: "+ err.Error())
|
||||||
|
} else {
|
||||||
|
t.SetProcessStderrPipe(errStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
proc.Wait()
|
out := &bytes.Buffer{}
|
||||||
|
proc.Stdout = out
|
||||||
|
|
||||||
done <- true
|
err = proc.Start()
|
||||||
close(done)
|
|
||||||
|
go func(err error, out *bytes.Buffer, errStream io.ReadCloser) {
|
||||||
|
defer func() {
|
||||||
|
if errStream != nil {
|
||||||
|
errStream.Close()
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
|
if err != nil {
|
||||||
|
done <- fmt.Errorf("Failed Start FFMPEG (%s) with %s, message %s", command, err, out.String())
|
||||||
|
close(done)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = proc.Wait()
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Failed Finish FFMPEG (%s) with %s message %s", command, err, out.String())
|
||||||
|
}
|
||||||
|
done <- err
|
||||||
|
close(done)
|
||||||
|
}(err, out, errStream)
|
||||||
|
|
||||||
return done, err
|
return done
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Transcoder) Output() (<-chan models.Progress, error) {
|
func (t Transcoder) Output() <-chan models.Progress {
|
||||||
out := make(chan models.Progress)
|
out := make(chan models.Progress)
|
||||||
var err error
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer close(out)
|
defer close(out)
|
||||||
|
if t.stdErrPipe == nil {
|
||||||
stderr, stderror := t.Process().StderrPipe()
|
|
||||||
if err != nil {
|
|
||||||
err = stderror
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
scanner := bufio.NewScanner(t.stdErrPipe)
|
||||||
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) {
|
||||||
@@ -203,7 +191,7 @@ func (t Transcoder) Output() (<-chan models.Progress, error) {
|
|||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
Progress := new(models.Progress)
|
Progress := new(models.Progress)
|
||||||
line := scanner.Text()
|
line := scanner.Text()
|
||||||
|
// fmt.Println(line)
|
||||||
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, `=`)
|
||||||
@@ -252,11 +240,7 @@ func (t Transcoder) Output() (<-chan models.Progress, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if scerror := scanner.Err(); err != nil {
|
|
||||||
err = scerror
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return out, err
|
return out
|
||||||
}
|
}
|
||||||
|
@@ -22,67 +22,34 @@ func DurToSec(dur string) (sec float64) {
|
|||||||
return secs
|
return secs
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetExec() string {
|
func GetFFmpegExec() []string {
|
||||||
var platform = runtime.GOOS
|
var platform = runtime.GOOS
|
||||||
var command = ""
|
var command = []string{"", "ffmpeg"}
|
||||||
|
|
||||||
switch platform {
|
switch platform {
|
||||||
case "windows":
|
case "windows":
|
||||||
command = "cmd"
|
command[0] = "where"
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
command = "/bin/sh"
|
command[0] = "which"
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return command
|
return command
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetExecArgs() string {
|
func GetFFprobeExec() []string {
|
||||||
var platform = runtime.GOOS
|
var platform = runtime.GOOS
|
||||||
var args = ""
|
var command = []string{"", "ffprobe"}
|
||||||
|
|
||||||
switch platform {
|
switch platform {
|
||||||
case "windows":
|
case "windows":
|
||||||
args = "/C"
|
command[0] = "where"
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
args = "-c"
|
command[0] = "which"
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return args
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetFFmpegExec() string {
|
|
||||||
var platform = runtime.GOOS
|
|
||||||
var command = ""
|
|
||||||
|
|
||||||
switch platform {
|
|
||||||
case "windows":
|
|
||||||
command = "where ffmpeg"
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
command = "which ffmpeg"
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
return command
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetFFprobeExec() string {
|
|
||||||
var platform = runtime.GOOS
|
|
||||||
var command = ""
|
|
||||||
|
|
||||||
switch platform {
|
|
||||||
case "windows":
|
|
||||||
command = "where ffprobe"
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
command = "which ffprobe"
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
return command
|
return command
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,5 +65,11 @@ func CheckFileType(streams []models.Streams) string {
|
|||||||
return "audio"
|
return "audio"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LineSeparator() string {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "windows":
|
||||||
|
return "\r\n"
|
||||||
|
default:
|
||||||
|
return "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user