LINUX.ORG.RU

ошибки при трансляции сложных кадров в ffmpeg

 , ,


0

2

Всем привет. Вкратце ситуация такова: занимаюсь трансляциями на небольшой сервер, который смотрит не больше 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://tv2.dermatology.ru/live/stream1');
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');

В рамках работы я смог разобраться как настроить стрим и запустить его, но некоторые вещи я еще не понял как делать, потому прошу помощи здесь на форуме, может быть умельцы подскажут в чем скрывается суть проблемы.

Лог

Ответ на: комментарий от stevejobs

А что с ним не так? На оптоволокне сижу, вещаю в 640х480. Причем,я с обс когда стримлю тоже самое, никаких ошибок нет. А когда этим конфигом через ффпмег работаю, начинаются ошибки. Сегодня буфер поднял до 500мб. Вроде даже работать начало нормально, по под конец 2х часового эфира вывел двух лекторов в скайп и все накрылось.

Что самое удивительное, я днем, до начала эфирного времени, всё гонял, проверял, всё норм было. Может быть такое, что из-за нагрузки на сервак (наплыв просматривающих) случается такое?

magrega ()
Последнее исправление: magrega (всего исправлений: 2)
Ответ на: комментарий от anonymous

ошибки из устройства, с которого ты забираешь сырые кадры? может не успевает выгребать из e2eSoft VCam, там точно fps=25?

Как мне это проверить?

Так же гуглил и костыль с реестром использовал. Мне это не помогло.

Кстати, забыл указать. Я стримлю на свой сервер через ртмп

magrega ()
Последнее исправление: magrega (всего исправлений: 2)
Ответ на: комментарий от magrega

гуглил интернет, на каком-то замшелом форуме нашел пост, о том, как человек решил подобную проблему поменял сетевую карту со встроенной на внешнюю. У меня внешней нет, я обновил дрова на встроенной и покрутил ёё настройки в диспетчере устройств, убрал автосогласование дуплекса и сделал 1гб\сек, так же начальную скорость лан поднял с 10мб до 100мб\сек. Из настроек ффмпега удалил это:

($hdready ? '960x720' : '640x480')

и оставил просто нужное разрешение видео 640x480.

Вчера провел эфир, ошибок не было. Буду сегодня опять смотреть.

magrega ()