Ubuntuでcrtmpserverを試す(その2)

前回の Ubuntuでcrtmpserverを試す に引き続き、今回は以下を参考に動画を配信して見た。

YouTubeのようなストリーミング配信するRTMPサーバーをたててみる( C++ RTMP Server(crtmpserver)を使ってみた) | レンタルサーバー・自宅サーバー設定・構築のヒント

処理フロー:MP4 → [crtmpserver] → RTMP → [flowplayer]

【crtmpserverの設定確認】

Ubuntuにパッケージとしてインストールしたcrtmpserverのデフォルト設定では、MP4ファイルの保存先がどのディレクトリになっているのかを確認する。
実際に /etc/crtmpserver/applications/flvplayback.lua の内容を確認すると、以下のように設定されている。

mediaFolder="/var/lib/crtmpserver/mediaFolder"

今回はこのディレクトリをそのまま使用する。

【MP4ファイルの配置】

前述のmediaFolderが示す /var/lib/crtmpserver/mediaFolder に便宜上hoge.mp4を配置する。
その際、シンボリックリンクでは上手く行かないので、実体を保存するか、ハードリンクを作成する。

【sample2.htmlの作成】

前回の Ubuntuでcrtmpserverを試す で作成したsample1.htmlと同じディレクトリに以下の内容でsample2.htmlを作成する。

<html>
    <head>
        <title>Play RTMP via crtmpserver</title>
        <script src="../flowplayer-3.2.13.min.js"></script>
    </head>
    <body>
        <a style="display:block;width:854px;height:480px;" id="player"></a>
        <script>
            $f("player", "../flowplayer-3.2.18.swf", {

                clip: {
                    url: 'mp4:hoge.mp4',
                    scaling: 'fit',
                    provider: 'rtmp'
                },

                plugins: {
                    rtmp: {
                        url: '../flowplayer.rtmp/flowplayer.rtmp-3.2.13.swf',
                        netConnectionUrl: 'rtmp://192.168.1.28/flvplayback'
                    }
                }
            });
        </script>
    </body>
</html>

上記 192.168.1.28 はサーバーのIPアドレスなので、インストール環境に合わせて適宜変更して欲しい。

【ブラウザで再生】

ブラウザで http://サーバーのIPアドレス/flowplayer/example/sample2.html にアクセスしてRTMPを再生する。

 

Ubuntuでcrtmpserverを試す

メディアサーバーのcrtmpserverが稼働する環境をUbuntu上に構築し、メディア配信に関する知識を増強しようと考えた。
今回は以下を参考にPCのブラウザで動画再生ができる環境を構築して見た。

RTMPストリーミング — pdoc 0.1 documentation

処理フロー:MP4 → [ffmpeg] → FLV → [crtmpserver] → RTMP → [flowplayer]

【動作環境】

【パッケージインストール】

apt-get install でUbuntuに以下のパッケージをインストールする。
( [ ] 内にインストールしたときのバージョンを記した。)

  • crtmpserver [1.0~dfsg-5]
  • lua5.2 [5.2.3-1]
  • apache2 [2.4.7-1ubuntu4.13]

ffmpegのインストール】

Ubuntuでffmpegをビルドする にしたがってffmpeg(バージョン:git-2017-01-02-aa95292)をインストールする。

【crtmpserver設定の表示】

crtmpserverの設定ファイルは /etc/crtmpserver 以下に存在する。
そのディレクトリにあるインストール直後のcrtmpserver.luaの末尾は

-- print("__________________________")
-- table_print(configuration)
-- print("__________________________")

となっているので -- を削除してコメントを外す。さらに、以下の不具合を修正する。

if ( app:match("^#.*$") or app:match("^$") or app:match("^\s+$") ) then
                                                          ↓
if ( app:match("^#.*$") or app:match("^$") or app:match("^%s+$") ) then

そして、 lua crtmpserver.lua を実行すると、以下のように設定内容が表示される。

