Linux Mint 17 и DLNA
Зачем это все надо Linux Mint — отличная домашняя ОС. Богатый выбор графических сред на любой вкус, простая и понятная даже новичку установка, сразу после установки имеем основной набор необходимого софта, удобный менеджер приложений, основные мультимедийные кодеки. В общем, отличная система для перехода и ознакомления с Linux.
Но возникает проблема для тех, у кого нет дома NAS или чего-то подобного, а смотреть контент с ПК на других устройствах, поддерживающих DLNA хочется. Под Linux существует множество различных DLNA-серверов, но оптимальным, все же, является MiniDLNA. И тому есть несколько причин. Во-первых, это типичный Unix-way: этот сервер является именно DLNA-сервером, а не комбайном с кучей свистелок, при этом контент без проблем воспринимается на любом устройстве. Даже телевизоры Samsung со своим AllShare прекрасно подключаются к нему. Также можно отметить и замечательную скорость работы и нетребовательность к ресурсам этого сервера.
И все бы было хорошо, но вот в с помощью команды
sudo apt-get install minidlna
установить его не получится — нет его в репозитарии.Существуют разные варианты устранения этого недоразумения, но самый правильный путь — установка из исходников.Чтобы не отвратить возможных новоиспеченных линуксоидов с этого пути и, возможно, помочь кому-то, напишу как обойти подводные камни, ибо информации много, но в начале пути людям нужно попроще.
Подготовка Если будете выполнять команды в консоли, запущенной с правами root, команду sudo писать не нужно.Для начала нужно установить необходимые библиотеки:
Обновляемся:
sudo apt-get update И устанавливаем сами библиотеки: sudo apt-get install libavcodec-dev libavformat-dev libavutil-dev libflac-dev libvorbis-dev libogg-dev libid3tag0-dev libexif-dev libjpeg-dev libsqlite3-dev Самая свежая версия MiniDLNA на данный момент — 1.1.3, ее можно скачать здесь, либо загрузить из консоли:
wget --trust-server-names http://sourceforge.net/projects/minidlna/files/latest/download ключ перед адресом нужен, чтобы сохранилось оригинальное имя, с выхдом новой версии имя файла будет отличатся. После этого архив нужно распаковать: tar -xf minidlna-1.1.3.tar.gz Теперь перейдем в распакованную папку с исходниками cd minidlna-1.1.3 Если вы хотите, чтобы на устройстве отображались сразу папки с файлами, нужно немного подправить код:
Открывайте спойлер Для отключения запроса способа отображения файлов нужно в папке с исходниками (minidlna-1.1.3, мы в нее уже должны были перейти) подправить файл upnpsoap.c, но сначала сделаем его резервную копию: sudo cp upnpsoap.c upnpsoap.c.old и откроем в редакторе sudo nano upnpsoap.c поиском (F6), ищем процедуру: «BrowseContentDirectory«static void BrowseContentDirectory (struct upnphttp * h, const char * action) { В начале процедуры выполняется разбор SOAP/XML-запроса, затем его обработка и возврат результата. Разбор запроса завершается формированием отладочного сообщения:
DPRINTF (E_DEBUG, L_HTTP, «Browsing ContentDirectory:\n» » * ObjectID: %s\n» » * Count: %d\n» » * StartingIndex: %d\n» » * BrowseFlag: %s\n» » * Filter: %s\n» » * SortCriteria: %s\n», ObjectID, RequestedCount, StartingIndex, BrowseFlag, Filter, SortCriteria); Далее реализован выбор корневого контейнера в зависимости от конфигурационного параметра root_container:
// Если запрошен корневой контейнер if (strcmp (ObjectID,»0») == 0) { // Выставляем флаг корневого контейнера args.flags |= FLAG_ROOT_CONTAINER; // Если в конфиге задан корневой контейнер if (runtime_vars.root_container) { // Если клиентом является аудио плейер и в конфиге задан обзор папок // Отправляем его в папку с музыкой if ((args.flags & FLAG_AUDIO_ONLY) && (strcmp (runtime_vars.root_container, BROWSEDIR_ID) == 0)) ObjectID = MUSIC_DIR_ID; else // Иначе выставляем контейнер, заданный в конфиге ObjectID = runtime_vars.root_container; } else // Если контейнер в конфиге не задан { // Если клиентом является аудио плейер // Отправляем его в папку с музыкой if (args.flags & FLAG_AUDIO_ONLY) ObjectID = MUSIC_ID; } } Сразу после этого блока и перед блоком с запросами к БД добавляем код перенаправления папок для видео, музыки и изображений:
//Redirect video to folder if (strcmp (ObjectID, VIDEO_ID) == 0) { ObjectID = VIDEO_DIR_ID; }
//Redirect music to folder if (strcmp (ObjectID, MUSIC_ID) == 0) { ObjectID = MUSIC_DIR_ID; }
//Redirect images to folder if (strcmp (ObjectID, IMAGE_ID) == 0) { ObjectID = IMAGE_DIR_ID; } В итоге правленный фрагмент должен выглядеть следующим образом: if (strcmp (ObjectID,»0») == 0) { args.flags |= FLAG_ROOT_CONTAINER; if (runtime_vars.root_container) { if ((args.flags & FLAG_AUDIO_ONLY) && (strcmp (runtime_vars.root_containe$ ObjectID = MUSIC_DIR_ID; else ObjectID = runtime_vars.root_container; } else { if (args.flags & FLAG_AUDIO_ONLY) ObjectID = MUSIC_ID; } }
//Redirect video to folder if (strcmp (ObjectID, VIDEO_ID) == 0) { ObjectID = VIDEO_DIR_ID; }
//Redirect music to folder if (strcmp (ObjectID, MUSIC_ID) == 0) { ObjectID = MUSIC_DIR_ID; }
//Redirect images to folder if (strcmp (ObjectID, IMAGE_ID) == 0) { ObjectID = IMAGE_DIR_ID; }
if (strcmp (BrowseFlag+6, «Metadata») == 0) { args.requested = 1; sql = sqlite3_mprintf («SELECT %s,» COLUMNS «from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID$ » where OBJECT_ID = '%q';», (args.flags & FLAG_ROOT_CONTAINER) ?»0, -1» : «o.OBJECT_I$ ObjectID); ret = sqlite3_exec (db, sql, callback, (void *) &args, &zErrMsg); totalMatches = args.returned; } Чтобы упростить процедуру последующего обновления, сохраним патч с внесенными изменениями:
diff -u upnpsoap.c.old upnpsoap.c > …/minidlna-folders.patch Теперь вместо редактирования файла, достаточно применить патч:
cd ~/src/minidlna/minidlna-НоваяВерсия patch < ../minidlna-folders.patch Теперь можно переходить к конфигурированию. Если вам это не нужно, переходите сразу к конфигурированию: sudo ./configure И компилируем:
sudo make Установка 1) Для тех, кто в дальнейшем захочет обновить версию, предыдущую можно удалить (конфигурационные файлы при этом сохраняются), если этого не сделать, то в случае, если в новой версии состав установочных файлов изменится, в /usr/local могут остаться старые файлы, при первой установке — переходим сразу к пункту 2.Для удаления заходим в папку с предыдущей установкой и выполняем команду:
sudo make uninstall 2) Запускаем установку: sudo make install 3)Если мы производим первоначальную установку, нужно создать init-скрипт:
sudo nano /etc/init.d/minidlna
, если мы обновляем версию, больше ничего делать не нужно, при первоначальной установке у нас откроется пустой файл, в который нужно внести следующий код: Листинг
#!/bin/sh
#
# MiniDLNA initscript
#
# Based on the mediatomb debian package.
# Original authors: Tor Krill
unset USER
# PATH should only include /usr/* if it runs after the mountnfs.sh script PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC=«DLNA/UPnP-AV media server» NAME=minidlnad DAEMON=/usr/local/sbin/minidlnad PIDDIR=/run/$NAME PIDFILE=$PIDDIR/$NAME.pid SCRIPTNAME=/etc/init.d/minidlna DEFAULT=/etc/default/minidlna
# Exit if the package is not installed [ -x $DAEMON ] || exit 0
# Read configuration variable file if it is present [ -r $DEFAULT ] && . $DEFAULT
# Load the VERBOSE setting and other rcS variables . /lib/init/vars.sh
# Define LSB log_* functions. # Depend on lsb-base (>= 3.0–6) to ensure that this file is present. . /lib/lsb/init-functions
# Do not start the daemon if NO_START is enabled in DEFAULT if [ »$START_DAEMON» != «yes» ] && [ »$1» != «stop» ]; then log_warning_msg »$NAME: Not starting $DESC.» log_warning_msg »$NAME: Disabled in $DEFAULT.» exit 0 fi
# Set the default configuration file if [ -z $CONFIGFILE ]; then CONFIGFILE=/etc/minidlna.conf fi
# Set the default log file if [ -z $LOGFILE ]; then LOGFILE=/var/log/minidlna.log fi
# Run as `minidlna' if USER is not specified or is `root' if [ -z $USER ]; then USER=minidlna fi
# If no group is specified, use USER if [ -z $GROUP ]; then GROUP=$USER fi
DAEMON_ARGS=»-f $CONFIGFILE -P $PIDFILE $DAEMON_OPTS»
# # Function that starts the daemon/service # do_start () { # Return # 0 if daemon has been started # 1 if daemon was already running # 2 if daemon could not be started touch $LOGFILE && chown $USER:$GROUP $LOGFILE || return 2 if [ ! -d $PIDDIR ]; then mkdir $PIDDIR || return 2 fi chown $USER:$GROUP $PIDDIR || return 2
start-stop-daemon --start --quiet --pidfile $PIDFILE \ --chuid $USER:$GROUP --exec $DAEMON --test > /dev/null \ || return 1 start-stop-daemon --start --quiet --pidfile $PIDFILE \ --chuid $USER:$GROUP --exec $DAEMON — \ $DAEMON_ARGS \ || return 2 }
# # Function that stops the daemon/service # do_stop () { # Return # 0 if daemon has been stopped # 1 if daemon was already stopped # 2 if daemon could not be stopped # other if a failure occurred start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME RETVAL=»$?» [ »$RETVAL» = 2 ] && return 2 # Wait for children to finish too if this is a daemon that forks # and if the daemon is only ever run from this initscript. start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON [ »$?» = 2 ] && return 2 # Many daemons don’t delete their pidfiles when they exit. rm -rf $PIDDIR return »$RETVAL» }
case »$1» in start) [ »$VERBOSE» != no ] && log_daemon_msg «Starting $DESC » »$NAME» do_start case »$?» in 0×1) [ »$VERBOSE» != no ] && log_end_msg 0;; 2) [ »$VERBOSE» != no ] && log_end_msg 1;; esac ;; stop) [ »$VERBOSE» != no ] && log_daemon_msg «Stopping $DESC» »$NAME» do_stop case »$?» in 0×1) [ »$VERBOSE» != no ] && log_end_msg 0;; 2) [ »$VERBOSE» != no ] && log_end_msg 1;; esac ;; status) status_of_proc -p »$PIDFILE» »$DAEMON» »$NAME» && exit 0 || exit $? ;; restart|force-reload) log_daemon_msg «Restarting $DESC» »$NAME» do_stop case »$?» in 0×1) if [ »$1» = «force-reload» ]; then # Rescan the collection DAEMON_ARGS=»$DAEMON_ARGS -R» fi do_start case »$?» in 0) log_end_msg 0;; 1) log_end_msg 1;; # Old process is still running *) log_end_msg 1;; # Failed to start esac ;; *) # Failed to stop log_end_msg 1 ;; esac ;; *) echo «Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}» >&2 exit 3 ;; esac
: , сохранить комбинацией клавиш Ctrl+O и выйти из редактора — Ctrl+X.4) После этого даем права на запуск скрипта:
sudo chmod 755 /etc/init.d/minidlna 5) И активируем запуск init-скрипта: sudo update-rc.d minidlna defaults 6) Так как по умолчанию служба запускается под пользователем minidlna, нам нужно создать соответствующую учетную запись: sudo adduser --system --home /var/lib/minidlna --group --gecos «MiniDLNA server» minidlna 7) Правим файл конфигурации сервера: sudo nano /etc/minidlna.conf В нем нам нужно следующее содержимое (здесь подправлен интервал, с которым сервер себя анонсирует, так как не все телевизоры опрашивают сервер, также вам надо прописать путь к папке с медиа, к примеру так: «media_dir=V,/mnt/sdb6/Video/Alex/» в соответствующем разделе файла): Листинг minidlna.conf # Порт сервера port=8200
# Привязка к сетевому интерфейсу # Можно задать несколько интерфейсов # в формате network_interface=eth0, eth1 #network_interface=eth0
# Имя пользователя или UID, под которым будет работать служба # Добавлен в версии 1.1.0 # В Debian задается в параметрах init-скрипта #user=jmaggard
# Путь к папке с медиа-файлами # Для сканирования нескольких папок, укажите несколько параметров media_dir # Чтобы сканировать файлы определенного типа, укажите соответствующий префикс: # A — аудио: media_dir=A,/home/jmaggard/Music # V — видео: media_dir=V,/home/jmaggard/Videos # P — изображения: media_dir=P,/home/jmaggard/Pictures # Начиная с версии 1.1.0, можно задать несколько типов: # PV — изображения и видео: media_dir=AV,/var/lib/minidlna/digital_camera # # При изменении параметра, потребуется повторное сканирование файлов. # Необходимо выполнить команду «service minidlna force-reload» от имени root. # Начиная с версии 1.1.0, при изменении параметра, сканирование выполняется автоматически. media_dir=/var/lib/minidlna
# Имя DLNA-сервера, отображаемое клиентом # По умолчанию:»$HOSTNAME:$USER» #friendly_name=
# Путь к папке для хранения базы данных и кэша обложек альбомов db_dir=/var/lib/minidlna
# Путь к папке с лог-файлами log_dir=/var/log
# Уровень детальности лога # В формате log_level=источник1, источник2=значение1, источник3, источник4=значение2 … # Доступные источники: «general», «artwork», «database», «inotify», «scanner», «metadata», «http», «ssdp», «tivo» # Возможные значения: «off», «fatal», «error», «warn», «info» or «debug» #log_level=general, artwork, database, inotify, scanner, metadata, info, ssdp, tivo=warn
# Перечень имен файлов-обложек альбомов, разделитель:»/» album_art_names=Cover.jpg/cover.jpg/AlbumArtSmall.jpg/albumartsmall.jpg/AlbumArt.jpg/albumart.jpg/Album.jpg/album.jpg/Folder.jpg/folder.jpg/Thumb.jpg/thumb.jpg
# Автообнаружение новых файлов # Включено по умолчанию inotify=yes
# Поддержка устройств TiVo #enable_tivo=no
# Строго следовать DLNA-стандарту # Использовать серверное масштабирование для очень больших JPEG-изображений # Что может снизить скорость их обработки. #strict_dlna=no
# Адрес веб-страницы устройства # По умолчанию IP-адрес и заданный порт сервера #presentation_url=http://www.mylan/index.php
# Интервал отправки SSDP-уведомлений, в секундах notify_interval=30
# Серийный номер и номер модели DLNA-сервера, сообщаемый клиенту serial=12345678 model_number=1
# Путь к сокету MiniSSDPd, если установлен # Требуется для обеспечения работы нескольких DLNA/UPnP служб на одном сервере #minissdpdsocket=/run/minissdpd.sock
# Контейнер, используемый в качестве корневой папки для клиентов # * ».» — стандартный контейнер # * «B» — «Обзор папки» # * «M» — «Музыка» # * «V» — «Видео» # * «P» — «Изображения» # Если задано «B» и клиент представится как аудиоплеер, в качестве корня будет использована папка «Music/Folders» #root_container=.
# Всегда использовать заданный критерий сортировки, вместо значения, запрошенного клиентом #force_sort_criteria=+upnp: class,+upnp: originalTrackNumber,+dc: title
# Максимальное число одновременных подключений # Учтите: многие клиенты открывают несколько подключений одновременно #max_connections=50 8)Затем проверяем параметры init-скрипта /etc/default/minidlna: sudo nano /etc/default/minidlna Обычно корректировка не требуется. Если файл отсутствует, при первичной установке из исходников, копируем листинг: # Запускать демон, если задано «yes» START_DAEMON=«yes»
# Путь к файлу конфигурации #CONFIGFILE=»/etc/minidlna.conf»
# Путь к лог-файлу #LOGFILE=»/var/log/minidlna.log»
# Запуск от имени заданного пользователя и группы # По умолчанию: minidlna #USER=«minidlna» #GROUP=«minidlna»
# Дополнительные ключи запуска DAEMON_OPTS=» Обычно после этого не требуется дополнительных настроек, но если есть проблемы с доступом к медиа (или хотите перестраховаться), можно настроить права доступа: Настройка прав доступа: Поскольку служба работает под пользователем с ограниченными правами, публикуемые папки и файлы должны быть доступны на чтение для всех пользователей, следовательно, иметь разрешения 644: «rw- r-- r--», для файлов и 755: «rwx r-x r-x», для папок.Проверяем доступность для каждой папки, заданной в minidlna.conf, командой:
sudo -u minidlna ls -l папка Если папка недоступна, задаем права доступа: sudo chmod -R 755 папка Вышестоящие папки также должны быть доступны на чтение всем пользователям. Проверяем доступность на чтение каждой папки, указанной в пути. Для вышестоящих папок используем chmod без ключа -R, если не требуется сброс разрешений для всех дочерних файлов и папок.В качестве альтернативы смене разрешений, можно запустить MiniDLNA от имени пользователя или группы-владельца файлов. Для этого необходимо задать параметры USER и GROUP в /etc/default/minidlna, и сменить владельца папки /var/lib/minidlna командой: sudo chown -R пользователь: группа /var/lib/minidlna Запуск сервера Запускаем: sudo service minidlna force-reload Проверяем, работает ли служба, также смотрим параметры запуска:
ps ax | grep minidlna Проверяем, слушается ли порт:
sudo ss -4lnp | grep minidlna Проверяем лог:
cat /var/log/minidlna.log В случае успешного старта, лог должен быть примерно следующим:
Gothician gothician # cat /var/log/minidlna.log [2014/07/27 10:05:31] minidlna.c:1014: warn: Starting MiniDLNA version 1.1.3. [2014/07/27 10:05:31] minidlna.c:355: warn: Creating new database at /var/lib/minidlna/files.db [2014/07/27 10:05:31] minidlna.c:1053: warn: HTTP listening on port 8200 [2014/07/27 10:05:31] scanner.c:706: warn: Scanning /var/lib/minidlna [2014/07/27 10:05:31] scanner.c:793: warn: Scanning /var/lib/minidlna finished (0 files)! [2014/07/27 10:05:31] playlist.c:125: warn: Parsing playlists… [2014/07/27 10:05:31] playlist.c:259: warn: Finished parsing playlists. [2014/08/03 09:25:35] minidlna.c:1053: warn: HTTP listening on port 8200 Если видим: «WARNING: Inotify max_user_watches [8192] is low.», необходимо увеличить число дескрипторов слежения inotify до 100 000. Для этого в файл /etc/sysctl.conf добавим строки:
#MiniDLNA warning fix fs.inotify.max_user_watches = 100000 Вручную редактором:
sudo nano /etc/sysctl.conf Или копипастом команды:
sudo sh -c 'printf »\n\n#MiniDLNA warning fix\nfs.inotify.max_user_watches = 100000\n» >> /etc/sysctl.conf && cat /etc/sysctl.conf' Изменение параметра вступит в силу после перезагрузки системы.Открываем в браузере адрес.сервера:8200, видим количество файлов в библиотеке, начиная с версии 1.1.2, также отображается список подключенных клиентов.
Настройка DLNA/UPnP-AV сервера завершена.
При появлении ошибок в каталоге, необходимо выполнить повторное сканирование файлов.При использовании приведенного выше init-скрипта, для запуска сканирования медиа-библиотеки используем команду:
sudo service minidlna force-reload Служба при этом будет перезапущена, подключенные клиенты будут отключены.
Для сканирования медиа-библиотеки при каждом старте системы можно задать ключ запуска:»-R» в параметре DAEMON_OPTS в файле /etc/default/minidlna. Сканирование большой медиа-библиотеки существенно нагружает диск, что может замедлить загрузку системы.
Полное формирование каталога может занять несколько минут. Сканирование папок выполняется в порядке их объявления в конфиге. Файлы из небольших папок, объявленных в конфиге выше, появятся в каталоге в самом начале процесса сканирования. Крупные папки с редко воспроизводимым контентом имеет смысл размещать в конфиге последними.
Все это опробовано на своей системе, пользуйтесь на здоровье. Надеюсь, количество пользователей Linux будет постоянно увеличиваться.
По материалам http://itadept.ru/, wiki.archlinux.org.