2013/10/20

Windows 8.1 にしたら OBS のゲームキャプチャが動かなくなった!

題名の通り。

とりあえず以下のようにコードを書き換えれば動くようになる。

D3D9Capture.cpp の 105 行目あたり

#ifdef _WIN64

#define NUM_KNOWN_PATCHES 5
#define PATCH_COMPARE_SIZE 13
UPARAM patch_offsets[NUM_KNOWN_PATCHES] = {/*0x4B55F,*/ 0x54FE6, 0x550C5, 0x8BDB5, 0x93AFA, 0x1841E5};
BYTE patch_compare[NUM_KNOWN_PATCHES][PATCH_COMPARE_SIZE] =
{
    //{0x48, 0x8b, 0x81, 0xc8, 0x38, 0x00, 0x00, 0x39, 0x98, 0x68, 0x50, 0x00, 0x00},  //winvis - 6.0.6002.18005
    {0x48, 0x8b, 0x81, 0xb8, 0x3d, 0x00, 0x00, 0x39, 0x98, 0x68, 0x50, 0x00, 0x00},  //win7   - 6.1.7600.16385
    {0x48, 0x8b, 0x81, 0xb8, 0x3d, 0x00, 0x00, 0x39, 0x98, 0x68, 0x50, 0x00, 0x00},  //win7   - 6.1.7601.17514
    {0x48, 0x8b, 0x81, 0xb8, 0x3d, 0x00, 0x00, 0x39, 0xB0, 0x28, 0x51, 0x00, 0x00},  //win8.1 - 6.3.9431.00000
    {0x8b, 0x81, 0xb8, 0x3d, 0x00, 0x00, 0x44, 0x39, 0xa0, 0x28, 0x51, 0x00, 0x00},  //win8.1 - 6.3.9600.16384
    {0x49, 0x8b, 0x85, 0xb8, 0x3d, 0x00, 0x00, 0x39, 0x88, 0xc8, 0x50, 0x00, 0x00},  //win8   - 6.2.9200.16384
};

#define PATCH_SIZE 2
BYTE patch[NUM_KNOWN_PATCHES][PATCH_SIZE] =
{
    //{0xEB, 0x12},
    {0xEB, 0x12},
    {0xEB, 0x12},
    {0x90, 0x90},
    {0x90, 0x90},
    {0x90, 0x90},
};

#else

#define NUM_KNOWN_PATCHES 5
#define PATCH_COMPARE_SIZE 12
UPARAM patch_offsets[NUM_KNOWN_PATCHES] = {/*0x4BDA1,*/ 0x79C9E, 0x79D96, 0x7F9BD, 0x8FBB1, 0x166A08, };
BYTE patch_compare[NUM_KNOWN_PATCHES][PATCH_COMPARE_SIZE] =
{
    //{0x8b, 0x89, 0x6c, 0x27, 0x00, 0x00, 0x39, 0xb9, 0x80, 0x4b, 0x00, 0x00},  //winvis - 6.0.6002.18005
    {0x8b, 0x89, 0xe8, 0x29, 0x00, 0x00, 0x39, 0xb9, 0x80, 0x4b, 0x00, 0x00},  //win7   - 6.1.7600.16385
    {0x8b, 0x89, 0xe8, 0x29, 0x00, 0x00, 0x39, 0xb9, 0x80, 0x4b, 0x00, 0x00},  //win7   - 6.1.7601.17514
    {0x8b, 0x80, 0xe8, 0x29, 0x00, 0x00, 0x39, 0xb0, 0x40, 0x4c, 0x00, 0x00},  //win8.1 - 6.3.9431.00000
    {0x80, 0xe8, 0x29, 0x00, 0x00, 0x83, 0xb8, 0x40, 0x4c, 0x00, 0x00, 0x00},  //win8.1 - 6.3.9600.16384
    {0x8b, 0x80, 0xe8, 0x29, 0x00, 0x00, 0x39, 0x90, 0xb0, 0x4b, 0x00, 0x00},  //win8   - 6.2.9200.16384
};

#define PATCH_SIZE 1
BYTE patch[NUM_KNOWN_PATCHES][PATCH_SIZE] =
{
    //{0xEB, 0x02},
    {0xEB},
    {0xEB},
    {0xEB},
    {0xEB},
    {0xEB},
};

#endif

自力でビルドできないひとは OBS 公式の対応待ちかな。

 

追記:公式での対応も来てました。はやい。

2013/10/18

続・rtmp-nginx-module で配信を mp4 で録画する方法

どうやら ffmpeg はエンコード中に kill シグナルが来ると、出力する mp4 ファイルが破損してしまうらしく、前の記事の方法では高確率でファイルが壊れてしまっていた。

なので正攻法(?)で、録画終了時に flv ファイルを mp4 ファイルに変換してやることにした。

まずは以下のスクリプトを /usr/local/bin/flv2mp4 あたりに作る。

#!/bin/bash

input=""
output=""
remove_origin="FALSE"

while getopts i:o:r OPT
do
    case $OPT in
        "i" ) input="$OPTARG" ;;
        "o" ) output="$OPTARG" ;;
        "r" ) remove_origin="TRUE" ;;
    esac
done

if [ "$input" = "" ]; then
    exit 1
fi
if [ "$output" = "" ]; then
    output=${input%.*}.mp4
fi

echo "Input: $input"
echo "Output: $output"

ffmpeg -y -i $input -vcodec copy -acodec copy $output

if [ "$remove_origin" = "TRUE" ]; then
    rm -f $input
fi

あとは nginx.conf の rtmp application の設定の中に、

