While investigating how the VOD transcoder determines which segments to send to ffmpeg, I noticed that each batch consistently contains one fewer segment than expected. Specifically, when segmentBufferMax is set to N, the transcoder only encodes N-1 segments per ffmpeg process, rather than the full N.
I believe the issue lies in the for loop in line 473 in transcodeFromSegment():
|
func (m *ManagerCtx) transcodeFromSegment(index int) error { |
|
m.mu.Lock() |
|
defer m.mu.Unlock() |
|
|
|
segmentsTotal := len(m.segments) |
|
if segmentsTotal <= m.segmentBufferMax { |
|
// if all our segments can fit in the buffer |
|
// then we should transcode all of them |
|
// regardless of the index |
|
index = 0 |
|
} else if index+m.segmentBufferMax < segmentsTotal { |
|
// cap transocded segments to the buffer size |
|
segmentsTotal = index + m.segmentBufferMax |
|
} |
|
|
|
offset, limit := 0, 0 |
|
for i := index; i < segmentsTotal-1; i++ { |
|
_, isEnqueued := m.waitForSegment(i) |
|
isTranscoded := m.isSegmentTranscoded(i) |
The loop iterates over the range [index; segmentsTotal-1). At first glance, this seems correct—mirroring the common [start, end) pattern, where end is exclusive.
However, segmentsTotal is a bit of misnomer here. It doesn't contain a total count of segments. Instead, it is an already exclusive upper bound!
The common case is that we're somewhere in the middle of a video. Then segmentsTotal is calculated in line 469:
|
segmentsTotal = index + m.segmentBufferMax |
Let's say
index is 100, and
segmentBufferMax is set to the default of 5. Now we calculate an
exclusive upper bound for the segment batch of 105. In other words, we're expecting the segment range
[100, 101, 102, 103, 104] to be transcoded. The upper bound of 105 is exclusive, meaning the -1 is basically already stored in there.
The problem is that the for-loop treats segmentsTotal as if it were inclusive, subtracting 1 to make it exclusive again. This results in the range [100, 104), which only includes segments 100, 101, 102, and 103—four segments, or segmentBufferMax - 1.
While investigating how the VOD transcoder determines which segments to send to ffmpeg, I noticed that each batch consistently contains one fewer segment than expected. Specifically, when
segmentBufferMaxis set to N, the transcoder only encodes N-1 segments per ffmpeg process, rather than the full N.I believe the issue lies in the for loop in line 473 in
transcodeFromSegment():go-transcode/hlsvod/manager.go
Lines 457 to 475 in f8137e6
The loop iterates over the range
[index; segmentsTotal-1). At first glance, this seems correct—mirroring the common[start, end)pattern, where end is exclusive.However,
segmentsTotalis a bit of misnomer here. It doesn't contain a total count of segments. Instead, it is an already exclusive upper bound!The common case is that we're somewhere in the middle of a video. Then
segmentsTotalis calculated in line 469:go-transcode/hlsvod/manager.go
Line 469 in f8137e6
Let's say
indexis 100, andsegmentBufferMaxis set to the default of 5. Now we calculate an exclusive upper bound for the segment batch of 105. In other words, we're expecting the segment range[100, 101, 102, 103, 104]to be transcoded. The upper bound of 105 is exclusive, meaning the -1 is basically already stored in there.The problem is that the for-loop treats
segmentsTotalas if it were inclusive, subtracting 1 to make it exclusive again. This results in the range[100, 104), which only includes segments100, 101, 102, and 103—four segments, orsegmentBufferMax - 1.