@@ -46,6 +46,7 @@ type Request struct {
4646 ItemID string
4747 MediaSourceID string
4848 PlaySessionID string
49+ AudioStreamIndex int
4950 StartTimeTicks int64
5051 RequestedStartTimeTicks int64
5152 SegmentStartIndex int
@@ -65,6 +66,7 @@ type Session struct {
6566 ItemID string
6667 MediaSourceID string
6768 PlaySessionID string
69+ AudioStreamIndex int
6870 StartTimeTicks int64
6971 RequestedStartTimeTicks int64
7072 SegmentStartIndex int
@@ -153,10 +155,19 @@ type MediaInfo struct {
153155 AudioCodec string
154156 AudioChannels int
155157 AudioTitle string
158+ AudioStreams []AudioStreamInfo
156159 Bitrate int64
157160 RunTimeTicks int64
158161}
159162
163+ type AudioStreamInfo struct {
164+ Index int
165+ Ordinal int
166+ Codec string
167+ Channels int
168+ Title string
169+ }
170+
160171func (info MediaInfo ) Summary () string {
161172 var parts []string
162173 if info .Name != "" {
@@ -191,6 +202,9 @@ func (info MediaInfo) Summary() string {
191202 }
192203 parts = append (parts , "audio=" + audio )
193204 }
205+ if len (info .AudioStreams ) > 0 {
206+ parts = append (parts , fmt .Sprintf ("audio_streams=%d" , len (info .AudioStreams )))
207+ }
194208 if info .Bitrate > 0 {
195209 parts = append (parts , fmt .Sprintf ("bitrate=%d" , info .Bitrate ))
196210 }
@@ -204,7 +218,20 @@ func (info MediaInfo) Summary() string {
204218}
205219
206220func (info MediaInfo ) IsZero () bool {
207- return info == MediaInfo {}
221+ return info .ItemID == "" &&
222+ info .SourceID == "" &&
223+ info .Name == "" &&
224+ info .Path == "" &&
225+ info .Container == "" &&
226+ info .VideoCodec == "" &&
227+ info .Width == 0 &&
228+ info .Height == 0 &&
229+ info .AudioCodec == "" &&
230+ info .AudioChannels == 0 &&
231+ info .AudioTitle == "" &&
232+ len (info .AudioStreams ) == 0 &&
233+ info .Bitrate == 0 &&
234+ info .RunTimeTicks == 0
208235}
209236
210237func (m * Manager ) RememberMedia (id string , info MediaInfo ) {
@@ -488,6 +515,9 @@ func shouldRestart(session *Session, request Request) bool {
488515 if request .SegmentStartIndex != session .SegmentStartIndex {
489516 return true
490517 }
518+ if request .AudioStreamIndex != session .AudioStreamIndex {
519+ return true
520+ }
491521 return request .InputURL != "" && session .InputURL != "" && request .InputURL != session .InputURL
492522}
493523
@@ -508,6 +538,7 @@ func touchSession(session *Session, request Request, now time.Time, mediaAccess
508538 if request .PlaySessionID != "" {
509539 session .PlaySessionID = request .PlaySessionID
510540 }
541+ session .AudioStreamIndex = request .AudioStreamIndex
511542 session .StartTimeTicks = request .StartTimeTicks
512543 session .RequestedStartTimeTicks = request .RequestedStartTimeTicks
513544 session .SegmentStartIndex = request .SegmentStartIndex
@@ -764,7 +795,7 @@ func (r FFmpegRunner) Start(ctx context.Context, session *Session, request Reque
764795 args := buildFFmpegArgs (session , request , r .Options )
765796 playlist := filepath .Join (session .Dir , "master.m3u8" )
766797 logPath := filepath .Join (session .Dir , "ffmpeg.log" )
767- logging .Infof ("transcode start id=%s segment=%d decode=%s audio=optional-aac log=%s" , session .ID , session .SegmentStartIndex , ffmpegOptionsSummary (r .Options ), logPath )
798+ logging .Infof ("transcode start id=%s segment=%d decode=%s audio_stream_index=%d audio_map=%s audio=optional-aac log=%s" , session .ID , session .SegmentStartIndex , ffmpegOptionsSummary (r .Options ), request . AudioStreamIndex , audioMapArg ( session , request ), logPath )
768799 logging .Debugf ("ffmpeg start id=%s item=%s media_source=%s start_ticks=%d segment_start=%d path=%s input=%s playlist=%s media=%s args=%s" , session .ID , session .ItemID , session .MediaSourceID , session .StartTimeTicks , session .SegmentStartIndex , r .Path , redactURLString (request .InputURL ), playlist , session .Media .Summary (), redactFFmpegArgs (args ))
769800 cmd := exec .CommandContext (ctx , r .Path , args ... )
770801 stdin , err := cmd .StdinPipe ()
@@ -845,7 +876,7 @@ func buildFFmpegArgs(session *Session, request Request, options ...FFmpegOptions
845876 args = append (args ,
846877 "-i" , request .InputURL ,
847878 "-map" , "0:v:0" ,
848- "-map" , "0:a:0?" ,
879+ "-map" , audioMapArg ( session , request ) ,
849880 "-c:v" , "libx264" ,
850881 "-preset" , "veryfast" ,
851882 "-profile:v" , "high" ,
@@ -872,6 +903,27 @@ func buildFFmpegArgs(session *Session, request Request, options ...FFmpegOptions
872903 return args
873904}
874905
906+ func audioMapArg (session * Session , request Request ) string {
907+ ordinal := audioOrdinalForRequest (session , request )
908+ return fmt .Sprintf ("0:a:%d?" , ordinal )
909+ }
910+
911+ func audioOrdinalForRequest (session * Session , request Request ) int {
912+ if request .AudioStreamIndex < 0 {
913+ return 0
914+ }
915+ media := request .Media
916+ if media .IsZero () && session != nil {
917+ media = session .Media
918+ }
919+ for _ , stream := range media .AudioStreams {
920+ if stream .Index == request .AudioStreamIndex && stream .Ordinal >= 0 {
921+ return stream .Ordinal
922+ }
923+ }
924+ return 0
925+ }
926+
875927func appendHardwareDecodeArgs (args []string , options FFmpegOptions ) []string {
876928 switch strings .ToLower (strings .TrimSpace (options .HardwareDecode )) {
877929 case "" , "none" , "off" , "false" :
0 commit comments