2011-11-08 19 views
3

ブラウザでJavaScriptを使用して、画像、ビデオ、およびオーディオをAirPlayサーバに送信する方法はありますか?Javascript:ブラウザのAirplay

+0

作品。 – Blender

+0

[RAOP](http://en.wikipedia.org/wiki/Remote_Audio_Output_Protocol)*はリバースエンジニアリングされていますが、プロトコルはHTML/JSのみでは実現不可能です。おそらく、いくつかのネイティブヘルパー(例えば、ローカルサーバ)で。 – ephemient

答えて

3

JavaScriptでこれを実現することはできません。しかし、ブラウザからNPAPIプラグインを使用して実行することができます(大きな苦痛を伴う)。

ローカルサーバーを実行できる場合は、これをさらに簡単にするいくつかのnode.jsモジュールがあります。次の例では、近くのAirPlayデバイスに投稿されているオーディオファイルをストリーミングします。

  • NPMのモジュールairtunesが必要です。
  • FFmpegを使用してファイルをトランスコードします。

あなたがでそれをテストすることができます(あなたが試すことができます5000:

curl -X POST --data-binary @sample.mp3 http://localhost:8080/audio 

それはFFmpegのは/ usr/local/bin/ffmpegの中に配置されていることを前提とし、AirPlayのデバイスは、ローカルホスト上で利用可能であることエアフォイルスピーカー付)。

var airtunes = require('airtunes'), 
    express = require('express'), 
    app = express(), 
    device = airtunes.add('localhost'), 
    spawn = require('child_process').spawn; 

app.post('/audio', function(req, res) { 
    // use ffmpeg to reencode data on the fly 
    var ffmpeg = spawn('/usr/local/bin/ffmpeg', [ 
    '-i', 'pipe:0',  // Read from stdin 
    '-f', 's16le',  // PCM 16bits, little-endian 
    '-ar', '44100',  // Sampling rate 
    '-ac', 2,    // Stereo 
    'pipe:1'    // Output to stdout 
    ]); 

    // pipe data to AirTunes 
    ffmpeg.stdout.pipe(airtunes, { end: false }); 

    // detect if ffmpeg was not spawned correctly 
    ffmpeg.stderr.setEncoding('utf8'); 
    ffmpeg.stderr.on('data', function(data) { 
    if(/^execvp\(\)/.test(data)) { 
     console.log('failed to start ' + argv.ffmpeg); 
     process.exit(1); 
    } 
    }); 

    req.pipe(ffmpeg.stdin); 

    req.on('end', function() { 
    res.end(); 
}); 
}); 

device.on('status', function(status) { 
    console.log('status: ' + status); 
}); 

console.log('listening on port 8080'); 
app.listen(8080); 

1

これは私が*それを疑う本当に*私のため

var xhr = new XMLHttpRequest(), 
     xhr_stop = new XMLHttpRequest(), 
     hostname = "apple-tv.local", 
     port =":7000", 
     position = "0"; 


    xhr_stop.open("POST", "http://" + hostname + port + "/stop", true, "AirPlay", null); 
    xhr_stop.send(null); 

    xhr.open("POST", "http://" + hostname + port + "/play", true, "AirPlay", null); 
    xhr.setRequestHeader("Content-Type", "text/parameters"); 
    xhr.send("Content-Location: " + url + "\nStart-Position: " + position + "\n"); 

    // set timer to prevent playback from aborting 
    xhr.addEventListener("load", function() { 

     var timer = setInterval(function() { 

      var xhr = new XMLHttpRequest(), 
       // 0 something wrong; 2 ready to play; >2 playing 
       playback_info_keys_count = 0, 
       terminate_loop, playback_started; 

      xhr.open("GET", "http://" + hostname + port + "/playback-info", true, "AirPlay", null); 

      xhr.addEventListener("load", function() { 

       playback_info_keys_count = xhr.responseXML.getElementsByTagName("key").length; 
       console.log("playback: " + playback_started + "; keys: " + playback_info_keys_count) 

       // if we're getting some actual playback info 
       if (!playback_started && playback_info_keys_count > 2) { 
        playback_started = true; 
        console.log("setting playback_started = true") 
        terminate_loop = false; 
       } 

       // playback terminated 
       if (terminate_loop && playback_info_keys_count <= 2) { 
        console.log("stopping loop & setting playback_started = false") 
        clearInterval(timer); 
        var xhr_stop = new XMLHttpRequest(); 
        xhr_stop.open("POST", "http://" + hostname + port + "/stop", true, "AirPlay", null); 
        xhr_stop.send(null);      
        playback_started = false; 
       } 

       // playback stopped, AppleTV is "readyToPlay" 
       if (playback_started && playback_info_keys_count == 2) { 
        console.log("sending /stop signal, setting playback_started = false") 
        var xhr_stop = new XMLHttpRequest(); 
        xhr_stop.open("POST", "http://" + hostname + port + "/stop", true, "AirPlay", null); 
        xhr_stop.send(null); 
        playback_started = false; 
        terminate_loop = true; 
       } 

      }, false); 

      xhr.addEventListener("error", function() { 
       clearInterval(timer); 
      }, false); 
      xhr.send(null); 

     }, 5000); 

    }, false); 
関連する問題