bep40 commited on
Commit
ca61e2d
·
verified ·
1 Parent(s): 51c6f2f

[ffmpeg-restream] monotonic seq (PR #64)

Browse files
Files changed (1) hide show
  1. ffmpeg_relay.py +17 -2
ffmpeg_relay.py CHANGED
@@ -64,6 +64,7 @@ class FfmpegRelay:
64
  self.started_at = time.time()
65
  self.failures = 0
66
  self.restarting = False
 
67
  self.resolved = _resolve_redirect(url, self._headers_dict())
68
  self._ensure_dir()
69
 
@@ -167,12 +168,26 @@ class FfmpegRelay:
167
  self.restarting = False
168
 
169
  def playlist_text(self):
170
- """Return current playlist content (empty string if relay warming up)."""
 
 
 
 
171
  try:
172
  with open(self.playlist, "r", encoding="utf-8") as f:
173
- return f.read()
174
  except Exception:
175
  return ""
 
 
 
 
 
 
 
 
 
 
176
 
177
  def segment(self, name):
178
  """Return (bytes, status) for a local segment file."""
 
64
  self.started_at = time.time()
65
  self.failures = 0
66
  self.restarting = False
67
+ self.last_served_seq = -1
68
  self.resolved = _resolve_redirect(url, self._headers_dict())
69
  self._ensure_dir()
70
 
 
168
  self.restarting = False
169
 
170
  def playlist_text(self):
171
+ """Return current playlist content (empty string if relay warming up).
172
+ MEDIA-SEQUENCE is served monotonically non-decreasing across restarts:
173
+ if ffmpeg restarted and reset sequence to 0, we bump it to
174
+ last_served_seq+1 so hls.js never sees a backward jump (which causes
175
+ a discontinuity error -> brief giât at exactly the restart moments)."""
176
  try:
177
  with open(self.playlist, "r", encoding="utf-8") as f:
178
+ text = f.read()
179
  except Exception:
180
  return ""
181
+ m = re.search(r"#EXT-X-MEDIA-SEQUENCE:(\d+)", text)
182
+ if m:
183
+ seq = int(m.group(1))
184
+ if seq < self.last_served_seq:
185
+ seq = self.last_served_seq
186
+ # keep serving a forward-moving sequence
187
+ self.last_served_seq = max(self.last_served_seq, seq)
188
+ text = text.replace("#EXT-X-MEDIA-SEQUENCE:%d" % int(m.group(1)),
189
+ "#EXT-X-MEDIA-SEQUENCE:%d" % self.last_served_seq, 1)
190
+ return text
191
 
192
  def segment(self, name):
193
  """Return (bytes, status) for a local segment file."""