diff --git a/ffmpeg/ffmpeg.go b/ffmpeg/ffmpeg.go index 6328104..c235a7b 100644 --- a/ffmpeg/ffmpeg.go +++ b/ffmpeg/ffmpeg.go @@ -27,8 +27,6 @@ type Transcoder struct { outputOptions [][]string metadata transcoder.Metadata inputPipeReader *io.ReadCloser - outputPipeReader *io.ReadCloser - inputPipeWriter *io.WriteCloser outputPipeWriter *io.WriteCloser commandContext *context.Context } @@ -105,7 +103,7 @@ func (t *Transcoder) Start() (<-chan transcoder.Progress, error) { if t.config.ProgressEnabled && !t.config.Verbose { stderrIn, err = cmd.StderrPipe() if err != nil { - return nil, fmt.Errorf("Failed getting transcoding progress (%s) with args (%s) with error %s", t.config.FfmpegBinPath, args, err) + return nil, fmt.Errorf("failed getting transcoding progress (%s) with args (%s) with error %s", t.config.FfmpegBinPath, args, err) } } @@ -116,7 +114,7 @@ func (t *Transcoder) Start() (<-chan transcoder.Progress, error) { // Start process err = cmd.Start() if err != nil { - return nil, fmt.Errorf("Failed starting transcoding (%s) with args (%s) with error %s", t.config.FfmpegBinPath, args, err) + return nil, fmt.Errorf("failed starting transcoding (%s) with args (%s) with error %s", t.config.FfmpegBinPath, args, err) } if t.config.ProgressEnabled && !t.config.Verbose { @@ -148,20 +146,16 @@ func (t *Transcoder) Output(arg string) transcoder.Transcoder { } // InputPipe ... -func (t *Transcoder) InputPipe(w *io.WriteCloser, r *io.ReadCloser) transcoder.Transcoder { - if &t.input == nil { - t.inputPipeWriter = w - t.inputPipeReader = r - } +func (t *Transcoder) InputPipe(r *io.ReadCloser) transcoder.Transcoder { + t.input = "pipe:" + t.inputPipeReader = r return t } // OutputPipe ... -func (t *Transcoder) OutputPipe(w *io.WriteCloser, r *io.ReadCloser) transcoder.Transcoder { - if &t.output == nil { - t.outputPipeWriter = w - t.outputPipeReader = r - } +func (t *Transcoder) OutputPipe(w *io.WriteCloser) transcoder.Transcoder { + t.output = []string{} + t.outputPipeWriter = w return t } @@ -235,16 +229,14 @@ func (t *Transcoder) GetMetadata() (transcoder.Metadata, error) { var outb, errb bytes.Buffer input := t.input - - if t.inputPipeReader != nil { - input = "pipe:" - } - args := []string{"-i", input, "-print_format", "json", "-show_format", "-show_streams", "-show_error"} cmd := exec.Command(t.config.FfprobeBinPath, args...) cmd.Stdout = &outb cmd.Stderr = &errb + if t.inputPipeReader != nil { + cmd.Stdin = *t.inputPipeReader + } err := cmd.Run() if err != nil { @@ -256,7 +248,6 @@ func (t *Transcoder) GetMetadata() (transcoder.Metadata, error) { if err = json.Unmarshal([]byte(outb.String()), &metadata); err != nil { return nil, err } - t.metadata = metadata return metadata, nil diff --git a/ffmpeg/metadata.go b/ffmpeg/metadata.go index 4e81910..ee2bd63 100644 --- a/ffmpeg/metadata.go +++ b/ffmpeg/metadata.go @@ -15,6 +15,7 @@ type Format struct { NbPrograms int `json:"nb_programs"` FormatName string `json:"format_name"` FormatLongName string `json:"format_long_name"` + StartTime string `json:"start_time"` Duration string `json:"duration"` Size string `json:"size"` BitRate string `json:"bit_rate"` @@ -24,40 +25,64 @@ type Format struct { // Streams ... type Streams struct { - Index int - ID string `json:"id"` - CodecName string `json:"codec_name"` - CodecLongName string `json:"codec_long_name"` - Profile string `json:"profile"` - CodecType string `json:"codec_type"` - CodecTimeBase string `json:"codec_time_base"` - CodecTagString string `json:"codec_tag_string"` - CodecTag string `json:"codec_tag"` - Width int `json:"width"` - Height int `json:"height"` - CodedWidth int `json:"coded_width"` - CodedHeight int `json:"coded_height"` - HasBFrames int `json:"has_b_frames"` - SampleAspectRatio string `json:"sample_aspect_ratio"` - DisplayAspectRatio string `json:"display_aspect_ratio"` - PixFmt string `json:"pix_fmt"` - Level int `json:"level"` - ChromaLocation string `json:"chroma_location"` - Refs int `json:"refs"` - QuarterSample string `json:"quarter_sample"` - DivxPacked string `json:"divx_packed"` - RFrameRrate string `json:"r_frame_rate"` - AvgFrameRate string `json:"avg_frame_rate"` - TimeBase string `json:"time_base"` - DurationTs int `json:"duration_ts"` - Duration string `json:"duration"` - Disposition Disposition `json:"disposition"` - BitRate string `json:"bit_rate"` + Index int `json:"index"` + ID string `json:"id"` + CodecName string `json:"codec_name"` + CodecLongName string `json:"codec_long_name"` + Profile string `json:"profile"` + CodecType string `json:"codec_type"` + CodecTimeBase string `json:"codec_time_base"` + CodecTagString string `json:"codec_tag_string"` + CodecTag string `json:"codec_tag"` + Width int `json:"width,omitempty"` + Height int `json:"height,omitempty"` + CodedWidth int `json:"coded_width,omitempty"` + CodedHeight int `json:"coded_height,omitempty"` + ClosedCaptions int `json:"closed_captions,omitempty"` + FilmGrain int `json:"film_grain,omitempty"` + HasBFrames int `json:"has_b_frames,omitempty"` + SampleAspectRatio string `json:"sample_aspect_ratio,omitempty"` + DisplayAspectRatio string `json:"display_aspect_ratio,omitempty"` + PixFmt string `json:"pix_fmt,omitempty"` + Level int `json:"level,omitempty"` + ColorRange string `json:"color_range,omitempty"` + ColorSpace string `json:"color_space,omitempty"` + ColorTransfer string `json:"color_transfer,omitempty"` + ColorPrimaries string `json:"color_primaries,omitempty"` + ChromaLocation string `json:"chroma_location,omitempty"` + FieldOrder string `json:"field_order,omitempty"` + Refs int `json:"refs,omitempty"` + QuarterSample string `json:"quarter_sample,omitempty"` + DivxPacked string `json:"divx_packed,omitempty"` + IsAvc string `json:"is_avc,omitempty"` + NalLengthSize string `json:"nal_length_size,omitempty"` + RFrameRate string `json:"r_frame_rate"` + AvgFrameRate string `json:"avg_frame_rate"` + TimeBase string `json:"time_base"` + StartPts int `json:"start_pts"` + StartTime string `json:"start_time"` + DurationTs int `json:"duration_ts"` + Duration string `json:"duration"` + BitRate string `json:"bit_rate"` + BitsPerRawSample string `json:"bits_per_raw_sample,omitempty"` + NbFrames int `json:"nb_frames,string,omitempty"` + ExtradataSize int `json:"extradata_size"` + Disposition Disposition `json:"disposition"` + Tags map[string]string `json:"tags,omitempty"` + SampleFmt string `json:"sample_fmt,omitempty"` + SampleRate string `json:"sample_rate,omitempty"` + Channels int `json:"channels,omitempty"` + ChannelLayout string `json:"channel_layout,omitempty"` + BitsPerSample int `json:"bits_per_sample,omitempty"` } // Tags ... type Tags struct { - Encoder string `json:"ENCODER"` + Encoder string `json:"ENCODER"` + MajorBrand string `json:"major_brand"` + MinorVersion string `json:"minor_version"` + CompatibleBrands string `json:"compatible_brands"` + CreationTime string `json:"creation_time"` } // Disposition ... @@ -72,6 +97,13 @@ type Disposition struct { HearingImpaired int `json:"hearing_impaired"` VisualImpaired int `json:"visual_impaired"` CleanEffects int `json:"clean_effects"` + AttachedPic int `json:"attached_pic,omitempty"` + TimedThumbnails int `json:"timed_thumbnails,omitempty"` + Captions int `json:"captions,omitempty"` + Descriptions int `json:"descriptions,omitempty"` + Metadata int `json:"metadata,omitempty"` + Dependent int `json:"dependent,omitempty"` + StillImage int `json:"still_image,omitempty"` } // GetFormat ... @@ -137,202 +169,327 @@ func (f Format) GetTags() transcoder.Tags { return f.Tags } +// GetStartTime ... +func (f Format) GetStartTime() string { + return f.StartTime +} + // GetEncoder ... func (t Tags) GetEncoder() string { return t.Encoder } -//GetIndex ... +// GetIndex ... func (s Streams) GetIndex() int { return s.Index } -//GetID ... +// GetID ... func (s Streams) GetID() string { return s.ID } -//GetCodecName ... +// GetCodecName ... func (s Streams) GetCodecName() string { return s.CodecName } -//GetCodecLongName ... +// GetCodecLongName ... func (s Streams) GetCodecLongName() string { return s.CodecLongName } -//GetProfile ... +// GetProfile ... func (s Streams) GetProfile() string { return s.Profile } -//GetCodecType ... +// GetCodecType ... func (s Streams) GetCodecType() string { return s.CodecType } -//GetCodecTimeBase ... +// GetCodecTimeBase ... func (s Streams) GetCodecTimeBase() string { return s.CodecTimeBase } -//GetCodecTagString ... +// GetCodecTagString ... func (s Streams) GetCodecTagString() string { return s.CodecTagString } -//GetCodecTag ... +// GetCodecTag ... func (s Streams) GetCodecTag() string { return s.CodecTag } -//GetWidth ... +// GetWidth ... func (s Streams) GetWidth() int { return s.Width } -//GetHeight ... +// GetHeight ... func (s Streams) GetHeight() int { return s.Height } -//GetCodedWidth ... +// GetCodedWidth ... func (s Streams) GetCodedWidth() int { return s.CodedWidth } -//GetCodedHeight ... +// GetCodedHeight ... func (s Streams) GetCodedHeight() int { return s.CodedHeight } -//GetHasBFrames ... +// GetHasBFrames ... func (s Streams) GetHasBFrames() int { return s.HasBFrames } -//GetSampleAspectRatio ... +// GetSampleAspectRatio ... func (s Streams) GetSampleAspectRatio() string { return s.SampleAspectRatio } -//GetDisplayAspectRatio ... +// GetDisplayAspectRatio ... func (s Streams) GetDisplayAspectRatio() string { return s.DisplayAspectRatio } -//GetPixFmt ... +// GetPixFmt ... func (s Streams) GetPixFmt() string { return s.PixFmt } -//GetLevel ... +// GetLevel ... func (s Streams) GetLevel() int { return s.Level } -//GetChromaLocation ... +// GetChromaLocation ... func (s Streams) GetChromaLocation() string { return s.ChromaLocation } -//GetRefs ... +// GetRefs ... func (s Streams) GetRefs() int { return s.Refs } -//GetQuarterSample ... +// GetQuarterSample ... func (s Streams) GetQuarterSample() string { return s.QuarterSample } -//GetDivxPacked ... +// GetDivxPacked ... func (s Streams) GetDivxPacked() string { return s.DivxPacked } -//GetRFrameRrate ... -func (s Streams) GetRFrameRrate() string { - return s.RFrameRrate +// GetRFrameRate ... +func (s Streams) GetRFrameRate() string { + return s.RFrameRate } -//GetAvgFrameRate ... +// GetAvgFrameRate ... func (s Streams) GetAvgFrameRate() string { return s.AvgFrameRate } -//GetTimeBase ... +// GetTimeBase ... func (s Streams) GetTimeBase() string { return s.TimeBase } -//GetDurationTs ... +// GetDurationTs ... func (s Streams) GetDurationTs() int { return s.DurationTs } -//GetDuration ... +// GetDuration ... func (s Streams) GetDuration() string { return s.Duration } -//GetDisposition ... +// GetDisposition ... func (s Streams) GetDisposition() transcoder.Disposition { return s.Disposition } -//GetBitRate ... +// GetBitRate ... func (s Streams) GetBitRate() string { return s.BitRate } -//GetDefault ... +// GetBitsPerRawSample ... +func (s Streams) GetBitsPerRawSample() string { + return s.BitsPerRawSample +} + +// GetBitsPerSample ... +func (s Streams) GetBitsPerSample() int { + return s.BitsPerSample +} + +// GetChannelLayout ... +func (s Streams) GetChannelLayout() string { + return s.ChannelLayout +} + +// GetChannels ... +func (s Streams) GetChannels() int { + return s.Channels +} + +// GetClosedCaptions ... +func (s Streams) GetClosedCaptions() int { + return s.ClosedCaptions +} + +// GetExtradataSize ... +func (s Streams) GetExtradataSize() int { + return s.ExtradataSize +} + +// GetFilmGrain ... +func (s Streams) GetFilmGrain() int { + return s.FilmGrain +} + +// GetIsAvc ... +func (s Streams) GetIsAvc() string { + return s.IsAvc +} + +// GetNalLengthSize ... +func (s Streams) GetNalLengthSize() string { + return s.NalLengthSize +} + +// GetNbFrames ... +func (s Streams) GetNbFrames() int { + return s.NbFrames +} + +// GetSampleFmt ... +func (s Streams) GetSampleFmt() string { + return s.SampleFmt +} + +// GetSampleRate ... +func (s Streams) GetSampleRate() string { + return s.SampleRate +} + +// GetStartPts ... +func (s Streams) GetStartPts() int { + return s.StartPts +} + +// GetStartTime ... +func (s Streams) GetStartTime() string { + return s.StartTime +} + +// GetCompatibleBrands ... +func (t Tags) GetCompatibleBrands() string { + return t.CompatibleBrands +} + +// GetCreationTime ... +func (t Tags) GetCreationTime() string { + return t.CreationTime +} + +// GetMajorBrand ... +func (t Tags) GetMajorBrand() string { + return t.MajorBrand +} + +// GetMinorVersion ... +func (t Tags) GetMinorVersion() string { + return t.MinorVersion +} + +// GetDefault ... func (d Disposition) GetDefault() int { return d.Default } -//GetDub ... +// GetDub ... func (d Disposition) GetDub() int { return d.Dub } -//GetOriginal ... +// GetOriginal ... func (d Disposition) GetOriginal() int { return d.Original } -//GetComment ... +// GetComment ... func (d Disposition) GetComment() int { return d.Comment } -//GetLyrics ... +// GetLyrics ... func (d Disposition) GetLyrics() int { return d.Lyrics } -//GetKaraoke ... +// GetKaraoke ... func (d Disposition) GetKaraoke() int { return d.Karaoke } -//GetForced ... +// GetForced ... func (d Disposition) GetForced() int { return d.Forced } -//GetHearingImpaired ... +// GetHearingImpaired ... func (d Disposition) GetHearingImpaired() int { return d.HearingImpaired } -//GetVisualImpaired ... +// GetVisualImpaired ... func (d Disposition) GetVisualImpaired() int { return d.VisualImpaired } -//GetCleanEffects ... +// GetCleanEffects ... func (d Disposition) GetCleanEffects() int { return d.CleanEffects } + +// GetAttachedPic ... +func (d Disposition) GetAttachedPic() int { + return d.AttachedPic +} + +// GetCaptions ... +func (d Disposition) GetCaptions() int { + return d.Captions +} + +// GetDependent ... +func (d Disposition) GetDependent() int { + return d.Dependent +} + +// GetMetadata ... +func (d Disposition) GetMetadata() int { + return d.Metadata +} + +// GetStillImage ... +func (d Disposition) GetStillImage() int { + return d.StillImage +} + +// GetTimedThumbnails ... +func (d Disposition) GetTimedThumbnails() int { + return d.TimedThumbnails +} diff --git a/metadata.go b/metadata.go index d03241d..5999509 100644 --- a/metadata.go +++ b/metadata.go @@ -13,6 +13,7 @@ type Format interface { GetNbPrograms() int GetFormatName() string GetFormatLongName() string + GetStartTime() string GetDuration() string GetSize() string GetBitRate() string @@ -35,6 +36,8 @@ type Streams interface { GetHeight() int GetCodedWidth() int GetCodedHeight() int + GetClosedCaptions() int + GetFilmGrain() int GetHasBFrames() int GetSampleAspectRatio() string GetDisplayAspectRatio() string @@ -44,18 +47,34 @@ type Streams interface { GetRefs() int GetQuarterSample() string GetDivxPacked() string - GetRFrameRrate() string + GetIsAvc() string + GetNalLengthSize() string + GetRFrameRate() string GetAvgFrameRate() string GetTimeBase() string + GetStartPts() int + GetStartTime() string GetDurationTs() int GetDuration() string - GetDisposition() Disposition GetBitRate() string + GetBitsPerRawSample() string + GetNbFrames() int + GetExtradataSize() int + GetDisposition() Disposition + GetSampleFmt() string + GetSampleRate() string + GetChannels() int + GetChannelLayout() string + GetBitsPerSample() int } // Tags ... type Tags interface { GetEncoder() string + GetMajorBrand() string + GetMinorVersion() string + GetCompatibleBrands() string + GetCreationTime() string } // Disposition ... @@ -70,4 +89,10 @@ type Disposition interface { GetHearingImpaired() int GetVisualImpaired() int GetCleanEffects() int + GetAttachedPic() int + GetTimedThumbnails() int + GetCaptions() int + GetMetadata() int + GetDependent() int + GetStillImage() int } diff --git a/transcoder.go b/transcoder.go index f53ca4e..786575c 100644 --- a/transcoder.go +++ b/transcoder.go @@ -9,9 +9,9 @@ import ( type Transcoder interface { Start() (<-chan Progress, error) Input(i string) Transcoder - InputPipe(w *io.WriteCloser, r *io.ReadCloser) Transcoder + InputPipe(r *io.ReadCloser) Transcoder Output(o string) Transcoder - OutputPipe(w *io.WriteCloser, r *io.ReadCloser) Transcoder + OutputPipe(w *io.WriteCloser) Transcoder WithInputOptions(opts Options) Transcoder WithAdditionalInputOptions(opts Options) Transcoder WithOutputOptions(opts Options) Transcoder