Skip to content

Commit 2c76bf4

Browse files
authored
Merge pull request #1918 from danog/fix-stream-receiver-on-demand
Stream mode: download the stream only to record it
2 parents 7bf4f69 + 86dbf8a commit 2c76bf4

2 files changed

Lines changed: 26 additions & 8 deletions

File tree

‎src/GroupCall/GroupCallController.php‎

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -283,12 +283,8 @@ public function resumeAfterRestart(): void
283283
$this->presentationDj?->resumeReader();
284284
$this->connection?->resume();
285285
$this->presentationConnection?->resume();
286-
if ($this->streamMode) {
287-
// The stream receiver does not survive a restart (its recording does not either):
288-
// follow the stream again from the live edge.
289-
$this->streamReceiver = new StreamReceiver($this);
290-
$this->streamReceiver->start($this->rtmpMode);
291-
}
286+
// The stream receiver does not survive a restart, and neither does its recording: it's started again when a
287+
// recording is set, see setOutput().
292288
EventLoop::queue($this->refetch(...));
293289
}
294290

@@ -414,8 +410,9 @@ private function applyConnectionParams(array $params): void
414410
);
415411
$this->connection?->close();
416412
$this->connection = null;
417-
$this->streamReceiver ??= new StreamReceiver($this);
418-
$this->streamReceiver->start($parsed['rtmp']);
413+
// Only to record: without a recording, it downloaded every chunk for nothing, and the flood waits of
414+
// downloading a few streams at once made it fall behind (TIME_TOO_SMALL), see setOutput().
415+
$this->streamReceiver?->start($parsed['rtmp']);
419416
return;
420417
}
421418
if ($parsed['transport'] === null) {
@@ -1143,6 +1140,7 @@ public function setOutput(LocalFile|WritableStream $file, string|int|null $parti
11431140
CallStream::checkAvailable($streams, $available, 'The stream');
11441141
$this->streamReceiver ??= new StreamReceiver($this);
11451142
$this->streamReceiver->setOutput($file, $format);
1143+
$this->streamReceiver->start($this->rtmpMode);
11461144
return $available;
11471145
}
11481146

@@ -1162,6 +1160,7 @@ public function setOutputFolder(LocalDirectory $dir, string|int|null $participan
11621160
}
11631161
$this->streamReceiver ??= new StreamReceiver($this);
11641162
$this->streamReceiver->setOutputDirectory($dir, $format);
1163+
$this->streamReceiver->start($this->rtmpMode);
11651164
return $this;
11661165
}
11671166

‎tests/danog/MadelineProto/GroupCallMembershipTest.php‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
use danog\MadelineProto\DataCenter;
2525
use danog\MadelineProto\EventHandler\Calls\GroupCallState;
2626
use danog\MadelineProto\GroupCall\GroupCallController;
27+
use danog\MadelineProto\GroupCall\StreamReceiver;
28+
use danog\MadelineProto\LocalFile;
2729
use danog\MadelineProto\Logger;
2830
use danog\MadelineProto\MTProto;
2931
use danog\MadelineProto\RPCErrorException;
@@ -148,6 +150,23 @@ public function testAnEndedCallIsLeft(string $rpc): void
148150
$this->assertSame([], $API->getAllGroupCalls());
149151
}
150152

153+
/**
154+
* In stream mode, the chunks of the stream are only downloaded to record them: without a recording, magnaluna
155+
* downloaded the RTMP livestreams it plays to for nothing, drew flood waits, and fell behind their live edge.
156+
*/
157+
public function testTheStreamIsOnlyDownloadedToRecordIt(): void
158+
{
159+
$controller = $this->joinedCall($this->client());
160+
$receiver = new ReflectionProperty(GroupCallController::class, 'streamReceiver');
161+
(fn () => $this->applyConnectionParams(['stream' => true, 'rtmp' => true]))->call($controller);
162+
$this->assertNull($receiver->getValue($controller), 'Not downloaded without a recording');
163+
164+
$controller->setOutput(new LocalFile(sys_get_temp_dir().'/madeline-stream-on-demand.mkv'));
165+
$this->assertNotNull($receiver->getValue($controller));
166+
$this->assertTrue((new ReflectionProperty(StreamReceiver::class, 'running'))->getValue($receiver->getValue($controller)), 'Downloaded to record it');
167+
$receiver->getValue($controller)->stop();
168+
}
169+
151170
/**
152171
* A call that ended is reported to the event handler as discarded: a live story ends with an updateStory, without
153172
* the groupCallDiscarded the event handler waits for (magnaluna didn't start its live story again).

0 commit comments

Comments
 (0)