Всем привет. Вкратце ситуация такова: занимаюсь трансляциями на небольшой сервер, который смотрит не больше 700 человек. До лета 2020 года я стримил на флэше и проблем не испыватал, сейчас от флеша ушел и стримлю через hls и dash. Сегменты на сервер посылаю с помощью ffmpeg. Проблема в том, что во время стрима, если я показываю статичные картинки, слайды например, то проблем нет, вещание идет, все хорошо, но если я вывожу например скайп с лекторами, где они оба на экране разговаривают, лог покрывается ошибками о перегрузе буфера и эфир начинает зависать, пока я не выведу опять статичную картинку.
Вот часть лога с ошибками:
[dshow @ 0000000000614140] real-time buffer [e2eSoft VCam (WDM)] [video input] too full or near too full (64% of size: 100000000 [rtbufsize parameter])! frame dropped!
dshow passing through packet of type video size 921600 timestamp 249911910000 orig timestamp 249911910221 graph timestamp 249911910000 diff -221 e2eSoft VCam (WDM)
dshow passing through packet of type video size 921600 timestamp 249912310000 orig timestamp 249912310297 graph timestamp 249912310000 diff -297 e2eSoft VCam (WDM)
dshow passing through packet of type video size 921600 timestamp 249912710000 orig timestamp 249912709992 graph timestamp 249912710000 diff 8 e2eSoft VCam (WDM)
dshow passing through packet of type video size 921600 timestamp 249913110000 orig timestamp 249913110025 graph timestamp 249913110000 diff -25 e2eSoft VCam (WDM)
dshow passing through packet of type video size 921600 timestamp 249913510000 orig timestamp 249913510028 graph timestamp 249913510000 diff -28 e2eSoft VCam (WDM)
dshow passing through packet of type video size 921600 timestamp 249913910000 orig timestamp 249913910366 graph timestamp 249913910000 diff -366 e2eSoft VCam (WDM)
[dshow @ 0000000000614140] real-time buffer [e2eSoft VCam (WDM)] [video input] too full or near too full (64% of size: 100000000 [rtbufsize parameter])! frame dropped!
[rawvideo @ 000000000067a4c0] PACKET SIZE: 921600, STRIDE: 1920
Past duration 0.656242 too large
[libx264 @ 0000000000678980] frame=119801 QP=1.62 NAL=2 Slice:P Poc:24 I:0 P:121 SKIP:1079 size=952 bytes
frame=119802 fps= 25 q=0.0 size= 274701kB time=01:19:52.96 bitrate= 469.5kbits/s dup=0 drop=1 speed= 1x
[rawvideo @ 000000000067a4c0] PACKET SIZE: 921600, STRIDE: 1920
Past duration 0.656242 too large
dshow passing through packet of type video size 921600 timestamp 249914380000 orig timestamp 249914310064 graph timestamp 249914380000 diff 69936 e2eSoft VCam (WDM)
[libx264 @ 0000000000678980] frame=119802 QP=1.12 NAL=2 Slice:P Poc:26 I:303 P:581 SKIP:316 size=126402 bytes
[rawvideo @ 000000000067a4c0] PACKET SIZE: 921600, STRIDE: 1920
Past duration 0.656242 too large
dshow passing through packet of type video size 921600 timestamp 249914710000 orig timestamp 249914710087 graph timestamp 249914710000 diff -87 e2eSoft VCam (WDM)
[libx264 @ 0000000000678980] frame=119803 QP=1.12 NAL=2 Slice:P Poc:28 I:42 P:808 SKIP:350 size=91743 bytes
[rawvideo @ 000000000067a4c0] PACKET SIZE: 921600, STRIDE: 1920
Past duration 0.656242 too large
dshow passing through packet of type video size 921600 timestamp 249915110000 orig timestamp 249915110103 graph timestamp 249915110000 diff -103 e2eSoft VCam (WDM)
[libx264 @ 0000000000678980] frame=119804 QP=1.12 NAL=2 Slice:P Poc:30 I:485 P:400 SKIP:315 size=133739 bytes
[rawvideo @ 000000000067a4c0] PACKET SIZE: 921600, STRIDE: 1920
Past duration 0.656242 too large
[libx264 @ 0000000000678980] frame=119805 QP=1.13 NAL=2 Slice:P Poc:32 I:30 P:783 SKIP:387 size=83133 bytes
[rawvideo @ 000000000067a4c0] PACKET SIZE: 921600, STRIDE: 1920
Past duration 0.656242 too large
[libx264 @ 0000000000678980] frame=119806 QP=1.42 NAL=2 Slice:P Poc:34 I:0 P:268 SKIP:932 size=2152 bytes
[rawvideo @ 000000000067a4c0] PACKET SIZE: 921600, STRIDE: 1920
Past duration 0.656242 too large
Я пытался увеличивать -rtbufsize 100M до 150мб, но дело это не поменяло. Прикладываю файл настроек, на случай, если он поможет прояснить дело.
<?php
// переход director на 960x720 раскоментить
$hdready = false;
$fps = 25;
$archive = in_array('archive', $argv);
define('ffmpeg', 'c:/ffmpeg/bin/ffmpeg.exe');
define('local_param', ''); // '-r 25'
//-crf 8
//-qp 8
//-force_key_frames expr:gte(t,n_forced*3)
//-preset fast -tune zerolatency
//-g 50 -keyint_min 50
//-x264-params keyint=75:scenecut=0
define('codec_param', '-c:v libx264 -preset fast -tune zerolatency -profile:v baseline -level:v 3.0 -b:v 448k -c:a aac -profile:a aac_low -b:a 64k -g '.($fps*2).' -pix_fmt yuv420p');
define('codec_archive', '-c:v libx264 -preset fast -profile:v main -c:a aac -pix_fmt yuv420p');
define('remote_dest', 'rtmp://*************');
define('local_dest', strtr(__DIR__, array("\\"=>'/')).'/archive-'.date('Y-m-d-H-i-s').'.mp4');
//-x264-params min-keyint=24
//-c:a libfdk_aac
//-codecs
//-pix_fmts
/*
$encode .= ' -f tee';
if (false !== $video) $encode .= ' -map 0:v';
if (false !== $audio) $encode .= ' -map 0:a';
$encode .= ' -use_fifo true -fifo_options "drop_pkts_on_overflow=1:attempt_recovery=1:recovery_wait_time=1" "';
$encode .= '[onfail=ignore:f=flv]'.remote_dest;
$encode .= '|[onfail=ignore]'.local_dest;
$encode .= '"';
*/
ob_start();
passthru(ffmpeg.' -list_devices true -f dshow -i dummy 2>&1');
$ss = ob_get_contents();
ob_end_clean();
$keyboard=fopen("php://stdin","r");
$dev_a = array();
$dev_v = array();
$type = null;
foreach(explode("\n", $ss) as $s) {
$s = trim($s);
if ('' != $s) {
if (false !== strpos($s, 'video devices')) {
$type = 'v';
}
else if (false !== strpos($s, 'audio devices')) {
$type = 'a';
}
elseif (null !== $type) {
$p = strpos($s, '] "');
if (false !== $p) {
$name = substr($s, $p+4, -1);
if ('a' == $type) {
$dev_a[] = $name;
}
else {
$dev_v[] = $name;
}
}
}
}
}
$video = false;
if ($dev_v) {
foreach($dev_v as $i=>$name) {
echo '['.$i.'] '.$name."\n";
}
for(;;) {
echo 'Select video: ';
$key = fgets($keyboard);
if ('' == $key) break;
$key = intval($key);
if (isset($dev_v[$key])) {
$video = $key;
break;
}
}
}
$audio = false;
if ($dev_a) {
foreach($dev_a as $i=>$name) {
echo '['.$i.'] '.$name."\n";
}
for(;;) {
echo 'Select audio: ';
$key = fgets($keyboard);
if ('' == $key) break;
$key = intval($key);
if (isset($dev_a[$key])) {
$audio = $key;
break;
}
}
}
$encode = ffmpeg;
if (false !== $video) $encode .= ' -f dshow -rtbufsize 100M -video_size '.($hdready ? '960x720' : '640x480').' -framerate '.$fps.' -i video="'.$dev_v[$video].'"';
if (false !== $audio) $encode .= ':audio="'.$dev_a[$audio].'"';
$encode .= ' '.local_param;
if ($hdready) $encode .= ' -vf scale=960:720,setsar=4/3,setdar=4/3';
if ($archive) {
$encode .= ' '.codec_archive;
$encode .= ' '.local_dest;
}
else {
$encode .= ' -report '.codec_param;
$encode .= ' -f fifo -fifo_format flv -map 0:v -map 0:a -drop_pkts_on_overflow 1 -attempt_recovery 1 -recovery_wait_time 1';
$encode .= ' -f flv "'.remote_dest.'"'; // live=1
}
echo "\n{$encode}\n";
echo "\n\nStart encoding... <q>-stop \n\n";
passthru($encode);
echo "\n\nDone. Press any key...";
shell_exec('pause');
В рамках работы я смог разобраться как настроить стрим и запустить его, но некоторые вещи я еще не понял как делать, потому прошу помощи здесь на форуме, может быть умельцы подскажут в чем скрывается суть проблемы.