главная страница
материалы
  ms access и bitmap
  win в ucs-2 на perl
  приложение facebook
  медиа библиотека
  восстановление exif
  netgear stora
  netgear stora usb
  html и javascript
  openwrt upgrade
  yandex dns
  playlist vbs
  фотоархив
  node.js
  изменения в mrtg
  windows
  конвертация
  перекодировка для tv
  перекодировка для tvix

Перекодирование видео в HMS для телевизора Philips 37PFL9604H

Фильмотека хранится на NAS netgear Stora. Контент отдается по UPNP без какой-либо конвертации. Соответственно, на телевизоре на некоторых фильмах не отображается видео или звук. Причем оказалось, что важно не только поддержка контейнера и форматов, но и их соответствие, и даже соответствие расширению файла. Из первых опытов:

Видео

XVIDDIVX3DIVX4DIVX5

Аудио

MP2MP3AC3PCMWMA

Перекодирование видео с помощью VLC не увенчались успехом - не пошел ни один файл, им переконвертированый. Причем, расширение файла почему-то надо придумывать самому, что не всегда удается сделать правильно.

Воспользовался HMS как перекодировщиком, используя функцию предварительного транскодирования.

В Настройка → Обработка скопировал скрипт "Предварительное транскодирование (Shift+F5)". В нем поставил галку для отображения кнопки на панели и немного переделал.
// для того, чтобы фильм транскодировался в исходный каталог
sDestFileName := ChangeFileExt(aSourceFileName, sDestFileExt)

// для того, чтобы фильм не пытался перезаписать самого себя
if aSourceFileName = sDestFileName then 
  HmsLogMessage(mtiInfo,'Ошибка совпадения названий файлов',True)
else begin
...
end

Для того, чтобы при выставленном аудио кодеке AC3 сохранялся MP3, который поддерживается телевизором, на основе основного профиля создал новый профиль транскодирования в Настройка → Транскодер → Профили

Фильмы (транскодирование)

IfThen(mpSubItemsCount > 0, HmsTranscodingDvdParams,
   IfThen(mpAudioCodec = 'MP3',
      HmsTranscodingInputParams + 
      ReplaceStr(HmsTranscodingVideoParams, '-acodec ac3',  '-acodec copy') + 
      HmsTranscodingMapParams(mpAudioStreamNo),    

      HmsTranscodingInputParams + 
      HmsTranscodingVideoParams + 
      HmsTranscodingMapParams(mpAudioStreamNo)
   )   
)

Там же установил этот профиль в Предварительном транскодировании фильмов. После этого для перекодирования достаточно выделить файл, нажать кнопку транскодирования и после завершения процесса удалить файл с диска по правой кнопке.

Проверил разные контейнеры и видео форматы в Настройка → Устройства → по-умолчанию (кнопка настройки) → Кодеки с тем аудио кодеком, который ставится по-умолчанию.

Контейнер\Кодек

MPEG1MPEG2MPEG4H.264
DVD 103MB 105MB 92MB 139MB
TS 109MB 112MB 95MB 149MB
MPEG1 95MB 97MB 82MB 133MB

Там же можно поставить галку для отображения субтитров в полученном файле, если таковые имются. Можно еще поставить галку для отображения кнопки сканирования.

Проверял перекодированный файл тут же, изменив в настройках устройства, соответствующего телевизору, поддерживаемые файлы на "*" для того, чтобы HMS не пытался транскодировть полученный файл.

Заодно сделал профиль для телефона

Фильмы (MP4)

const
  mWidth  = 480; //640;
  mHeight = 270; //360;
var iWidth,iHeight : Integer;
begin
iWidth := mpWidth; iHeight := mpHeight;
if iWidth > mWidth then begin
  iHeight := iHeight * mWidth div iWidth;
  iWidth := mWidth;
end;
if iHeight > mHeight then begin
  iWidth := iWidth * mHeight div iHeight;
  iHeight := mHeight;
