Javascript:浏览器中的Airplay

时间:2011-11-08 23:34:22

标签: javascript airplay

有没有办法在浏览器中使用JavaScript将图像,视频和音频发送到AirPlay服务器?

2 个答案:

答案 0 :(得分:3)

在JavaScript中无法实现这一点。但是,您可以使用NPAPI插件从浏览器运行它(非常痛苦)。

如果您可以运行本地服务器,那么有几个node.js模块可以让您更轻松。以下示例将流式传输发布到附近AirPlay设备的任何音频文件。

  • 它需要我维护的NPM的airtunes模块。
  • 使用FFmpeg对文件进行转码。

您可以使用以下方法进行测试:

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

它假设FFmpeg位于/ usr / local / bin / ffmpeg,并且AirPlay设备在localhost:5000上可用(您可以尝试使用Airfoil扬声器)。

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 :(得分: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);