Видео и аудио кодирование

Материал из Artem Aleksashkin's Wiki
Перейти к навигации Перейти к поиску

Главное, что нужно понять:

  • Видеофайлы(медиафайлы) содержат потоки(дорожки): видеопоток, аудиопоток, субтитры и другую информацию(например видеорегистраторы авто - gps координаты и время).
  • Потоки упакованы в контейнер: avi, mkv, mp4, wmv, mov...
  • Потоки сжаты кодеками: h264, mpeg, mp3, aac, vp8, vp9, av1...
  • Потоки можно извлекать и работать с ними отдельно. Добавлять сдвиги, удалять и пр. Зависит от контейнера и кодека.
  • При кодировании важна производительность декодирования. Чтобы компьютер пользователя не грелся. Или ноутбук или телефон не разряжались. Есть аппаратная поддержка кодеков для этих целей. Выбирайте кодеки с аппаратной поддержкой, иначе видеофайл будет воспроизводится центральным процессором.
  • Кодеки бывают свободные и несвободные(требуют уплаты роялти или платы за использование алгоритма)


Видео

Ссылки

Кодеки

$ mediainfo --Output=XML ./Terminator_Genezis.avi 
<?xml version="1.0" encoding="UTF-8"?>
<Mediainfo
    version="0.1"
    ref="./Terminator_Genezis.avi">
<File>
<track type="General">
<Complete_name>./Terminator_Genezis.avi</Complete_name>
<Format>AVI</Format>
<Format_Info>Audio Video Interleave</Format_Info>
<File_size>1.46 GiB</File_size>
<Duration>2h 5mn</Duration>
<Overall_bit_rate>1 663 Kbps</Overall_bit_rate>
<Writing_application>VirtualDubMod 1.5.10.3 | www.virtualdub-fr.org || (build 2550/release)</Writing_application>
<Writing_library>VirtualDubMod build 2550/release</Writing_library>
</track>

<track type="Video">
<ID>0</ID>
<Format>MPEG-4 Visual</Format>
<Format_profile>Advanced Simple@L5</Format_profile>
<Format_settings__BVOP>1</Format_settings__BVOP>
<Format_settings__QPel>No</Format_settings__QPel>
<Format_settings__GMC>No warppoints</Format_settings__GMC>
<Format_settings__Matrix>Custom</Format_settings__Matrix>
<Codec_ID>XVID</Codec_ID>
<Codec_ID_Hint>XviD</Codec_ID_Hint>
<Duration>2h 5mn</Duration>
<Bit_rate>1 269 Kbps</Bit_rate>
<Width>720 pixels</Width>
<Height>304 pixels</Height>
<Display_aspect_ratio>2.35:1</Display_aspect_ratio>
<Frame_rate>23.976 (23976/1000) fps</Frame_rate>
<Color_space>YUV</Color_space>
<Chroma_subsampling>4:2:0</Chroma_subsampling>
<Bit_depth>8 bits</Bit_depth>
<Scan_type>Progressive</Scan_type>
<Compression_mode>Lossy</Compression_mode>
<Bits__Pixel_Frame_>0.242</Bits__Pixel_Frame_>
<Stream_size>1.11 GiB (76%)</Stream_size>
<Writing_library>XviD 73</Writing_library>
</track>

<track type="Audio">
<ID>1</ID>
<Format>AC-3</Format>
<Format_Info>Audio Coding 3</Format_Info>
<Mode_extension>CM (complete main)</Mode_extension>
<Format_settings__Endianness>Big</Format_settings__Endianness>
<Codec_ID>2000</Codec_ID>
<Duration>2h 5mn</Duration>
<Bit_rate_mode>Constant</Bit_rate_mode>
<Bit_rate>384 Kbps</Bit_rate>
<Channel_s_>6 channels</Channel_s_>
<Channel_positions>Front: L C R, Side: L R, LFE</Channel_positions>
<Sampling_rate>48.0 KHz</Sampling_rate>
<Frame_rate>31.250 fps (1536 spf)</Frame_rate>
<Compression_mode>Lossy</Compression_mode>
<Stream_size>345 MiB (23%)</Stream_size>
<Alignment>Split accross interleaves</Alignment>
<Interleave__duration>42 ms (1.00 video frame)</Interleave__duration>
<Interleave__preload_duration>500 ms</Interleave__preload_duration>
</track>

</File>
</Mediainfo>

H.264

