Open Graph тэги вручную для тем WordPress

open-graph-facebookДля начала нужно заменить стандартный тег <html> на тот, что нам нужен. Открываете файл header.php и заменяете стандартный тег:

<html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>

на этот код:

<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:fb="http://ogp.me/ns/fb#" 
      xmlns:og="http://ogp.me/ns#" <?php language_attributes(); ?>>

В этом же файле header.php перед закрывающим тегом </head> вставляете код тегов Open Graph Facebook:

<!--Open Graph Facebook-->

<?php if (have_posts()):while(have_posts()):the_post(); endwhile; endif;?>  

<!-- постоянные значения -->  

<meta property="fb:admins" content="ВАШ_ЛИЧНЫЙ_ID_FACEBOOK" />  

<!-- если это статья -->  

<?php if (is_single()) { ?>  
<meta property="og:url" content="<?php the_permalink(); ?> "/>  
<meta property="og:title" content="<?php single_post_title(''); ?>" />  
<meta property="og:description" 
         content="<?php echo strip_tags(get_the_excerpt($post->ID)); ?>" />  
<meta property="og:type" content="article" />  
<meta property="og:image" 
content="<?php if (function_exists('wp_get_attachment_thumb_url')) {echo 
wp_get_attachment_thumb_url(get_post_thumbnail_id($post->ID)); } ?>" />  

<!-- если это любая другая страница -->  

<?php } else { ?>  
<meta property="og:site_name" content="<?php bloginfo('name'); ?>" />  
<meta property="og:description" 
       content="<?php bloginfo('description'); ?>" />  
<meta property="og:type" content="website" />  
<meta property="og:image" content="http://ПУТЬ-К-КАРТИНКЕ/КАРТИНКА.jpg" /> 
<?php } ?>

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

Сохраняете изменения и проверяете работу тегов Open Graph, нажав на кнопку «Мне нравится» в любой статье блога.

Может быть ситуация, при которой картинка статьи всё равно публикуется некорректно или вся статья просто не отображается (как было у меня). Это значит, что функция wp_get_attachment_thumb_url() не работает. Тогда необходимо сделать следующие действия.

Замените этот тег:

<meta property="og:image" 
content="<?php if (function_exists('wp_get_attachment_thumb_url')) {echo 
wp_get_attachment_thumb_url(get_post_thumbnail_id($post->ID)); }?>" />

на этот тег:

<meta property="og:image" 
      content="<?php if (function_exists('catch_that_image')) 
      {echo catch_that_image(); }?>" />

Сохраните изменения. Затем справа в панели управления найдите ссылку на файл «Функции темы» (functions.php), откройте его и в конце кода перед знаком ?> вставьте следующий код:

function catch_that_image() {  
    global $post, $posts;  
    $first_img = '';  
    ob_start();  
    ob_end_clean();  
    $output = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"] title="3 варианта, как настроить теги Open Graph Facebook для WordPress?" alt="3 варианта, как настроить теги Open Graph Facebook для WordPress?">/i', $post->post_content, $matches);  
    $first_img = $matches [1] [0];  
    if(empty($first_img)){  
            //Определяет картинку по умолчанию 
            $first_img = "http://ПУТЬ_К_КАРТИНКЕ_ПО_УМОЛЧАНИЮ/ФОТО.jpg";  
        }  
    return $first_img;  
}

Этот код описывает функцию catch_that_image(), которая находит первую картинку в статье блога и вставляет её ссылку в тег изображения Open Graph. Если в статье нет картинки, то эта функция использует изображение по умолчанию. Для этого вставьте ссылку нужного изображения в эту переменную:

$first_img = "http://ПУТЬ_К_КАРТИНКЕ_ПО_УМОЛЧАНИЮ/ФОТО.jpg";

Теперь сохраняйте изменения в файле functions.php, заходите на блог и проверяйте работу кнопок «Мне нравится». Всё должно работать корректно.

Compiling Kernel 3.8 on Debian Testing/Wheezy

linuxNOTE: It seems like series 3.8 has issues with intel (i915) graphics — it occasionally generates kworker threads that causes unresponsiveness as seen by slow mouse and keyboard response when e.g. plugging or unplugging mains power. No issues on e.g. nvidia though.

http://verahill.blogspot.com.au/2013/03/368-slow-mouse-and-keyboard-triggered.html
http://forums.gentoo.org/viewtopic-p-7278760.html
https://bbs.archlinux.org/viewtopic.php?pid=1248190

Post: Kernel 3.8 is out now. Not much to say — the compilation works well using the standard method. The compressed kernel is about 81 Mb to download.

The approach below shows how to compile the kernel on Debian. If you’re interested in a more generic approach, see this post:

http://verahill.blogspot.com.au/2013/02/344-compile-kernel-38-without-using-kpkg.html

NOTE: kernel 3.8 — in contrast to the 3.7 series — now compiles fine on AMD FX 8150.

NOTE: kernel 3.8 plays well with nvidia dkms

Here we go:

sudo apt-get install kernel-package fakeroot build-essential ncurses-dev
mkdir ~/tmp
cd ~/tmp
wget http://www.kernel.org/pub/linux/kernel/v3.0/linux-3.8.tar.bz2
tar xvf linux-3.8.tar.bz2
cd linux-3.8/
cat /boot/config-`uname -r`>.config
make oldconfig

You will be asked a lot of questions — how many depends on what version you upgrade from. If in doubt, pick the default answer (i.e. hit enter). If really in doubt, use google.

Then continue:

make-kpkg clean

Do

make menuconfig

if you want to make any specific changes to the kernel (e.g. add support for certain devices)

Then continue:

