Raspberry Piを手に入れてまず試しにやってみるのは音楽をストリーミング再生させてみることではないでしょうか。(私だけ?)
コマンドラインを利用すれば簡単にストリーミングさせることができます。
こちらにあるように
ssh
$ youtube-dl 'https://www.youtube.com/watch?v=hoge' -o - | mplayer -
簡単にストリーミング再生出来ます。
Node.jsでコマンドライン操作
Node.jsのマニュアル & ドキュメンテーションを見ると
app.js
var spawn = require('child_process').spawn,
ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
ls.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
ls.on('close', function (code) {
console.log('child process exited with code ' + code);
});
こんな風に書いてあります。通常のコマンドはこれでいけるのですが、二つ以上のコマンドを組み合わせようとすると(パイプ)上手くいきません。
node.jsでパイプを使ったコマンドを実行するには
node.jsでパイプを使ったコマンドを実行するには - GitHubGist
こちらのGistを拝見したところ、sh -c
コマンドをchild_process
で実行して、実際に行いたいコマンドは引数に格納して実行すれば良い様です。
分かった様な、分からない様な。(分ってない)試しにapp.js
をこんな風に書いてみました。
app.js
var spawn = require('child_process').spawn;
var cmd = "youtube-dl 'https://www.youtube.com/watch?v=wArJc179HNk' -o - | mplayer - -novideo";
function shspawn(command) {
return spawn('sh', ['-c', command]);
}
var child = shspawn(cmd);
var buf="";
child.stdout.on('data',function(data){
buf=buf+data;
});
child.stderr.on('data',function (data){
console.log('exec error: '+data);
});
child.on('close',function(code) {
console.log("exit.");
});
1時間ほどのプレイリスト - Indie/Indie-Pop Compilation - May 2015 (55-Minute Playlist) ですが上手くストリーミング再生出来ました。
expressを使ってブラウザで操作する
express
を利用して幾つかのプレイリストを操作できる様にしてみました。
app.js
var express = require('express');
var ejs = require("ejs");
var spawn = require('child_process').spawn;
var app = express();
app.engine('ejs',ejs.renderFile);
app.get('/', function(req, res){
res.render('pontube.ejs',
{title: 'PonTube Pi'});
});
app.get('/control', function (req, res) {
console.log(req.query);
var id = req.query.id;
var watch = "https://www.youtube.com/watch?v=" + id;
var clear_cmd = "killall mplayer";
//console.log("cmd = "+cmd);
function shspawn(command) {
return spawn('sh', ['-c', command]);
}
var child = shspawn(clear_cmd);
var buf="";
child.stdout.on('data',function(data){
buf=buf+data;
});
child.stderr.on('data',function (data){
//console.log('exec error: '+data);
});
child.on('close',function(code) {
console.log( 'CLEAR. PLAY.' );
});
var play_cmd = "youtube-dl " + watch + " -o - | mplayer - -novideo";
function shspawn(command) {
return spawn('sh', ['-c', command]);
}
var child = shspawn(play_cmd);
var buf="";
child.stdout.on('data',function(data){
buf=buf+data;
});
child.stderr.on('data',function (data){
//console.log('exec error: '+data);
});
child.on('close',function(code) {
console.log( 'EXIT.' );
});
});
app.get('/stop', function (req, res) {
console.log(req.query);
var id = req.query.id;
var stop_cmd = "killall mplayer";
//console.log("cmd = "+cmd);
function shspawn(command) {
return spawn('sh', ['-c', command]);
}
var child = shspawn(stop_cmd);
var buf="";
child.stdout.on('data',function(data){
buf=buf+data;
});
child.stderr.on('data',function (data){
//console.log('exec error: '+data);
});
child.on('close',function(code) {
console.log( 'STOP.' );
});
});
var server = app.listen(3000, function () {
var host = server.address().address
var port = server.address().port
console.log('This app listening at http://192.168.0.12:'+ port)
});
views/pontube.ejs
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="content-type"
content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=no">
<title><%=title %></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" type="text/css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<style>
body{
margin: 0 auto;
max-width: 640px;
}
article{
margin: 20px;
}
</style>
</head>
<body>
<header>
<h1 class="text-center h2"><%=title %></h1>
</header>
<article>
<div class="list-group">
<button type="button" class="list-group-item" id="wArJc179HNk">Indie/Indie-Pop Compilation - May 2015 (55-Minute Playlist)</button>
<button type="button" class="list-group-item" id="YYYJDalKI9E">Indie/Pop/Folk Compilation - January 2016 (1-Hour Playlist)</button>
<button type="button" class="list-group-item" id="wiKgHFU8L9g">1.5 Hours of Rock n' Roll - Rock/Hard Rock Playlist</button>
<button type="button" class="list-group-item" id="WVP3fUzQHcg">2 HOUR LONG Piano Music for Studying, Concentrating, and Focusing Playlist</button>
<button type="button" class="list-group-item" id="ubZASS3uPrs">Relaxing Love Songs 80's & 90's Playlist</button>
</div>
<button class="btn btn-default" id="stop">stop</button>
</article>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script>
$(".list-group-item").click(function() {
var station = $(this).attr("id");
$.get("http://192.168.0.12:3000/control", { id: station } );
});
$(".btn").click(function() {
var stop = $(this).attr("id");
$.get("http://192.168.0.12:3000/stop", { id: stop } );
});
</script>
</body>
</html>
コマンドライン操作も良いですが、手元のブラウザから操作出来ると愛着が湧いてきます。
音声コマンドと組み合わせても面白いかもしれません。では。