function transform_video_x264_aac_mp4($file_src,$file_dst,$width,$height,$vb,$ab,$tmp_dir="./")
{
	if (!file_exists($file_src)) return false;
	$X264_SUBQ="1";
	$X264_FRAMEREF="1";
	$X264_KEYINT="125";
	$X264_THREADS="auto";
	$X264_ME="hex";
	$X264_BFRAMES="1";
	$session_id=time();
	$files_prefix = $tmp_dir."".$session_id;
	$mediainfo = $this->exec_program("mediainfo ".$file_src);
	preg_match("/General[\s\S]*?Format\s+\:\s+(.*)\s+/",$mediainfo,$m);
	$format = $m[1];
	$format_profile = "";
	if (preg_match("/General[\s\S]*?Format profile\s+\:\s+(.*)\s+/",$mediainfo,$m))
	{
		$format_profile = $m[1];
	}
	$format_info = "";
	if (preg_match("/General[\s\S]*?Format\/Info\s+\:\s+(.*)\s+/",$mediainfo,$m))
	{
		$format_info = $m[1];
	}
	preg_match("/Video[\s\S]*?Frame rate\s+\:\s+(.*?)\s+fps/",$mediainfo,$m);
	//echo $format."\n";
	$fps = $m[1];
	if ($format_info == "Apple")
	{
		// dump audio
		$this->exec_program("mplayer -quiet ".$file_src." -ao pcm:fast:file=".$files_prefix."_audiostream -vc dummy -vo null -channels 2");
		// encode video from src
		$this->exec_program("mencoder ".$file_src." -ovc x264 -x264encopts bitrate=".$vb.":subq=".$X264_SUBQ.":frameref=".$X264_FRAMEREF.":me=".$X264_ME.":bframes=".$X264_BFRAMES.":threads=".$X264_THREADS.":keyint=".$X264_KEYINT." -of rawvideo -vf scale=".$width.":".$height." -ofps ".$fps." -nosound -o ".$files_prefix."_videostream.x264");
		// encode audio
		$this->exec_program("ffmpeg -i ".$files_prefix."_audiostream -strict experimental -acodec aac -ab ".$ab." -ac 2 ".$files_prefix."_audiostream.aac");
		$this->exec_program("MP4Box -new -add ".$files_prefix."_videostream.x264 -fps ".$fps." -add ".$files_prefix."_audiostream.aac ".$file_dst."");
		$this->exec_program("rm -f ".$files_prefix."_*");
		return true;
	}
	if ($format_profile == "QuickTime")
	{
		// dump audio
		$this->exec_program("mplayer -quiet ".$file_src." -ao pcm:fast:file=".$files_prefix."_audiostream -vc dummy -vo null -channels 2");
		// encode video from src
		$this->exec_program("mencoder ".$file_src." -ovc x264 -x264encopts bitrate=".$vb.":subq=".$X264_SUBQ.":frameref=".$X264_FRAMEREF.":me=".$X264_ME.":bframes=".$X264_BFRAMES.":threads=".$X264_THREADS.":keyint=".$X264_KEYINT." -of rawvideo -vf scale=".$width.":".$height." -ofps ".$fps." -nosound -o ".$files_prefix."_videostream.x264");
		// encode audio
		$this->exec_program("ffmpeg -i ".$files_prefix."_audiostream -strict experimental -acodec aac -ab ".$ab." -ac 2 ".$files_prefix."_audiostream.aac");
		$this->exec_program("MP4Box -new -add ".$files_prefix."_videostream.x264 -fps ".$fps." -add ".$files_prefix."_audiostream.aac ".$file_dst."");
		$this->exec_program("rm -f ".$files_prefix."_*");
		return true;
	}
	if ($format == "MPEG-4")
	{
		$mpeg4tracks = $this->exec_program("MP4Box -info ".$file_src);
		$tracks = preg_split("/\n\n/",$mpeg4tracks);
		$videotrack = false;
		foreach($tracks as $track)
		{
			if (preg_match("/Track # (\d+)[\s\S]*?Visual Stream/",$track,$m))
			{
				$videotrack = $m[1];
			}
		}
		$audiotrack = false;
		foreach($tracks as $track)
		{
			if (preg_match("/Track # (\d+)[\s\S]*?Audio (Stream|Track)/",$track,$m))
			{
				$audiotrack = $m[1];
			}
		}
		if ($videotrack === false) return false;
		$this->exec_program("MP4Box -raw ".$videotrack." ".$file_src." -out ".$files_prefix."_videostream");
		if ($audiotrack !== false) $this->exec_program("MP4Box -raw ".$audiotrack." ".$file_src." -out ".$files_prefix."_audiostream");
		$this->exec_program("mencoder ".$files_prefix."_videostream -ovc x264 -x264encopts bitrate=".$vb.":subq=".$X264_SUBQ.":frameref=".$X264_FRAMEREF.":me=".$X264_ME.":bframes=".$X264_BFRAMES.":threads=".$X264_THREADS.":keyint=".$X264_KEYINT." -of rawvideo -vf scale=".$width.":".$height." -ofps ".$fps." -nosound -o ".$files_prefix."_videostream.x264");
		if ($audiotrack !== false) $this->exec_program("ffmpeg -i ".$files_prefix."_audiostream -strict experimental -acodec aac -ab ".$ab." -ac 2 ".$files_prefix."_audiostream.aac");
		if ($audiotrack !== false) $this->exec_program("MP4Box -new -add ".$files_prefix."_videostream.x264 -fps ".$fps." -add ".$files_prefix."_audiostream.aac ".$file_dst."");
		else $this->exec_program("MP4Box -new -add ".$files_prefix."_videostream.x264 -fps ".$fps." ".$file_dst."");
		$this->exec_program("rm -f ".$files_prefix."_*");
		return true;
	}
	if ($format == "AVI")//Format Audio Video Interleave
	{
		// dump audio
		$this->exec_program("mplayer -quiet ".$file_src." -ao pcm:fast:file=".$files_prefix."_audiostream -vc dummy -vo null -channels 2");
		// encode video from src
		$this->exec_program("mencoder ".$file_src." -ovc x264 -x264encopts bitrate=".$vb.":subq=".$X264_SUBQ.":frameref=".$X264_FRAMEREF.":me=".$X264_ME.":bframes=".$X264_BFRAMES.":threads=".$X264_THREADS.":keyint=".$X264_KEYINT." -of rawvideo -vf scale=".$width.":".$height." -ofps ".$fps." -nosound -o ".$files_prefix."_videostream.x264");
		// encode audio
		$this->exec_program("ffmpeg -i ".$files_prefix."_audiostream -strict experimental -acodec aac -ab ".$ab." -ac 2 ".$files_prefix."_audiostream.aac");
		$this->exec_program("MP4Box -new -add ".$files_prefix."_videostream.x264 -fps ".$fps." -add ".$files_prefix."_audiostream.aac ".$file_dst."");
		$this->exec_program("rm -f ".$files_prefix."_*");
		return true;
	}
	if ($format == "Windows Media")//WMV
	{
		// dump audio
		$this->exec_program("mplayer -quiet ".$file_src." -ao pcm:fast:file=".$files_prefix."_audiostream -vc dummy -vo null -channels 2");
		// encode video from src
		$this->exec_program("mencoder ".$file_src." -ovc x264 -x264encopts bitrate=".$vb.":subq=".$X264_SUBQ.":frameref=".$X264_FRAMEREF.":me=".$X264_ME.":bframes=".$X264_BFRAMES.":threads=".$X264_THREADS.":keyint=".$X264_KEYINT." -of rawvideo -vf scale=".$width.":".$height." -ofps ".$fps." -nosound -o ".$files_prefix."_videostream.x264");
		// encode audio
		$this->exec_program("ffmpeg -i ".$files_prefix."_audiostream -strict experimental -acodec aac -ab ".$ab." -ac 2 ".$files_prefix."_audiostream.aac");
		$this->exec_program("MP4Box -new -add ".$files_prefix."_videostream.x264 -fps ".$fps." -add ".$files_prefix."_audiostream.aac ".$file_dst."");
		$this->exec_program("rm -f ".$files_prefix."_*");
		return true;
	}
	if ($format == "Flash Video")//FLV
	{
		// dump audio
		$this->exec_program("mplayer -quiet ".$file_src." -ao pcm:fast:file=".$files_prefix."_audiostream -vc dummy -vo null -channels 2");
		// encode video from src
		$this->exec_program("mencoder ".$file_src." -ovc x264 -x264encopts bitrate=".$vb.":subq=".$X264_SUBQ.":frameref=".$X264_FRAMEREF.":me=".$X264_ME.":bframes=".$X264_BFRAMES.":threads=".$X264_THREADS.":keyint=".$X264_KEYINT." -of rawvideo -vf scale=".$width.":".$height." -ofps ".$fps." -nosound -o ".$files_prefix."_videostream.x264");
		// encode audio
		$this->exec_program("ffmpeg -i ".$files_prefix."_audiostream -strict experimental -acodec aac -ab ".$ab." -ac 2 ".$files_prefix."_audiostream.aac");
		$this->exec_program("MP4Box -new -add ".$files_prefix."_videostream.x264 -fps ".$fps." -add ".$files_prefix."_audiostream.aac ".$file_dst."");
		$this->exec_program("rm -f ".$files_prefix."_*");
		return true;
	}
	return false;
}

VP9

AV1

Контейнеры