[applications] => table
    (
       [1] => table
           (
              [name] => applestreamingclient
              [protocol] => dynamiclinklibrary
              [description] => Apple Streaming Client
              [aliases] => table
                  (
                     [1] => asc
                  )
           )
       [2] => table
           (
              [validateHandshake] => true
              [acceptors] => table
                  (
                     [1] => table
                         (
                            [port] => 1935
                            [protocol] => inboundRtmp
                            [ip] => 0.0.0.0
                         )
                     [2] => table
                         (
                            [port] => 8080
                            [protocol] => inboundRtmpt
                            [ip] => 0.0.0.0
                         )
                  )
              [name] => appselector
              [protocol] => dynamiclinklibrary
              [description] => Application for selecting the rest of the applications
              [default] => true
           )
       [3] => table
           (
              [externalStreams] => table
                  (
                  )
              [aliases] => table
                  (
                     [1] => simpleLive
                     [2] => vod
                     [3] => live
                     [4] => WeeklyQuest
                     [5] => SOSample
                     [6] => oflaDemo
                  )
              [mediaFolder] => /var/lib/crtmpserver/mediaFolder
              [protocol] => dynamiclinklibrary
              [seekGranularity] => 1.5
              [keyframeSeek] => true
              [validateHandshake] => true
              [name] => flvplayback
              [clientSideBuffer] => 12
              [description] => FLV Playback Sample
              [acceptors] => table
                  (
                     [1] => table
                         (
                            [protocol] => inboundLiveFlv
                            [port] => 6666
                            [waitForMetadata] => true
                            [ip] => 0.0.0.0
                         )
                     [2] => table
                         (
                            [port] => 9999
                            [protocol] => inboundTcpTs
                            [ip] => 0.0.0.0
                         )
                  )
           )
       [4] => table
           (
              [targetServers] => table
                  (
                     [1] => table
                         (
                            [localStreamName] => stream1
                            [keepAlive] => true
                            [targetStreamType] => live
                            [targetUri] => rtmp://gigi:spaima@localhost/vod
                            [emulateUserAgent] => My user agent
                         )
                  )
              [abortOnConnectError] => true
              [name] => proxypublish
              [protocol] => dynamiclinklibrary
              [description] => Application for forwarding streams to another RTMP server
              [acceptors] => table
                  (
                     [1] => table
                         (
                            [port] => 6665
                            [protocol] => inboundLiveFlv
                            [ip] => 0.0.0.0
                         )
                  )
           )
       [5] => table
           (
              [active] => false
              [protocol] => dynamiclinklibrary
              [targetServer] => localhost
              [streams] => table
                  (
                     [1] => mp4:lg.mp4
                  )
              [randomAccessStreams] => false
              [name] => stresstest
              [numberOfConnections] => 10
              [description] => Application for stressing a streaming server
              [targetApp] => vod
           )
       [rootDirectory] => /usr/lib/crtmpserver/applications
    )
[pathSeparator] => /
[logAppenders] => table
    (
       [1] => table
           (
              [name] => console appender
              [type] => coloredConsole
              [level] => 6
           )
       [2] => table
           (
              [name] => file appender
              [type] => file
              [fileName] => /var/log/crtmpserver/main.log
              [level] => 6
           )
    )
[daemon] => true

crtmpserver.luaで外したコメントは元に戻しておくこと。

【crtmpserverログの確認】

crtmpserverのログファイルは /var/log/crtmpserver に存在するので、Servicesテーブルを確認する。

+-----------------------------------------------------------------------------+
|                                                                     Services|
+---+---------------+-----+-------------------------+-------------------------+
| c |      ip       | port|   protocol stack name   |     application name    |
+---+---------------+-----+-------------------------+-------------------------+
|tcp|        0.0.0.0| 1935|              inboundRtmp|              appselector|
+---+---------------+-----+-------------------------+-------------------------+
|tcp|        0.0.0.0| 8080|             inboundRtmpt|              appselector|
+---+---------------+-----+-------------------------+-------------------------+
|tcp|        0.0.0.0| 6666|           inboundLiveFlv|              flvplayback|
+---+---------------+-----+-------------------------+-------------------------+
|tcp|        0.0.0.0| 9999|             inboundTcpTs|              flvplayback|
+---+---------------+-----+-------------------------+-------------------------+
|tcp|        0.0.0.0| 6665|           inboundLiveFlv|             proxypublish|
+---+---------------+-----+-------------------------+-------------------------+

