パート1: powershellとmci
使用されるオペレーティングシステムはWindows 7です。
発生する最初の質問:Powershellでmp3を再生する方法?
以前、habrで同様の質問の参照がありました:
Windows 7のコマンドラインからmp3を再生する方法は?
PowerShellの使用方法は?
満足のいく答えがないため、Media Control Interfaceまたはmciを使用することにしました。
利点は次のとおりです:組み込みシステム、十分な低レベル、文字列の形式でコマンドを送信することが可能です。
多くのmciは、「CD-ROMドライブをプログラムで開く方法」という質問に答えていることで知られていますが、他の多くの機能も提供しています。 以下に使用シナリオをいくつか示します。
CD-ROMの取り外し:
mci 'set cdaudio door open'
ローカルmp3ファイルを再生します。
mci 'play C:\\temp\\Kalimba.mp3' mci 'status C:\\temp\\Kalimba.mp3 mode'
wavファイルへの書き込み:
mci 'open new type waveaudio alias RecWavFile' mci 'set RecWavFile bitspersample 16 samplespersec 44100 channels 2' mci 'record RecWavFile' mci 'stop RecWavFile' mci 'save RecWavFile C:\\temp\\RecWavFile.wav' mci 'close RecWavFile' mci 'play C:\\temp\\RecWavFile.wav wait'
ネットワークからストリームを再生する簡単な方法:
mci 'play http://some-radio-server.com:80/some-radio-channel.mp3'
ネットワークからストリームを再生するための高度なオプション:
mci 'open http://some-radio-server.com:80/some-radio-channel.mp3 type mpegvideo alias radio' #mci 'open http://other-radio-server/other-radio-channel.fake.mp3 type mpegvideo alias radio' mci 'status radio volume' mci 'setaudio radio volume to 100' mci 'play radio' mci 'status radio mode' mci 'stop radio' mci 'close radio'
奇妙に思えるかもしれませんが、最初はPowerShellでmciを操作する同様の方法はありません(著者は見つかりませんでした)。 この作業を可能にするには、mciSendStringA関数のラッパーを作成する必要があります。 同時に、本格的なコマンドラインインターフェイスを使用するには、コマンドの入力に加えて、関数の結果を出力し、エラーコードを復号化する必要があります。 たとえば、statusコマンドでステータスを要求するには、最初のものが必要です。 2番目の方法は、毎回エラーの説明を探す必要がないため便利です。
mci powershell wrapper:
$MemDef =@" [DllImport("winmm.dll", CharSet = CharSet.Ansi)] public static extern int mciSendStringA( string lpstrCommand, [Out] byte[] lpstrReturnString, int uReturnLength, IntPtr hwndCallback); [DllImport("winmm.dll", CharSet = CharSet.Ansi)] public static extern int mciGetErrorStringA( int dwError, [Out] byte[] lpstrBuffer, int uLength); "@ $winmm = Add-Type -memberDefinition $MemDef -ErrorAction 'SilentlyContinue' -passthru -name mciSendString function mci($strSend) { $buffer = New-Object byte[] 128 [int]$error = $winmm::mciSendStringA( $strSend, $buffer, 128, 0 ) [Text.Encoding]::ASCII.GetString($buffer) $error_buffer = New-Object byte[] 128 [void]$winmm::mciGetErrorStringA( $error, $error_buffer, 128 ) [Text.Encoding]::GetEncoding('windows-1251').GetString($error_buffer) }
いくつかの説明が役立つ場合があります。
$ MemDefにはC#コードが含まれています。 そして、$ winmmの中には既にコンパイルの結果があります。
テキスト文字列を取得するには、ライブラリ関数から必要があります:
- [Out] byte []として、返された文字列の型を(レジスタが重要であることを意味するC#コードで)宣言します。
- 呼び出すとき、バッファを準備します。
- バッファとバッファサイズを渡します。
- 受信バイトを特定のエンコーディングの文字列として解釈します。
特にwinapi関数を宣言するためにC#インクルージョンを使用することはあまり正しくないように思われるかもしれません。 しかし、ここで重要なのはユーザビリティであり、それを達成する方法ではありません。mciコマンドを含む行は、powershellスタイルに調和して溶け込みます。
mciコマンドのリストは、 ここで見つけるか、「マルチメディアコマンド文字列」を検索して見つけることができます。
PS mciを通じて、映画を見ることができます。
パート2: HTTP プロキシとnode.js
例からわかるように、ローカルファイルだけでなく、名前としてURLも指定できます。
ただし、一部のサーバー(other-radio-serverなど)には問題があります:強制切断後にのみ再生が開始されます。 独自のHTTPプロキシが「間違った」パケットを「修正」するのに役立ちます。 特に、即時再生の場合は、ヘッダー「content-length」を応答に追加するだけです。
Node.jsは、プロキシの記述に最適です。
プロキシを開始して接続した後、前の行の代わりにコメント化された行を使用できます。
URL「.fake.mp3」の末尾は、プロキシ操作の必要性を示しています。 以下は、最適とはほど遠いサーバーコードです。
node / proxy_server.js:
require('./simple_cli').run() var http = require('http') var url = require('url') http.createServer(function(request, response) { var u = url.parse(request.url) var options = { port : u['port'] || 80, host : u['hostname'], method : request.method, path : u['pathname'], headers : request.headers } console.log(request.url) delete options.headers['proxy-connection'] if( request.url.substr(-9) === ".fake.mp3" ) { var p = options['path'] options['path'] = p.substr(0, p.length - 9) options['icy-metadata'] = '0' } console.log(options) var proxy_request = http.request(options); proxy_request.on('response', function (proxy_response) { console.log(proxy_response.headers) if( request.url.substr(-9) === ".fake.mp3" ) { proxy_response.headers['content-length'] = '221183499' } proxy_response.pipe(response); response.writeHead(proxy_response.statusCode, proxy_response.headers); }); request.pipe(proxy_request); }).listen(8080); console.log('Server running...');
PSプロキシは、たとえば、送信された要求および受信された応答を表示または前処理する場合にも役立ちます。
パート3: インタラクティブ機能
サーバーを通過するヘッダーを表示するために、コンソールをクリアする必要がある場合があります。 最も簡単なコマンドラインインターフェイスにより、これを実現できます。
node / simple_cli.js
module.exports.run = function(){ process.stdin.resume(); process.stdin.setEncoding('utf8'); process.stdin.on('data', function (data) { data = data.toString().trim(); switch (data) { case 'exit': process.exit(); break; case 'clear': process.stdout.write('\u001B[2J\u001B[0;0f'); break; case 'help': process.stdout.write('exit, clear, help\n'); break; default: process.stdout.write('unrecognize: '+data+'\n'); } }); }
これは、便利なサーバーの起動に必要です。
run_proxy_server.cmd
"%~d0%~p0node.exe" "%~d0%~p0node\proxy_server.js" pause
最終的なレシピ:
- 作業フォルダーにダウンロードしますnode.exe c " nodejs.org/download "
その中にすべてのファイルを作成した後、次のツリーを取得します。
+
| -node.exe
| -run_proxy_server.cmd
| +ノード
| | -proxy_server.js
| | -simple_cli.js
- HTTPプロキシを実行します。
run_proxy_server.cmd - ローカルプロキシを設定します。
windows + R、control、ctrl + F、pr
「プロキシサーバーの構成」、「ネットワークの構成」、「プロキシサーバー」、「プロキシサーバーの使用...」
住所:127.0.0.1ポート:8080
わかった - ラッパーコードをインタラクティブに実行する
- 例をインタラクティブに実行する
最後の2つのポイントについては、たとえば次のオプションのいずれかを使用できます。
- コマンドラインからpoweshell
- Windows PowerShell
- Windows PowerShell ISE
PS some-radio-serverおよびsome-radio-channelとして、たとえば、それぞれicy-e-05.sharp-streamおよびkiss100lowを、other-radio-serverおよびother-radio-channel-pub5.diとして使用できます.fmおよびdi_eurodance。