среда, 7 ноября 2012 г.

Некоторые особенности nginx+mp4/flv

Штатно, если ничего не настраивать, mp4 отдаются или как text/plain, или application/octet-stream.



Для отладки удобно использовать curl:
показ заголовков
curl -I "http://site.ru/video.mp4"

Лог общения с сервером
curl -v -I "http://site.ru/video.mp4"

Проверка включения сжатия (на text/plain оно часто включается, что надо проверять)
curl -I --header "Accept-Encoding: gzip,deflate" "http://site.ru/video.mp4"
и искать строку типа

Content-Encoding: gzip

mp4
Простейший вариант отдачи:
в mime.types:
video/mp4    mp4;

В location для отдачи таких видео:
        location ~* ^.+/(\+\.mp4)$
        {
                root   /var/www/site/video;
                access_log /var/www/site/logs/nginx.access.log;
                add_header Content-disposition "attachment; filename=$1";
                gzip off;
        }
В правильно настроенной системе сжатие и так не будет включаться для video/mp4, но некоторые хотят перестраховаться.
В add_header указываем, что файл отдается как вложение (откроется окно "сохранить как")


Особенность формата mp4 в том, что он изначально плохо предназначен для стриминга, поэтому с начала файл показывать можно, а вот поиск по времени уже работать не будет или надо будет сначала весь файл выкачать. Для возможной перемотки нужен индекс в файле, без таких индексов даже локально файл будет тормозить при перемотке, что уж говорить про веб. "В форматах, основанных на H.264, метаданные, необходимые для поддержки позиционирования, хранятся в так называемом “moov атоме.” Это часть файла, которая содержит индексную информацию для всего файла.

До начала воспроизведения плееру необходимо прочитать метаданные. Для этого он отсылает специальный запрос с аргументом start=0. Многие кодирующие программы добавляют метаданные в конец файла. Для псевдо-стриминга это плохо: метаданные должны быть расположены в начале файла, иначе потребуется загрузить файл целиком, прежде чем начать воспроизведение. Если файл отформатирован хорошо, с метаданными в начале файла, nginx просто посылает в ответ содержимое файла. В противном случае, он вынужден будет прочитать файл и подготовить новый поток, в котором метаданные предшествуют медийным данным. "
http://nginx.org/ru/docs/http/ngx_http_mp4_module.html

Вообще эту доку лучше прочитать целиком, она небольшая.

Собственно пример с этим модулем (требуется плеер с поддержкой этого стриминга)

location /video/ {
    mp4;
    mp4_buffer_size     1m;
    mp4_max_buffer_size 5m;
}

"Некоторые плееры также поддерживают запросы с указанием диапазона запрашиваемых байт (byte-range requests), для них вообще не требуется этот модуль.". В этом случае как раз достаточно первого варианта.


"Модуль mp4 не читает весь файл - он читает только метаданные (а если start не указан - то вообще не читает), остальное при необходимости (если не используется sendfile) читает copy-фильтр."
http://www.lexa.ru/nginx-ru/msg47915.html

О подготовке файлов для стриминга
Есть вариант добавления нужной информации через yamdi (начинать читать отсюда)

flv
"Модуль ngx_http_flv_module обеспечивает серверную поддержку псевдо-стриминга для файлов Flash Video (FLV).


Он специальным образом обрабатывает запросы с аргументом start в строке запроса, посылая в ответ содержимое файла с запрошенного смещения в байтах, добавив перед ним FLV-заголовок."

http://nginx.org/ru/docs/http/ngx_http_flv_module.html

Не совсем понятно назначение данного модуля - flv изначально потоковый, там всё нужное и так есть. Если сервер умеет range - проблем быть не должно.

Up
Замечание по регэкспу для location:
часто (у того же ispmanager) правила описываются как
location ~* ^.+\.(jpg|jpeg)$ {
(для краткости обрезано). Так вот, в старых версиях почему-то в $1 оказывалось полное имя файла, тогда как в новых всегда будет только расширение. Поэтому правильнее описывать например так:
^.+/(.+\.)(jpg|jpeg)$
и потом set $file $1$2;

Именно такой шаблон не тестировался, особенно с файлами из корня, но что-то наподобие работает.

Комментариев нет:

Отправить комментарий