ffmpegからストリーム送信】

以下のコマンドを実行し、ffmpegからcrtmpserverにストリームを送信する。

ffmpeg -stream_loop -1 -re -i hoge.mp4 -vcodec copy -metadata streamName=ffmpeg -f flv tcp://localhost:6666

各パラメーターの詳細は以下の通り。

参考:最新ffmpegのオプションまとめ - MobileHackerz Knowledgebase Wiki

  • -stream_loop -1
    入力メディアを永久に繰り返し出力する。
  • -re
    入力メディアと同じスピードで出力する。このオプションを指定しないと、最初から最後まで再生されない(試して見て欲しい)。
  • -i hoge.mp4
    入力メディアとして便宜上hoge.mp4を指定する。
  • -vcodec copy
    入力メディアの映像データーをそのままコピーする(CPU負荷が低い)。
  • -metadata streamName=ffmpeg
    ffmpegと言う名前でストリームを配信する。その名前は再生対象のメディアを指定するときのキーワードとなる。
  • -f flv
    FLVフォーマットでメディアを出力する。
  • tcp://localhost:6666
    crtmpserverのinboundLiveFlvプロトコルスタック、flvplaybackアプリケーションに出力する(現段階では意味を正確に理解していないため、これ以上は説明できないので悪しからず)。

上記のコマンドを実行することで、crtmpserverのログには以下のように出力される。

1483539098:3:/build/buildd/crtmpserver-1.0~dfsg/thelib/src/netio/epoll/tcpacceptor.cpp:154:Accept:Client connected: 127.0.0.1:42042 -> 0.0.0.0:6666
1483539098:6:/build/buildd/crtmpserver-1.0~dfsg/thelib/src/protocols/liveflv/inboundliveflvprotocol.cpp:46:Initialize:parameters:
<MAP name="" isArray="false">
    <STR name="ip">0.0.0.0</STR>
    <UINT16 name="port">6666</UINT16>
    <STR name="protocol">inboundLiveFlv</STR>
    <STR name="sslCert"></STR>
    <STR name="sslKey"></STR>
    <BOOL name="waitForMetadata">true</BOOL>
</MAP>
1483539098:6:/build/buildd/crtmpserver-1.0~dfsg/thelib/src/protocols/liveflv/inboundliveflvprotocol.cpp:51:Initialize:_waitForMetadata: 1
1483539098:4:/build/buildd/crtmpserver-1.0~dfsg/thelib/src/netio/epoll/iohandlermanager.cpp:100:RegisterIOHandler:Handlers count changed: 6->7 IOHT_TCP_CARRIER
1483539098:6:/build/buildd/crtmpserver-1.0~dfsg/thelib/src/protocols/liveflv/baseliveflvappprotocolhandler.cpp:45:RegisterProtocol:protocol CTCP(10) <-> TCP(100) <-> [ILFL(101)] registered to app flvplayback
1483539098:3:/build/buildd/crtmpserver-1.0~dfsg/thelib/src/protocols/liveflv/inboundliveflvprotocol.cpp:184:SignalInputData:Stream metadata:
<MAP name="" isArray="true">
    <MAP name="__index__value__0" isArray="true">
        <DOUBLE name="audiocodecid">10.000</DOUBLE>
        <DOUBLE name="audiodatarate">125.000</DOUBLE>
        <DOUBLE name="audiosamplerate">44100.000</DOUBLE>
        <DOUBLE name="audiosamplesize">16.000</DOUBLE>
        <STR name="compatible_brands">isommp42</STR>
        <DOUBLE name="duration">0.000</DOUBLE>
        <STR name="encoder">Lavf57.61.100</STR>
        <DOUBLE name="filesize">0.000</DOUBLE>
        <DOUBLE name="framerate">29.970</DOUBLE>
        <DOUBLE name="height">720.000</DOUBLE>
        <STR name="major_brand">mp42</STR>
        <STR name="minor_version">0</STR>
        <BOOL name="stereo">true</BOOL>
        <STR name="streamName">ffmpeg</STR>
        <DOUBLE name="videocodecid">7.000</DOUBLE>
        <DOUBLE name="videodatarate">2172.205</DOUBLE>
        <DOUBLE name="width">1280.000</DOUBLE>
    </MAP>