time fakeroot make-kpkg -j4 --initrd kernel_image kernel_headers
As usual 4 is the number of threads you wish to launch — make it equal to the number of cores that you have for optimum performance during compilation (more about that here).
The build takes around 20 minutes on a four-core intel i5-2400 with -j4, and 14 minutes on an fx-8150 with -j8 (96 minutes with -j1).
Install:
sudo dpkg -i ../linux-image-3.8.0_3.8.0-10.00.Custom_amd64.deb ../linux-headers-3.8.0_3.8.0-10.00.Custom_amd64.deb
New stuff/Questions:
Offload RCU callback processing from boot-selected CPUs (RCU_NOCB_CPU) [N/y/?] (NEW) *
Memory placement aware NUMA scheduler (NUMA_BALANCING) [N/y/?] (NEW) *
Enable to assign a node which has only movable memory (MOVABLE_NODE) [N/y/?] (NEW)
Allow for memory hot-add (MEMORY_HOTPLUG) [Y/n] y
Allow for balloon memory compaction/migration (BALLOON_COMPACTION) [Y/n/?] (NEW)
Set default setting of cpu0_hotpluggable (BOOTPARAM_HOTPLUG_CPU0) [N/y/?] (NEW
Debug CPU0 hotplug (DEBUG_HOTPLUG_CPU0) [N/y/?] (NEW)
ACPI tables can be passed via uncompressed cpio in initrd (ACPI_INITRD_TABLE_OVERRIDE) [N/y/?] (NEW)
Support multiple cpuidle drivers (CPU_IDLE_MULTIPLE_DRIVERS) [N/y/?] (NEW)
"NOTRACK" target support (DEPRECATED) (NETFILTER_XT_TARGET_NOTRACK) [N/m] (NEW

Default SCTP cookie HMAC encoding
  > 1. Enable optional MD5 hmac cookie generation (SCTP_DEFAULT_COOKIE_HMAC_MD5) (NEW)
    2. Enable optional SHA1 hmac cookie generation (SCTP_DEFAULT_COOKIE_HMAC_SHA1) (NEW)
    3. Use no hmac alg in SCTP cookie generation (SCTP_DEFAULT_COOKIE_HMAC_NONE) (NEW)
  choice[1-3?]:   Enable optional MD5 hmac cookie generation (SCTP_COOKIE_HMAC_MD5) [Y/?] (NEW) y

Enable optional SHA1 hmac cookie generation (SCTP_COOKIE_HMAC_SHA1) [N/y/?] (NEW) *
Enable optional MD5 hmac cookie generation (SCTP_COOKIE_HMAC_MD5) [Y/?] (NEW) y
Distributed ARP Table (BATMAN_ADV_DAT) [N/y/?] (NEW)
Kvaser CAN/USB interface (CAN_KVASER_USB) [N/m/?] (NEW)
LSI MPT Fusion SAS 3.0 Device Driver (SCSI_MPT3SAS) [N/m/?] (NEW)
Chelsio Communications FCoE support (SCSI_CHELSIO_FCOE) [N/m/?] (NEW) *
Marvell 88E6060 ethernet switch chip support (NET_DSA_MV88E6060) [N/m/y/?] (NEW)
Marvell 88E6085/6095/6095F/6131 ethernet switch chip support (NET_DSA_MV88E6131) [N/m/y/?] (NEW)
Marvell 88E6123/6161/6165 ethernet switch chip support (NET_DSA_MV88E6123_61_65) [N/m/y/?] (NEW) *
Cadence devices (NET_CADENCE) [Y/n/?] (NEW)
AT91RM9200 Ethernet support (ARM_AT91_ETHER) [N/m/y/?] (NEW)
Cadence MACB/GEM support (MACB) [N/m/y/?] (NEW)
Broadcom devices (NET_VENDOR_BROADCOM) [Y/?] y
Marvell MDIO interface support (MVMDIO) [N/m/y/?] (NEW)
CDC MBIM support (USB_NET_CDC_MBIM) [N/m/?] (NEW)
Atheros Wireless Cards (ATH_CARDS) [N/m/?] (NEW)
Atheros AR5523 wireless driver support (AR5523) [N/m/?] (NEW)
Wilocity 60g WiFi card wil6210 support (WIL6210) [N/m/?] (NEW) *
Realtek RTL8723AE PCIe Wireless Network Adapter (RTL8723AE) [N/m/?] (NEW)
ARC UART driver support (SERIAL_ARC) [N/m/y/?] (NEW) *
CBUS I2C driver (I2C_CBUS_GPIO) [N/m/?] (NEW)
TS-5500 DIO blocks and compatibles (GPIO_TS5500) [N/m/y/?] (NEW) 
TI BQ2415x battery charger driver (CHARGER_BQ2415X) [N/m/?] (NEW)
Board level reset or power off (POWER_RESET) [N/y/?] (NEW) *

 Default Thermal governor
  > 1. step_wise (THERMAL_DEFAULT_GOV_STEP_WISE) (NEW)
    2. fair_share (THERMAL_DEFAULT_GOV_FAIR_SHARE) (NEW)
    3. user_space (THERMAL_DEFAULT_GOV_USER_SPACE) (NEW)
  choice[1-3?]:   Fair-share thermal governor (FAIR_SHARE) [N/y/?] (NEW)

Step_wise thermal governor (STEP_WISE) [Y/?] (NEW) y
User_space thermal governor (USER_SPACE) [N/y/?] (NEW)
SSB GPIO driver (SSB_DRIVER_GPIO) [N/y/?] (NEW) *
BCMA GPIO driver (BCMA_DRIVER_GPIO) [N/y/?] (NEW)
Support for Realtek PCI-E card reader (MFD_RTSX_PCI) [N/m/y/?] (NEW)
TI ADC / Touch Screen chip support (MFD_TI_AM335X_TSCADC) [N/m/y/?] (NEW)
Support for Nano River Technologies Viperboard (MFD_VIPERBOARD) [N/m/?] (NEW)
Support for Retu multi-function device (MFD_RETU) [N/m/?] (NEW) *
Maxim MAX8973 voltage regulator  (REGULATOR_MAX8973) [N/m/?] (NEW)
TI TPS51632 Power Regulator (REGULATOR_TPS51632) [N/m/?] (NEW)
Siano SMS1xxx based MDTV receiver (SMS_USB_DRV) [N/m/?] (NEW)
Siano SMS1xxx based MDTV via SDIO interface (SMS_SDIO_DRV) [N/m/?] (NEW)   *
Stanton Control System 1 MIDI (SND_SCS1X) [N/m/?] (NEW) *
ION iCade arcade controller (HID_ICADE) [N/m/?] (NEW)
HID over I2C transport layer (I2C_HID) [N/m/?] (NEW) *
Renesas R-Car USB phy support (USB_RCAR_PHY) [N/m/?] (NEW)   *
SDHCI support for ACPI enumerated SDHCI controllers (MMC_SDHCI_ACPI) [N/m/?] (NEW)
NXP PCF8523 (RTC_DRV_PCF8523) [N/m/?] (NEW)
Philips PCF8563/Epson RTC8564 (RTC_DRV_PCF8563) [M/n/?] m
Userspace platform driver with generic irq and dynamic memory (UIO_DMEM_GENIRQ) [N/m/?] (NEW)
Microsoft Hyper-V Balloon driver (HYPERV_BALLOON) [N/m/?] (NEW) *
SystemBase PCI Multiport UART (SB105X) [N/m/y/?] (NEW)
TTY over Firewire (FIREWIRE_SERIAL) [N/m/?] (NEW) *
F2FS filesystem support (EXPERIMENTAL) (F2FS_FS) [N/m/y/?] (NEW) *
Enable CIFS debugging routines (CIFS_DEBUG) [Y/n/?] (NEW)
Simplified Mandatory Access Control Kernel Support (SECURITY_SMACK) [N/y/?] (NEW)
Camellia cipher algorithm (x86_64/AES-NI/AVX) (CRYPTO_CAMELLIA_AESNI_AVX_X86_64) [N/m/y/?] (NEW)

Поиск файлов в Linux

find

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

0. Создадим файл размером 10 Мбайт с размером блока 100 Кбайт:

rootoor@srv:~/dd-test$ dd if=/dev/zero of=file1.test bs=100K count=100
100+0 записей считано
100+0 записей написано
скопировано 10240000 байт (10 MB), 0,0448225 c, 228 MB/c

rootoor@srv:~/dd-test$ ls -l
итого 10000
-rw-r--r-- 1 rootoor rootoor 10240000 2013-05-05 13:47 file1.test

rootoor@srv:~/dd-test$

/dev/zero – специальный файл в UNIX-подобных системах, представляющий собой источник нулевых байтов (ASCII NUL, 0x00)

of=file.test – файл который создаем

bs=100K – размер блока, 100 КБайт (может быть: К — КБайт, М — МБайт, — ГБайт)

count=100 – количество блоков

В результате мы получили заданный файл, размером 100К*100=10 МБ

rootoor@srv:~# dd if=/dev/zero of=/var/www/file1.test bs=1M count=52
52+0 records in
52+0 records out
54525952 bytes (55 MB) copied, 0.453559 s, 120 MB/s

теперь в директории /var/www/ находится файл file1.test размером 52 МБ.

1. Поиск файлов в текущей директории размером больше 10 Мбайт

rootoor@srv:/var/www$ find . -size +10M -print
./var/www/file1.test

find – утилита для поиска файлов

. – где ищем. В нашем случае текущей директории (/var/www/* – поиск в директории /var/www/~ — поиск в домашней директории/ – поиск в корне файловой системы$HOME – поиск в домашней директории )

-size +10M – размер искомого файла. Больше 10 Мбайт (b – блок, размером 512 байт, c – байт, w – слово, размером 2 байта, k – килобайт, M – мегабайт и G– гигабайт )

-print – вывод на экран

2. Поиск файлов больше 50 Мб с выводом детальной информации

Усложним задачу и попробуем вывести на экран кроме имени файла еще некоторую информацию о нем.

rootoor@srv:~# find /var/www/* -type f -size +50000k -exec ls -lh {} \; | awk '{ print $8 " " $5 " " $1 " " $3":"$4 }'

./var/www/test1.file 110M -rw-r--r-- rootoor:rootoor
./var/www/file1.test 52M -rw-r--r-- rootoor:rootoor

-type f – тип, который ищем (f – файл, d – директория, l – символичная ссылка, s – сокет, b – блок)

-exec ls -lh {} \; – выполняет команду ls -lh над найденными файлами (вывод содержимого директории)

awk ‘{ print $8 » » $5 » » $1 » » $3″:»$4 }’ – обрабатываем вывод информации командой ls -lh

и выводим более детальную информацию в нужном нам порядке:
$8 – имя файла
$5 – размер файла
$1 – права доступа
$3 – владелец
$4 – группа

3. Поиск файлов заданного размера и определенного имени

rootoor@srv:~# find $HOME -name w*  -size +1M -exec ls -lh {} \; | awk '{ print $8 " " $5 }'

/home/rootoor/kawabanga.tar.gz 17M

-name w* – любой файл имя, которого содержит w*

 

Разделение большого файла на несколько частей

Split

$ split --bytes=<размер части> <исходный файл> <префикс имени части>

Размер частей может иметь суффикс, означающий множитель.

b — 512
kB — 1000
K — 1024
MB — 1000*1000
M — 1024*1024
GB — 1000*1000*1000
G — 1024*1024*1024

и так далее для T, P, E, Z, Y.

Пример:

$ split -a 1 -d -b 100M big.iso small.iso.part

Получим много файлов по 100 Мб, с суффиксами part0, part1, part2, part3…:

small.iso.part0
small.iso.part1
small.iso.part2
small.iso.part3

и т.д.

Чтобы снова объединить все части воедино, можно использовать команду cat:

$ cat small.iso.part* > big.iso

Утилита cat соберет все файлы, начиная с small.iso.part0.

Бесплатные DNS-сервера

DNS-servers

Primary only:
primaryns.kiev.ua — доступен только для Украины

Primary and secondary:
zoneedit.com — 5 доменов, меня все устраивает
everydns.net — 20 доменов, нет email-forwarding
dnspark.com — 3 домена
soa.granitecanyon.com — доменов неограничено
domain-dns.com — доменов неограничено, нельзя создавать NS-записи
xname.org
mydomain.com — очень перегружен, очень тормознут
dns.xtremeweb.de = gratisdns.de — нету mail-forwarding
freedns.afraid.org — нет описания
editdns.net — нет описания
prosto.name — Хороший новенький русский сервис
dnsexit.com
1gb.ru
freedns.sgh.waw.pl — как xname.org
freedns.ws
namecheap.com
www.netbreeze.net/dns/ — панель на русском
help.yandex.ru/pdd/hosting.xml

Secondary only:
ns2.trifle.net
secondary.net.ua

Оперативная реакция на DDoS-атаки

DDoS-network-mapОдин из ресурсов, за которым я присматриваю, вдруг стал неожиданно популярным как у хороших пользователей, так и у плохих. Мощное, в общем-то, железо перестало справляться с нагрузкой. Софт на сервере самый обычный — Linux, Nginx, PHP-FPM (+APC), MySQL, версии — самые последние. На сайтах крутится Drupal и phpBB. Оптимизация на уровне софта (memcached, индексы в базе, где их не хватало) чуть помогла, но кардинально проблему не решила. А проблема — большое количество запросов, к статике, динамике и особенно базе. Поставил следующие лимиты в Nginx:

на соединения

limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn perip 100;

и скорость запросов на динамику (fastcgi_pass на php-fpm)

limit_req_zone $binary_remote_addr zone=dynamic:10m rate=2r/s;
limit_req zone=dynamic burst=10 nodelay;

Сильно полегчало, по логам видно, что в первую зону никто не попадает, зато вторая отрабатывает по полной.

Но плохиши продолжали долбить, и захотелось их отбрасывать раньше — на уровне фаервола, и надолго.

Сначала сам парсил логи, и особо настырных добавлял через iptables в баню. Потом парсил уже по крону каждые 5 минут. Пробовал fail2ban. Когда понял, что плохишей стало очень много, перенёс их в ipset ip hash.

Почти всё хорошо стало, но есть неприятные моменты:
— парсинг/сортировка логов тоже приличное (процессорное) время отнимает
— сервер тупит, если началась новая волна между соседними разборками (логов)

Нужно было придумать как быстро добавлять нарушителей в черный список. Сначала была идея написать/дописать модуль к Nginx + демон, который будет ipset-ы обновлять. Можно и без демона, но тогда придётся запускать Nginx от рута, что не есть красиво. Написать это реально, но понял, что нет столько времени. Ничего похожего не нашёл (может плохо искал?), и придумал вот такой алгоритм.

При привышении лимита, Nginx выбрасывает 503-юю ошибку Service Temporarily Unavailable. Вот я решил на неё и прицепиться!

Для каждого location создаём свою страничку с ошибкой

error_page 503 =429 @blacklist;

И соответствующий именованный location

location @blacklist {
    fastcgi_pass    localhost:1234;
    fastcgi_param   SCRIPT_FILENAME    /data/web/cgi/blacklist.sh;
    include         fastcgi_params;
}

Дальше интересней.

Нам нужна поддержка CGI-скриптов. Ставим, настраиваем, запускаем spawn-fcgi и fcgiwrap. У меня уже было готовое для collectd.

Сам CGI-скрипт fc

#!/bin/bash

BAN_TIME=5
DB_NAME="web_black_list"
SQLITE_DB="/data/web/cgi/${DB_NAME}.sqlite3"
CREATE_TABLE_SQL="\
CREATE TABLE $DB_NAME (\
    ip varchar(16) NOT NULL PRIMARY KEY,\
    added DATETIME NOT NULL DEFAULT (DATETIME()),\
    updated DATETIME NOT NULL DEFAULT (DATETIME()),\
    counter INTEGER NOT NULL DEFAULT 0
)"
ADD_ENTRY_SQL="INSERT OR IGNORE INTO $DB_NAME (ip) VALUES (\"$REMOTE_ADDR\")"
UPD_ENTRY_SQL="UPDATE $DB_NAME SET updated=DATETIME(), counter=(counter+1) WHERE ip=\"$REMOTE_ADDR\""
SQLITE_CMD="/usr/bin/sqlite3 $SQLITE_DB"
IPSET_CMD="/usr/sbin/ipset"

$IPSET_CMD add $DB_NAME $REMOTE_ADDR > /dev/null 2>&1

if [ ! -f $SQLITE_DB ]; then
     $SQLITE_CMD "$CREATE_TABLE_SQL"
fi

$SQLITE_CMD "$ADD_ENTRY_SQL"
$SQLITE_CMD "$UPD_ENTRY_SQL"

echo "Content-type: text/html"
echo ""

echo "<html>"
echo "<head><title>429 Too Many Requests</title></head>"
echo "<body bgcolor=\"white\">"
echo "<center><h1>429 Too Many Requests</h1></center>"
echo "<center><small><p>Your address ($REMOTE_ADDR) is blacklisted for $BAN_TIME minutes</p></small></center>"
echo "<hr><center>$SERVER_SOFTWARE</center>"
echo "</body>"
echo "</html>"

Собственно всё очевидно, кроме, разве что, SQLite. Я его добавил пока просто для статистики, но в принципе можно использовать и для удаления устаревших плохишей из черного списка. Время 5 минут пока тоже не используется.

Черный список создавался вот так

ipset create web_black_list hash:ip

Правило в iptables у каждого может быть своё, в зависимости от конфигурации и фантазии.

З.Ы.: Улыбнуло сообщение одного «хакера» на форуме, как быстро он положил сервер. Он и не догадывался, что это сервер положил на него.

Источник: http://habrahabr.ru/post/176119/

Установка Django 1.4 на хостинг NIC.RU

django-logo-positiveУстанавливаем Django:

1. Создать файл ~/.pydistutils.cfg со следующим содержимым:

[install]
prefix=/home/$USER/.python

2. Создать файл ~/.bashrc со следующим содержимым:

export PATH="${PATH}":/home/$USER/.python/bin
export PYTHONPATH="${PYTHONPATH}":/home/$USER/.python/lib/python2.6/site-packages;

3. Создаём директории:

mkdir -p /home/$USER/.python/lib/python2.6/site-packages

4. Выполняем

source ~/.bashrc

5. Загружаем и устанавливаем Django:

wget https://www.djangoproject.com/download/1.4/tarball/
tar xzvf Django-1.4.tar.gz
cd Django-1.4
python setup.py install

6. Проверяем версию

django-admin.py --version

Таким же образом мы можем ставить и любые django-python модули.

Сервер онлайн-вещаний на базе nginx

776px-Nginx-battleship.svgВведение

Привет всем! Несколько месяцев назад на Хабре была опубликована статья «Вещание онлайн-видео с помощью nginx», в которой Aecktann рассказал о своем опыте внедрения разрабатываемого мной (rarutyunyan) модуля к nginx для вещания видео — nginx-rtmp-module. С тех пор продукт активно развивался и в этой статье я более подробно расскажу о нем.

Вещатель нужен для передачи видео-потока клиенту. Речь идет либо о живом потоке, либо о вещании записанного видео (VOD, Video-on-demand). Существует большое количество технологий вещания видео. Среди них можно выделить традиционные протоколы, такие как RTMP или MPEG-TS, а также появившиеся в последнее время технологии адаптивного вещания поверх HTTP. К последним относятся HLS (Apple), HDS (Adobe), Smooth Streaming (Microsoft), MPEG-DASH. При выборе технологии основным фактором является ее поддержка на клиентской стороне. Именно поэтому вещание в формате RTMP на текущий момент является одним из самых распространенных. Протокол HLS поддерживается устройствами компании Apple, а также некоторыми версиями Android.

Сборка и настройка nginx-rtmp

Для добавления модуля nginx-rtmp к nginx нужно указать его в опции —add-module при конфигурации nginx, как и любой другой модуль.

./configure --add-module=/path/to/nginx-rtmp-module

После сборки и инсталляции нужно добавить секцию rtmp{} в файл конфигурации nginx.conf. Добавлять ее надо в корень конфига. Например:

rtmp {
    server {
        listen 1935;
        application myapp {
            live on;
        }
    }
}

Для многих случаев этой простой конфигурации будет достаточно. В ней задается RTMP-приложение с именем myapp. В это приложение мы позже будем публиковать потоки и проигрывать их из него. У каждого потока также будет свое уникальное имя. Стоит отметить один важный нюанс, касающийся приведенной выше конфигурации. Она верна для того случая, когда число воркеров nginx равно единице (как правило, задается в начале nginx.conf).

worker_processes  1;

Чтобы иметь возможность использовать live вещания с бОльшим числом воркеров, нужно указать директиву rtmp_auto_push on (см. раздел «Воркеры и локальная ретрансляция»).

Публикация и проигрывание живого потока

Для публикации и проигрывания видео можно использовать Flash-проигрыватели (JWPlayer, FlowPlayer, Strobe и т.д.). Однако, для вещания серверных потоков и для тестирования часто используют ffmpeg (и ffplay). Начнем вещание тестового файла test.mp4 следующей командой:

ffmpeg -re -i /var/videos/test.mp4 -c copy -f flv rtmp://localhost/myapp/mystream

Тут надо учесть, что RTMP поддерживает ограниченый набор кодеков, впрочем, такие популярные кодеки, как H264 и AAC, входят в их число. Если кодеки в тестовом файле не совместимы с RTMP, потребуется перекодировка:

ffmpeg -re -i /var/videos/test.mp4 -c:v libx264 -c:a libfaac -ar 44100 -ac 2 -f flv rtmp://localhost/myapp/mystream

Вещать можно как поток из файла, так и из другого источника. Например, если предположить, что по адресу video.example.com/livechannel.ts вещается некий live MPEG-TS поток, то его также можно завернуть в rtmp:

ffmpeg -i http://video.example.com/livechannel.ts -c copy -f flv rtmp://localhost/myapp/mystream

Пример вещания с локальной веб-камеры:

ffmpeg -f video4linux2 -i /dev/video0 -c:v libx264 -an -f flv rtmp://localhost/myapp/mystream

Проиграть поток можно при помощи ffplay следующей командой:

ffplay rtmp://localhost/myapp/mystream

И, наконец, простой пример использования JWPlayer для проигрывания потока из браузера (полностью приведен в директории /test/www модуля):

<script type="text/javascript" src="/jwplayer/jwplayer.js"></script>
<div id="container">Loading the player ...</div>
    <script type="text/javascript">
        jwplayer("container").setup({
        modes: [
            {   type: "flash",
                src: "/jwplayer/player.swf",
                config: {
                    bufferlength: 1,
                    file: "mystream",
                    streamer: "rtmp://localhost/myapp",
                    provider: "rtmp",
                }
            }
        ]
});
</script>

Видео по запросу

Модуль поддерживает вещание видео-файлов в форматах mp4 и flv. Пример настройки:

application vod {
    play /var/videos;
}

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

ffplay rtmp://localhost/vod/movie1.mp4
ffplay rtmp://localhost/vod/movie2.flv

Ретрансляция

При построении распределенных систем важно иметь возможность ретрансляции потоков для балансировки нагрузки по большому числу серверов. Модуль реализует два типа ретрансляции: push и pull. Первый тип ретрансляции состоит в передаче на удаленный сервер локально публикуемого потока, а второй — в передаче удаленного
потока на локальный сервер. Пример push ретрансляции:

application myapp {
    live on;
    push rtmp://cdn.example.com;
}

В момент, когда начинается публикация по адресу rtmp://localhost/myapp/mystream, создается соединение с удаленным сервером и поток mystream публикуется далее на rtmp://cdn.example.com/myapp/mystream. При прекращении локальной публикации, соединение с cdn.example.com автоматически завершается.

Pull-ретрансляции выполняют обратную операцию:

application myapp {
    live on;
    pull rtmp://cdn.example.com;
}

В этом примере при появлении клиента, желающего локально проиграть поток rtmp://localhost/myapp/mystream, будет создано соединение с rtmp://cdn.example.com/myapp/mytstream и удаленный поток будет ретранслирован на локальный сервер, после чего станет доступным всем локальным клиентам. В тот момент, когда не останется ни одного клиента, соединение будет завершено.

Вещание на мобильные устройства (HLS)

Для вещания на устройста iPhone/iPad, а также на новые версии Android, используется протокол HLS (HTTP Live Streaming).

Протокол был разработан компанией Apple и представляет из себя «нарезанный» на куски MPEG-TS/H264/AAC поток, отдаваемый по HTTP. К потоку прилагается плейлист в формате m3u8. Отдавать HTTP nginx умеет отлично. Значит, надо лишь создать и обновлять плейлист и фрагменты HLS-потока, а также следить за удалением старых фрагментов. Для этого существует модуль nginx-rtmp-hls. Он находится в директории hls, однако не собирается по умолчанию т.к. требует библиотеки libavformat, входящей в пакет ffmpeg. Для сборки nginx с поддержкой HLS, надо добавить этот модуль явно при конфигурации:

./configure --add-module=/path/to/nginx-rtmp-module --add-module=/path/to/nginx-rtmp-module/hls

Так вышло, что некоторое время назад проект ffmpeg был форкнут. И теперь у нас есть два проекта — ffmpeg и avconv, а следовательно, тут же начали возникать проблемы совместимости (вернее, несовместимости) библиотек. Для сборки nginx-rtmp нужен оригинальный ffmpeg. В то же время, некоторые дистрибутивы Linux перешли на использование avconv, который для сборки не подойдет. На этот случай я написал подробнуюинструкцию.

Для генерации HLS достаточно указать следующие директивы:

application myapp {
    live on;
    hls on;
    hls_path /tmp/hls;
    hls_fragment 5s;
}

Ну и, наконец, в секции http{}, настроить отдачу всего, что связано с HLS:

location /hls {
    root /tmp;
}

Теперь публикуем поток mystream в приложение myapp, а в браузере iPhone набираем в строке адреса example.com/hls/mystream.m3u8. Кроме того, поток можно встроить в html тег video:

<video width="600" height="300" controls="1" autoplay="1" src="http://example.com/hls/mystream.m3u8"></video>

Отмечу, что для проигрывания на iPhone поток должен быть закодирован в H264 и AAC. Если исходный поток не соответствует этим условиям, необходимо настроить перекодирование.

Перекодирование

При вещании видео часто возникает необходимость перекодирования входящего потока в другое качество, либо другие кодеки. Эта задача по своей сути кардинально отличается от раздачи RTMP и, в отличие от последней, связана с высокими нагрузками на CPU, большим и активным потреблением памяти, часто опирается на использование многопоточности и является потенциально нестабильной. По этой причине она не должна включаться в основной процесс сервера, и в идеале должна выполняться отдельным процессом. Стоит отметить, что прекрасный инструмент для решения этой задачи уже существует — это все тот же ffmpeg. Он поддерживает огромное число кодеков, форматов и фильтров, позволяет использовать множество сторонних библиотек. Вместе с тем, он достаточно прост и активно поддерживается сообществом. Модуль nginx-rtmp предоставляет простой интерфейс для использования ffmpeg. Директива exec позволяет запустить внешнее приложение в момент публикации входящего потока. При завершении публикации приложение также принудительно завершается. Кроме того, поддерживается перезапуск запущенного приложения, если оно внезапно завершилось само.

application myapp {
    live on;
    exec ffmpeg -i rtmp://localhost/myapp/$name -c:v flv -c:a -s 32x32 -f flv rtmp://localhost/myapp32x32/$name;
}

application myapp32x32 {
    live on;
}

В этом примере ffmpeg используется для перекодирования входящего видео в Sorenson-H263, изменении его размера до 32х32 и публикации результата в приложение myapp32x32. Можно одновременно задать несколько директив exec, которые будут производить с потоком любые преобразования и публиковать результат в другие приложения как на локальный, так и на удаленный сервер. Директива поддерживает несколько переменных, среди которых $app (имя приложения) и $name (имя потока).

Воркеры и локальная ретрансляция

Как известно, nginx является однопоточным сервером. Для того, чтобы эффективно использовать все ядра современных процессоров, обычно он запускается в несколько воркеров. Обработка HTTP запросов как правило, происходит независимо друг от друга, и лишь в отдельных случаях (как, например, в случае с кешом), требуется осуществлять доступ к общим данным. Такие данные хранятся в разделяемой памяти.

При живом вещании ситуация иная. Все клиентские соединения, проигрывающие поток, очевидным образом зависят от соединения, публикующего этот поток. Использование разделяемой памяти в данном случае неэффективно, излишне трудоемко, привело бы к синхронизации и большой потере производительности. Поэтому для использования нескольких воркеров был реализован механизм внутренних ретрансляций через UNIX-сокеты. Собственно, такие ретрансляции практически ничем не отличаются от обычных внешних push-ретрансляций. Локальные ретрансляции включаются следующей директивой

rtmp_auto_push on;

Указывать ее надо в корневой секции конфигурационного файла. Отмечу, что локальные ретрансляции нужны только для живых вещаний.

Запись

Часто возникает необходимость записи на диск публикуемых потоков. Модуль позволяет записывать как отдельные данные из потока (аудио, видео, ключевые фреймы) так и поток целиком. Можно установить ограничение на размер файла, а также на число записываемых фреймов. Следующий пример включает запись первых 128К каждого потока.

record all;
record_path /tmp/rec;
record_max_size 128K;

Запись происходит в формате flv в директорию /tmp/rec.

Управлять записью можно в ручном режиме, включая и отключая ее при помощи http-запроса. Для этого используется control-модуль. Информацию о нем можно найти на сайте проекта.

Авторизация и бизнес-логика

Во многих случаях требуется ввести ограничения или учет операций публикации и проигрывания видео. Это бывает связано с логикой проекта, в котором он используется. Самый частый подобный случай — необходимость авторизации пользователя перед тем, как дать ему доступ к просмотру видео. Чтобы интегрировать бизнес-логику проекта в вещатель, в модуле реализованы HTTP-колбэки, такие как on_publish и on_play. Серверный код получает всю имеющуюся информацию о клиенте, включая его адрес, имя потока, адрес страницы и т.д. Если возвращается HTTP статус 2xx, то колбек считается завершенным успешно и работа клиента продолжается. В противном случае соединение разрывается.

on_publish http://example.com/check_publisher;
on_play http://example.com/check_player;

Статистика

В каждый момент времени к вашему серверу могут быть подсоединены тысячи клиентов. Естественно, нужен интерфейс, позвляющий увидеть их список, а также все основные характеристики публикуемых или проигрываемых ими потоков. Причем, важно, чтобы эту информацию можно быть как анализировать визуально, так и обрабатывать программно. Такой интерфейс у модуля nginx-rtmp существует. Чтобы его использовать, необходимо в http-секции nginx.conf прописать следующие директивы.

location /stat {
    rtmp_stat all;
    rtmp_stat_stylesheet stat.xsl;
}

location /stat.xsl {
    root /path/to/stat.xsl/dir/;
}

Директива rtmp_stat включает отдачу XML-документа с полным описанием live-клиентов, публикующих или проигрывающих потоки, списком приложений и серверов. Этот документ удобен для программной обработки, но для визуального анализа совершенно не годится. Чтобы иметь возможность просматривать список клиентов в браузере, директивой rtmp_stat_stylesheet задается относительный путь к таблице стилей XML (stat.xsl). Этот файл лежит в корне проекта. Надо настроить nginx на его раздачу по указанному урлу. Результат можно просматривать в браузере.

Существует возможность явно разрывать клиентские соединения. Для этого используется control-модуль, не описанный в статье.

Простое Интернет-радио

С самого начала статьи я постоянно употреблял слово «видео». Конечно, модуль может вещать не только видео, а также и аудио-потоки. Вот простой пример интернет-радиостанции на bash, вещающей mp3-файлы из /var/music. Этот поток может воспроизводить простой JWPlayer, встроенный в веб-страницу.

while true; do
    ffmpeg -re -i "`find /var/music -type f -name '*.mp3'|sort -R|head -n 1`" -vn -c:a libfaac -ar 44100 -ac 2 -f flv rtmp://localhost/myapp/mystream;
done

Совместимость

Модуль совместим со всем основным софтом, работающим с протоколом RTMP, включая FMS/FMLE, Wowza, Wirecast, протестирован с самыми распространенными флеш-проигрывателями JWPlayer, FlowPlayer, StrobeMediaPlayback, а также отлично работает с ffmpeg/avconv и rtmpdump.

Нагрузки

Модуль использует асинхронную однопоточную модель сервера nginx. Это позволяет добиться высокой производительности. Мы используем модуль на машинах Intel Xeon E5320/E5645 в режиме одного воркера. В этом режиме удается достигнуть максимальной пропускной способности имеющихся сетевых карт — 2Gbps. Пользователи модуля подтверждают сохранение этого же соотношения (2Gbps на ядро) в режиме локальной ретрансляции с несколькими воркерами. Практика показывает, что производительность вещателя обычно упирается в сеть, а не в CPU.

Прямых сравнений с другими продуктами я не проводил, однако, «тяжелые» многопоточные FMS, Wowza и Red5, будучи более функциональными, должны, в силу особенностей реализации, существенно проигрывать моему решению по числу одновременно подсоединенных клиентов и нагрузке на CPU. Это подтверждается многими пользователями, проводившими такие сравнения, в т.ч. в уже упомянутой мной статье.

Заключение

В заключение скажу, что модуль распространяется по лицензии BSD. Он собирается и работает под Linux, FreeBSD и MacOS. В статье описана лишь малая часть функционала nginx-rtmp-module. Желающие могут ознакомиться с проектом по ссылкам, приведенным ниже.

http://habrahabr.ru/post/162237/

Вещание онлайн-видео с помощью nginx

776px-Nginx-battleship.svgЧто такое онлайн-видео?

Под термином онлайн-видео я понимаю длительное вещание какого-то живого видеосигнала (к примеру, из телестудии). Традиционные средства отдачи видео (flv- и mp4-стриминг) в данном случае не работают, просто потому что файла, содержащего весь видеопоток, не существует.

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

RTMP-протокол

RTMP — Real Time Messaging Protocol (вики) — протокол, который обычно используется для раздачи живого видео- и аудиоконтента клиентам. Он удобен тем, что в AS3 есть его поддержка из коробки, требует не слишком много ресурсов на клиенте и поддерживает множество плюшек (например, трансляцию с переменными битрейтами и переключение клиентов на более высокое качество при наличии свободного канала).

NB: Помимо RTMP существует набор других протоколов вещания медиапотоков (RTSP, Apple HTTP Live Streaming и др.), но в этой статье они не рассматриваются.

Протокол RTMP — детище компании Adobe. Единственным официальным сервером, которым можно вещать RTMP-поток, является Adobe Flash Media Server. Его цена и производительность, к сожалению, оставляют желать лучшего, поэтому различными разработчиками были предприняты попытки создать более или менее совместимые альтернативные реализации протокола. К сожалению, у RTMP-протокола есть известные проблемы с лицензированием, к примеру, его официальная спецификация, если следовать ей строго, не позволяет написать работающий RTMP-сервер. Тем не менее, существует несколько реализаций:

  • Red5 — один из первых RTMP-серверов, написан на Java
  • Wowza — проприетарный RTMP-сервер, написан на Java. Помимо RTMP, поддерживает также RTSP, Apple HLS, и Smoothstreaming (Silverlight).
  • erlyvideo — свободный RTMP-сервер с отдельно распространяющимися проприетарными модулями, написан на Erlang. Проект пишется русскими программистами и активно развивается.

Java тормозит

В тестах, которые я проводил, Red5 и Wowza показали неприлично низкую производительность. При мегабитном видеопотоке Wowza при 1000 зрителей онлайн съедала уже около 300% процессорного времени (Intel Xeon E5607). Если требуется вещать хотя бы для 20000 человек онлайн, то нужно закупать 20 серверов? Это слишком дорого.

Что же делать?

Использовать неблокирующие операции. Тормоза в Wowza и Red5 следуют из-за далеко не самой оптимальной схемы обработки событий. Для реализации действительно быстрого стримингового сервера, нужно использовать эффективный метод обработки событий (для linux это epoll). Именно такую схему работы и реализовал Роман Арутюнян (блогgithub-профильrarutyunyan) в своём RTMP-сервере, реализованном как модуль к nginx.

nginx-rtmp-module

Достоинства:

  • Нереально шустрый. На том же физическом сервере, который я использовал для тестов Wowza, nginx выдержал 2500 мегабитных соединений на ядро, т.е. 10000 на весь сервер целиком.
  • Удобные конфиги :). После километровых XML-конфигов Wowza эти выглядят спасением.
  • Отзывчивость автора к фичреквестам.

Недостатки:

  • Проект молодой, наличествуют баги, которые, впрочем, оперативно исправляются.
  • Небольшая функциональность. Сервер вещает только в RTMP, перекодировка появилась буквально несколько дней назад, имеет статус экспериментальной и фактически является обёрткой над ffmpeg. UNIX-way во всей своей красе.
  • Нет многопоточности. Модуль может работать только в том случае, если nginx запускается с одним воркером. Для утилизации всех процессорных ядер нужно запускать несколько воркеров на разных IP-адресах и/или портах.

Многопоточность можно реализовать с помощью примерно такого костыля (Ubuntu):

    for ip in $(cat /etc/network/interfaces | grep address | awk '{print $2}') ; do
        touch /etc/nginx/nginx.$ip.conf
        cp /etc/nginx/nginx.conf.skel /etc/nginx/nginx.$ip.conf
        sed -i "s/%IPADDR%/${ip}/g" /etc/nginx/nginx.$ip.conf
        /usr/sbin/nginx -c /etc/nginx/nginx.$ip.conf
    done

При этом у вас должен быть написан скелет конфига с указанием %IPADDR% вместо IP-адреса. Например, такой:

worker_processes  1;

error_log   logs/error.%IPADDR%.log debug;

pid /var/run/nginx.%IPADDR%.pid;

worker_rlimit_nofile 65536;

events {
    worker_connections  16384;
}

rtmp {
        server {
                listen %IPADDR%:1935;
                chunk_size 4000;
                application live {
                        live on;
                        pull live stream %masterIP%;
                }
        }
}

http {
        server {
                listen %IPADDR%:8080;
                location /stat {
                        rtmp_stat all;
                        rtmp_stat_stylesheet stat.xsl;
                }
                location /stat.xsl {
                        root /srv/nginx/html;
                }
        }
}

Впрочем, автор обещает реализовать нормальную многопоточность в будущих релизах.

С помощью nginx-rtmp-module мне удалось полностью утилизировать 10-гигабитный канал. При этом основной проблемой стала вовсе не прожорливость самого nginx, а необходимость тюнинга сетевой карты и параметров ядра, чтобы software interrupts не съедали 100% CPU.

Ссылки по теме:

RTMP на Википедии
Wowza — официальный сайт
Erlyvideo — официальный сайт
Nginx-rtmp-module — проект на GitHub

Установка и настройка Wowza media server 2.2.4 и JW Player на Debian

wowza

Установка сервера

Топаем на оф сайт и качаем DEB версию. Пока качается ищем ключик (или покупаем…)

Установка самого сервера проста

sudo chmod +x WowzaMediaServer-2.2.4.deb.bin
sudo ./WowzaMediaServer-2.2.4.deb.bin

Т.к. требуется Java, ставим

apt-get install sun-java6-jre

Запускаем сервер

/etc/init.d/WowzaMediaServer start

 

Настройка сервера для вещания

Переходим в папку

cd /usr/local/WowzaMediaServer/content

Создаем папку для вещания, что типа плейлиста

mkdir simplevideostreaming

В папку content нужно будет класть ваше видео, либо сделать симлинк на content с вашим видео, и создать там папку simplevideostreaming.

 

Настройка плеера JW Player

Идем на оф сайт нажимаем Download JW Player, снимаем птички, ничего не заполняем, тыкаем Download Now. Плеер скачивается.

Распаковываем архив и кладем на сервер.

Пример для вещания

Кладем видео  video.flv в папку /usr/local/WowzaMediaServer/content

В папке которую мы распаковывали на сервер создаем тестовый html и вносим такие строки

<object id="player" style="display: block; margin-left: auto; margin-right: auto;" width="512" height="288" data="player.swf" type="application/x-shockwave-flash">
<param name="data" value="player.swf" />
<param name="name" value="player" />
<param name="allowfullscreen" value="true" />
<param name="allowscriptaccess" value="always" />
<param name="flashvars" value="streamer=rtmp://ВАШ_САЙТ:1935/simplevideostreaming&amp;file=video.flv&amp;image=preview.jpg&amp;provider=rtmp" />
<param name="src" value="player.swf" />
</object>

Подробнее:

streamer означает что видео будет потоковое, а не из файла

ВАШ_САЙТ — вписываем ваш URL  сайта где крутится сервер  Wowza

simplevideostreaming — это папка-плейлист который создавали в после установки сервера.

video.flv и preview.jpg — собственно видео и превью которое показывается до запуска видео.

Сохраняем и открываем, получаем такое…

jwplaeer-300x171

К плееру можно прикрутить переключение в HD, шарилку на Facebook и прочие плагины. Их можно найти тут. Если нужно бесплатно есть на трекерах.

 

P.S. Суть установки Wowza media server для меня была в перемотки длинных видео, т.к приходилось ждать пока все видео прогрузится. Здесь же промотка происходит как на YouTube с любого места.