end;
TranscodingParams := 
HmsTranscodingInputParams + 
' -vf "scale=' + IntToStr(iWidth) + ':' + IntToStr(iHeight) + '"' +
' -vcodec mpeg4 -b:v 3000000 -copyts -pix_fmt yuv420p -threads 2' +
' -acodec libfaac -ab 448000 -ar 48000 -ac 2' +
HmsTranscodingMapParams(mpAudioStreamNo)
end.

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

Скрипт, в силу этих причин, получился не очень изящным, но работающим.
const
  mWidth  = 480; //Max Width,  640;
  mHeight = 270; //Max Height, 360;
  mScroll = 25;  //Bottom padding
  
var iWidth,iHeight : Integer;
    sAudio,sVideo,sSubt: String;
    sStreams,sHeightSubt: String;
    
begin
sAudio:=CurrentMediaItem.Properties[mpiAudioSelected];
sSubt:=CurrentMediaItem.Properties[mpiSubtitleLanguage];
if (sAudio <> '') then
  sStreams:=' -vstreamid ' + Str(HmsGetStreamID('V',0))+
            ' -astreamid ' + ExtractWord(2,sAudio,'x]')
else
  sStreams:=HmsTranscodingMapParams(mpAudioStreamNo);
  
iWidth:=mpWidth; iHeight:=mpHeight;
if iWidth>mWidth then begin
  iHeight:=iHeight*mWidth div iWidth;
  iWidth:=mWidth;
end;
if iHeight>mHeight then begin
  iWidth:=iWidth*mHeight div iHeight;
  iHeight:=mHeight;
end;

if (sSubt <> '') then
sHeightSubt := 
',pad=' + IntToStr(iWidth) + ':' + IntToStr(mHeight) + ':0:' +
IntToStr((mHeight-iHeight) div 2) +
'" -vhook "hmssubt.dll ' + mpFilePath +
',Arial Narrow,14,,,,1,,,,' +
Str(iWidth) + ',' + Str(mHeight - mScroll) +
',' + Str(mpFrameRate) + ',,,,' + sSubt + '"'
else
sHeightSubt := '"'; 

TranscodingParams := 
HmsTranscodingInputParams + 
' -vf "scale='+IntToStr(iWidth)+ ':' + IntToStr(iHeight) + sHeightSubt + 
' -vcodec mpeg4 -b:v 3000000 -copyts -pix_fmt yuv420p -threads 2' +
' -acodec libfaac -ab 448000 -ar 48000 -ac 2' +
sStreams;
end.

И для обозначения в имени файла языка аудио дорожки и субтитров немного изменил скрипт запуска транскодирования
// добавление в переменные основной процедуры выбранные дорожки
procedure ProcessFile(const aSourceFileName, aDestDirectory: string; 
aCheckTranscodingFinish: Boolean;
sAudio, sSubt: string);
...

// то, что добавляется к имени файла
  sAddFileName: string;
begin
  sAddFileName:='';

// берется только язык дорожки
  if (''+sAudio<> '') then sAddFileName:=sAddFileName + '.' + 
    ExtractWord(1,sAudio,' ')

// если не выбрана аудио дорожка, но выбраны субтитры
  else sAddFileName:='.x';

// прибавляется язык дорожки
  if (''+sSubt <> '') then sAddFileName:=sAddFileName + '.' + 
    ExtractWord(1,sSubt,' ');
  if (sAddFileName='.x') then sAddFileName:='';
...

// само прибавление
      sDestFileName := IncludeTrailingBackslash(aDestDirectory) + 
      ChangeFileExt(ExtractFileName(aSourceFileName), 
      sAddFileName + sDestFileExt);
...

begin
...
// добавление в параметры основной процедуры выбранные дорожки
      ProcessFile(MediaItem.Properties[mpiFilePath], 
      cfgPreTranscodingDestDirectory, False,
      MediaItem.Properties[mpiAudioSelected],
      MediaItem.Properties[mpiSubtitleLanguage]);