</MAP>

【FlowPlayerのインストール】

FlowPlayerでMP4を再生する にしたがってFlowPlayerをインストールする。

【FlowPlayerにRTMPプラグインを追加】

以下のページからRTMP Streaming Pluginをダウンロードする。
(今回はバージョン 3.2.13をダウンロードした。)

flash.flowplayer.org

上記ページのDownloadセクションからダウンロードしたZIPファイルをFlowPlayer本体をインストールしたディレクトリ /var/www/html/flowplayer に展開する。

.
├── LICENSE.txt
├── README.txt
├── example
│   ├── hoge.mp4
│   ├── index.html
│   └── style.css
├── flowplayer-3.2.13.min.js
├── flowplayer-3.2.18.swf
├── flowplayer.controls-3.2.16.swf
└── flowplayer.rtmp
    ├── LICENSE.txt
    ├── README.txt
    └── flowplayer.rtmp-3.2.13.swf

2 directories, 11 files

【sample1.htmlの作成】

前述のtree表示内容に記載のexampleディレクトリにsample1.htmlを以下の内容で作成する。

<html>
    <head>
        <title>Play RTMP via crtmpserver</title>
        <script src="../flowplayer-3.2.13.min.js"></script>
    </head>
    <body>
        <a style="display:block;width:854px;height:480px;" id="player"></a>
        <script>
            $f("player", "../flowplayer-3.2.18.swf", {

                clip: {
                    url: 'ffmpeg',
                    live: true,
                    provider: 'rtmp'
                },

                plugins: {
                    rtmp: {
                        url: '../flowplayer.rtmp/flowplayer.rtmp-3.2.13.swf',
                        netConnectionUrl: 'rtmp://192.168.1.28/flvplayback'
                    }
                }
            });
        </script>
    </body>
</html>

上記 192.168.1.28 はサーバーのIPアドレスなので、インストール環境に合わせて適宜変更して欲しい。

【ブラウザで再生】

ブラウザで http://サーバーのIPアドレス/flowplayer/example/sample1.html にアクセスしてRTMPを再生する。

 

FlowPlayerでMP4を再生する

FlashアプリのFlowPlayerを使用して、MP4を再生して見ようと思った。最終的にはRTMPを再生する予定だが、その前に単体で動作確認をしておくと言う意味である。

【動作環境】

【パッケージインストール

apt-get install でUbuntuに以下のパッケージをインストールする。
( [ ] 内にインストールしたときのバージョンを示した。)

  • apache2 [2.4.7-1ubuntu4.13]

【FlowPlayerダウンロード】

以下のページからFlash版FlowPlayerをダウンロードする。
(今回はバージョン 3.2.18をダウンロードした。)

flash.flowplayer.org

上記ページのFlowplayer distributionセクションのdownloadリンクからダウンロードできる。

HTML5版FlowPlayerも存在するので注意して欲しい。

【FlowPlayerインストール

 Apache2のデフォルトのドキュメントルートである /var/www/html ディレクトリにダウンロードしたFlowPlayerを以下のように配置する。

$ tree
.
├── flowplayer
│   ├── LICENSE.txt
│   ├── README.txt
│   ├── example
│   │   ├── index.html
│   │   └── style.css
│   ├── flowplayer-3.2.13.min.js
│   ├── flowplayer-3.2.18.swf
│   ├── flowplayer.controls-3.2.16.swf
└── index.html