record all;
record_path /tmp/rec;
record_suffix –%Y%m%d%H%M%S.flv;
exec_record_done /usr/local/bin/flv2mp4 –i $path –r;

と記述しておけば、放送中は flv 形式で一時録画され、放送終了時に勝手に mp4 に変換され、元の flv は削除される。

めでたしめでたし!

2013/10/13

rtmp-nginx-module で配信を mp4 で録画する方法

題名の通り。

record all では出力形式が FLV 形式なので、Samba を通して再生すると恐ろしくシークが遅い。なので MP4 形式で録画するようにしたかったのだけど、rtmp-nginx-module にはそんな機能はないらしい。

そんなときは ffmpeg さんに頼んでみようというお話。

まずは以下のシェルスクリプトをどこかに作る。(例: /usr/local/bin/nginx_mp4_recording)

#!/bin/bash

NOW=$(date +%Y%m%d-%H%M%S)
OUTPUT=/tmp/rec/${1}-${NOW}.mp4

ffmpeg -re -i rtmp://localhost/live/${1} -vcodec copy -acodec copy $OUTPUT

あとは nginx の rtmp サーバーのアプリケーション(例: application live { … })内に、

exec /usr/local/bin/nginx_mp4_recording $name;

と書いて配信開始時に呼び出されるようにしておけばオッケー。

気になる負荷は Atom 330 1.6GHz で 0.5~1.0% くらい。余裕。

2013/10/02

nginx-rtmp-module を使用した Twitch.tv と Ustream の同時配信環境構築

Twitch で配信するとカクつく人が出るようなので、Ustream でも同時配信がしたくていろいろ調べてみた結果、nginx の nginx-rtmp-module を使用すればいいことがわかったのでメモ。

元ネタはhttps://obsproject.com/forum/viewtopic.php?f=18&t=2651

まずは nginx のインストール。

$ sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev
$ wget http://nginx.org/download/nginx-1.5.6.tar.gz
$ wget https://github.com/arut/nginx-rtmp-module/archive/master.zip
$ tar –zxvf nginx-1.5.6.tar.gz
$ unzip master.zip
$ cd nginx-1.5.6
$ ./configure \
  --prefix=/etc/nginx \
  --sbin-path=/usr/sbin/nginx \
  --conf-path=/etc/nginx/nginx.conf \
  --http-log-path=/var/log/nginx/access.log \
  --error-log-path=/var/log/nginx/error.log \
  --lock-path=/var/lock/nginx.lock \
  --pid-path=/var/run/nginx.pid \ 
  --with-http_ssl_module \ 
  --with-ipv6 \
  --add-module=../nginx-rtmp-module-master
$ make
$ sudo make install

つぎに起動用のスクリプトを http://wiki.nginx.org/Nginx-init-ubuntu から拾ってきて、/etc/init.d/nginx に置いて chmod +x する。

起動用スクリプト内にある DAEMON=/usr/local/sbin/nginxDAEMON=/usr/sbin/nginx に、NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf"NGINX_CONF_FILE="/etc/nginx/nginx.conf" にそれぞれ書き換えて保存し、

$ /usr/sbin/update-rc.d -f nginx defaults

を実行してスタートアップに登録する。

つぎに ffmpeg のインストール。avconv では Input/Output error が発生して Ustream に送信できないような感じだったので、ffmpeg 推奨。

$ sudo add-apt-repository ppa:jon-severinsson/ffmpeg
$ sudo apt-get update
$ sudo apt-get install ffmpeg

add-apt-repository が見つからないって言われたときは、sudo apt-get install software-properties-common を試してみるといいかも。

そして、nginx の設定ファイル(/etc/nginx/nginx.conf)に以下の設定を追記

rtmp {
    server {
        listen 1935;
        chunk_size 4096;
        application live {
            live on;
            record off;
            # twitch は push でも問題なく動作する
            push rtmp://live-lax.twitch.tv/app/your_stream_key_here;
            # ustream は push では上手く動作しないので ffmpeg を間にはさむ
            exec ffmpeg -re -i rtmp://localhost/live/$name -c copy -f flv "rtmp://x.xxxxxxxx.fme.ustream.tv/ustreamVideo/xxxxxxxx/your_stream_key_hereq flashver=FME/3.0\20(compatible;\20FMSc/1.0)";
        }
    }
}

最後に、

$ sudo service nginx start

で nginx を起動してサーバー側の設定は完了。

あとは OBS から、設定したサーバーにストリーミングするように設定すれば同時配信ができてるはず。

 

追記:

このままだとUst側の配信が非常に不安定になったため、TCPRelay v0.1.1 beta (配布元: http://strikerx3.blogspot.jp/2012/06/tcprelay-011-beta.html)を使用して配信を安定させた。

tcprelay.jar を /usr/local/bin に放り込み、

rtmp {
    server {
        listen 1935;
        chunk_size 4096;
        exec java -jar /usr/local/bin/tcprelay.jar -p:1396 -th:x.xxxxxxxx.fme.ustream.tv;
        application live {
            live on;
            record off;
            # twitch は push でも問題なく動作する
            push rtmp://live-lax.twitch.tv/app/your_stream_key_here;
            # ustream は push では上手く動作しないので ffmpeg を間にはさむ
            exec ffmpeg -re -i rtmp://localhost/live/$name -c copy -f flv "rtmp://localhost:1396/ustreamVideo/xxxxxxxx/your_stream_key_hereq flashver=FME/3.0\20(compatible;\20FMSc/1.0)";
        }
    }
}

と設定を書き換えたらいい感じになった。