2 directories, 8 files

【MP4ファイルの配置】

前述のtree表示内容に記載のexampleディレクトリにMP4ファイルを配置する。
今回は便宜上hoge.mp4を配置したことにする。
シンボリックリンクは扱えないので注意。

【index.htmlの修正】

前述のtree表示内容に記載のexampleディレクトリに存在するFlash版FlowPlayer付属のindex.htmlを以下のように変更する。

※MP4ファイルの中には再生できないものが存在する。Firefoxで直接MP4ファイルをアクセスしても再生されない場合、そのMP4ファイルがFlowPlayerで対応していない可能性がある。

<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<!-- A minimal Flowplayer setup to get you started -->


    <!--
        include flowplayer JavaScript file that does
        Flash embedding and provides the Flowplayer API.
    -->
    <script type="text/javascript" src="../flowplayer-3.2.13.min.js"></script>

    <!-- some minimal styling, can be removed -->
    <link rel="stylesheet" type="text/css" href="style.css">

    <!-- page title -->
    <title>Minimal Flowplayer setup</title>

</head><body>

    <div id="page">

        <h1>Minimal Flowplayer setup</h1>

        <p>View commented source code to get familiar with Flowplayer installation.</p>

        <!-- this A tag is where your Flowplayer will be placed. it can be anywhere -->
        <a
             href="hoge.mp4"
             style="display:block;width:520px;height:330px"
             id="player">
        </a>

        <!-- this will install flowplayer inside previous A- tag. -->
        <script>
            flowplayer("player", "../flowplayer-3.2.18.swf");
        </script>



        <!--
            after this line is purely informational stuff.
            does not affect on Flowplayer functionality
        -->

        <p>
            If you are running these examples <strong>locally</strong> and not on some webserver you must edit your
            <a href="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html">
                Flash security settings</a>.
        </p>

        <p class="less">
            Select "Edit locations" > "Add location" > "Browse for files" and select
            flowplayer-x.x.x.swf you just downloaded.
        </p>


        <h2>Documentation</h2>

        <p>
            <a href="http://flowplayer.org/documentation/installation/index.html">Flowplayer installation</a>
        </p>

        <p>
            <a href="http://flowplayer.org/documentation/configuration/index.html">Flowplayer configuration</a>
        </p>

        <p>
            See this identical page on <a href="http://flowplayer.org/demos/example/index.htm">Flowplayer website</a>
        </p>

    </div>


</body></html>

【ブラウザで再生】

ブラウザで http://サーバーのIPアドレス/flowplayer/example/ にアクセスしてMP4を再生する。

 

Ubuntuでffmpegをビルドする

apt-getでUbuntuにcrtmpserverをインストールしたので、そのソースデータの生成のためにffmpegを使用することにした。
ffmpegはソースビルドするしかないようなので、以下を参考にビルドを行った。

www.jifu-labo.net

結果、ソースコードのダウンロードも含めてビルドは一発で問題なく完了した。
なお、ソースの保存先を変更したかったので、上記参考文献に記載のビルドスクリプト

src_dir="$HOME/ffmpeg_sources"

を変更した。

また、PATHを変更するのが面倒だったので、

ln -s /usr/local/ffmpeg_build/bin/ffmpeg /usr/local/bin/ffmpeg

シンボリックリンクを作成した。

試しに、以下のコマンドを実行して、正常に動作することを確認した。

ffmpeg -i hoge.mp4 hoge.ts

【動作環境】

  • cat /proc/version の結果
    Linux version 3.13.0-106-generic (buildd@lcy01-30) (gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3) ) #153-Ubuntu SMP Tue Dec 6 15:44:32 UTC 2016

【2017/03/06】

libav-toolsのavconvならapt-getでインストール可能であることが判明した。
また、CentOS 7でも同様に一発でビルドが問題なく完了した。

 

Node.jsでWindows Named Pipeを使って通信する

Node.jsでWindows Named Pipeを使ってプロセス間通信を行うプログラムを作った。
ハマった点は以下の通り。

  • インストールしていたNode.jsのバージョンが古いことに気が付かず、windows-build-toolsがインストールできないため、sleepモジュールのネイティブコードがビルドできなくて困った。
  • 今となっては実際の送信がイベント駆動で行われているものと想定されるが、プロセス終了時に送信したメッセージが相手側に届かず困った。
  • Named Pipeが作成されていないときにオープンすると発生するUnhandled 'error' eventの意味が分からず、クライアント側でのサーバーの準備待ちのやり方が分からなくて困った。

上記はいずれも解決済みである。
ソースコードは以下から入手できる。

github.com

【参考文献】

 

Node.jsにネイティブビルド環境をインストールする

Windows上のNode.jsプログラム間でnamed-pipesモジュールを使用してプロセス間通信を行い、サーバー側プログラムが終了するときに、クライアントに送信したメッセージが届く前にパイプを閉じないように時間待ちをしたいと考えた。
しかし、以下を読んで、その時間待ち処理を行うには、徹底的なイベント駆動型を踏襲しなければならないことに辟易した。

qiita.com

言語仕様(と言うより、言語思想)に泣かされたことはscalaでもあったが、世の中には同じ思いの人が必ずいるものだ。
ちゃんとsleepを行うためのsleepモジュールが以下に存在した。

github.com

しかし、このsleepモジュールにはネイティブコードが含まれているため、それをビルドするための環境が必要だった。

そこで先ずは以下のWindows用のビルドツールをNode.jsにインストールした。

github.com

以下はnpmでwindows-build-toolsをインストールしたときの画面出力である。

>npm install --global windows-build-tools

> windows-build-tools@1.0.0 postinstall C:\Users\pochi\AppData\Roaming\npm\node_modules\windows-build-tools
> node ./lib/index.js

Downloading BuildTools_Full.exe
[============================================>] 100.0% of 3.29 MB (208.76 kB/s)
Downloading python-2.7.11.msi
[============================================>] 100.0% of 18.64 MB (124.66 kB/s)
Downloaded python-2.7.11.msi. Saved to C:\Users\pochi\.windows-build-tools\python-2.7.11.msi.
Starting installation...
Launched installers, now waiting for them to finish.
This will likely take some time - please be patient!
Waiting for installers... |Successfully installed Python 2.7
Waiting for installers... -Successfully installed Visual Studio Build Tools.
C:\Users\pochi\AppData\Roaming\npm
`-- windows-build-tools@1.0.0
  +-- chalk@1.1.3
  | +-- ansi-styles@2.2.1
  | +-- escape-string-regexp@1.0.5
  | +-- has-ansi@2.0.0
  | | `-- ansi-regex@2.0.0
  | +-- strip-ansi@3.0.1
  | `-- supports-color@2.0.0
  +-- cli-spinner@0.2.5
  +-- debug@2.6.0
  | `-- ms@0.7.2
  +-- fs-extra@1.0.0
  | +-- graceful-fs@4.1.11
  | +-- jsonfile@2.4.0
  | `-- klaw@1.3.1
  `-- nugget@2.0.1
    +-- minimist@1.2.0
    +-- pretty-bytes@1.0.4
    | +-- get-stdin@4.0.1
    | `-- meow@3.7.0
    |   +-- camelcase-keys@2.1.0
    |   | `-- camelcase@2.1.1
    |   +-- decamelize@1.2.0
    |   +-- loud-rejection@1.6.0
    |   | +-- currently-unhandled@0.4.1
    |   | | `-- array-find-index@1.0.2
    |   | `-- signal-exit@3.0.2
    |   +-- map-obj@1.0.1
    |   +-- normalize-package-data@2.3.5
    |   | +-- hosted-git-info@2.1.5
    |   | +-- is-builtin-module@1.0.0
    |   | | `-- builtin-modules@1.1.1
    |   | +-- semver@5.3.0
    |   | `-- validate-npm-package-license@3.0.1
    |   |   +-- spdx-correct@1.0.2
    |   |   | `-- spdx-license-ids@1.2.2
    |   |   `-- spdx-expression-parse@1.0.4
    |   +-- object-assign@4.1.0
    |   +-- read-pkg-up@1.0.1
    |   | +-- find-up@1.1.2
    |   | | `-- path-exists@2.1.0
    |   | `-- read-pkg@1.1.0
    |   |   +-- load-json-file@1.1.0
    |   |   | +-- parse-json@2.2.0
    |   |   | | `-- error-ex@1.3.0
    |   |   | |   `-- is-arrayish@0.2.1
    |   |   | +-- pify@2.3.0
    |   |   | `-- strip-bom@2.0.0
    |   |   |   `-- is-utf8@0.2.1
    |   |   `-- path-type@1.1.0
    |   +-- redent@1.0.0
    |   | +-- indent-string@2.1.0
    |   | | `-- repeating@2.0.1
    |   | |   `-- is-finite@1.0.2
    |   | `-- strip-indent@1.0.1
    |   `-- trim-newlines@1.0.0
    +-- progress-stream@1.2.0
    | +-- speedometer@0.1.4
    | `-- through2@0.2.3
    |   +-- readable-stream@1.1.14
    |   | +-- core-util-is@1.0.2
    |   | +-- inherits@2.0.3
    |   | +-- isarray@0.0.1
    |   | `-- string_decoder@0.10.31
    |   `-- xtend@2.1.2
    |     `-- object-keys@0.4.0
    +-- request@2.79.0
    | +-- aws-sign2@0.6.0
    | +-- aws4@1.5.0
    | +-- caseless@0.11.0
    | +-- combined-stream@1.0.5
    | | `-- delayed-stream@1.0.0
    | +-- extend@3.0.0
    | +-- forever-agent@0.6.1
    | +-- form-data@2.1.2
    | | `-- asynckit@0.4.0
    | +-- har-validator@2.0.6
    | | +-- commander@2.9.0
    | | | `-- graceful-readlink@1.0.1
    | | +-- is-my-json-valid@2.15.0
    | | | +-- generate-function@2.0.0
    | | | +-- generate-object-property@1.2.0
    | | | | `-- is-property@1.0.2
    | | | +-- jsonpointer@4.0.1
    | | | `-- xtend@4.0.1
    | | `-- pinkie-promise@2.0.1
    | |   `-- pinkie@2.0.4
    | +-- hawk@3.1.3
    | | +-- boom@2.10.1
    | | +-- cryptiles@2.0.5
    | | +-- hoek@2.16.3
    | | `-- sntp@1.0.9
    | +-- http-signature@1.1.1
    | | +-- assert-plus@0.2.0
    | | +-- jsprim@1.3.1
    | | | +-- extsprintf@1.0.2
    | | | +-- json-schema@0.2.3
    | | | `-- verror@1.3.6
    | | `-- sshpk@1.10.1
    | |   +-- asn1@0.2.3
    | |   +-- assert-plus@1.0.0
    | |   +-- bcrypt-pbkdf@1.0.0
    | |   +-- dashdash@1.14.1
    | |   | `-- assert-plus@1.0.0
    | |   +-- ecc-jsbn@0.1.1
    | |   +-- getpass@0.1.6
    | |   | `-- assert-plus@1.0.0
    | |   +-- jodid25519@1.0.2
    | |   +-- jsbn@0.1.0
    | |   `-- tweetnacl@0.14.5
    | +-- is-typedarray@1.0.0
    | +-- isstream@0.1.2
    | +-- json-stringify-safe@5.0.1
    | +-- mime-types@2.1.13
    | | `-- mime-db@1.25.0
    | +-- oauth-sign@0.8.2
    | +-- qs@6.3.0
    | +-- stringstream@0.0.5
    | +-- tough-cookie@2.3.2
    | | `-- punycode@1.4.1
    | +-- tunnel-agent@0.4.3
    | `-- uuid@3.0.1
    +-- single-line-log@1.1.2
    | `-- string-width@1.0.2
    |   +-- code-point-at@1.1.0
    |   `-- is-fullwidth-code-point@1.0.0
    |     `-- number-is-nan@1.0.1
    `-- throttleit@0.0.2

ご覧の通り、Visual C++ Build ToolsPythonを自動でインストールすると言うすぐれものだった。
なお、windows-build-toolsをインストールするためにはNode.jsのバージョンが4以上でなければならないので注意して欲しい。

これでsleepをインストールすることができるようになった。
(※以下の「npm install」の前に「npm init」を忘れずに。)

C:\Users\pochi\nodejs\sleep_test>npm install sleep --save

> sleep@5.0.0 install C:\Users\pochi\nodejs\sleep_test\node_modules\sleep
> node-gyp rebuild


C:\Users\pochi\nodejs\sleep_test\node_modules\sleep>if not defined npm_config_node_gyp (node "C:\Program Files\nodejs\node_modules\npm\bin\node-gyp-bin\\..\..\node_modules\node-gyp\bin\node-gyp.js" rebuild )  else (node "" rebuild )
このソリューション内のプロジェクトを 1 度に 1 つずつビルドします。並行ビルドを有効にするには、"/m" スイッチを追加してください。
  sleep.cc
  win_delay_load_hook.cc
     Creating library C:\Users\pochi\nodejs\sleep_test\node_modules\sl
  eep\build\Release\node_sleep.lib and object C:\Users\pochi\github\study-nodej
  s\calljs\node_modules\sleep\build\Release\node_sleep.exp
  Generating code
  Finished generating code
  node_sleep.vcxproj -> C:\Users\pochi\nodejs\sleep_test\node_modules\
  sleep\build\Release\\node_sleep.node
  node_sleep.vcxproj -> C:\Users\pochi\nodejs\sleep_test\node_modules\
  sleep\build\Release\node_sleep.pdb (Full PDB)
calljs@0.0.0 C:\Users\pochi\nodejs\sleep_test
`-- sleep@5.0.0
  `-- nan@2.5.0

npm WARN calljs@0.0.0 No description
npm WARN calljs@0.0.0 No repository field.

試しにインタラクティブモードでsleepを呼んでみた。

C:\Users\pochi\nodejs\sleep_test>node
> var sleep = require('sleep');
undefined
> sleep.sleep(3);
undefined
>
(To exit, press ^C again or type .exit)
>

「sleep.sleep(3)」で3秒待ってくれた、素晴らしい!

【動作環境】

【参考資料】

 

logicool m336 Bluetoothマウスが頻繁に動かなくなる件

12月頭のAmazon Cyber Mondayで安く購入したlogicool m336と言うBluetoothマウスだが、触ってもいないのにいつの間にかマウスポインターが動かず、ボタンも効かない事象が頻繁に発生している。
買ったばかりなのにこれでは困ると思い、検索してみると同じように困っている人が多数いた。

【解決策】

検索で見つけた解決策は次の2通り。

  • 電池の押さえが物理的に弱いのでティッシュを詰める方法

kotobuki1174takasui.xyz

  • Bluetoothドライバの電源管理との相性が悪いので省電力動作をオフにする方法

amaotolog.com

【環境】

  • OS:Windows 10 Home(Windos 7 Home Premiumからのアップグレード)
  • PC:ASUS U24E

【対策結果】

  • 電池の押さえが物理的に弱いのでティッシュを詰める方法
    事象は再発した。しかし、電池がカタカタ言う音がしなくて気持ち良いので、このまま使うことにした。
  • Bluetoothドライバの電源管理との相性が悪いので省電力動作をオフにする方法
    事象は発生しなくなった。なお、当該環境ではBluetooth Mobileデバイスに「電源管理」が存在する。

f:id:pochy9n:20161218182231p:plain