BlankTar

about | blog | works | photo

なんか面白いものを作ろうかと思って、HTML5のAnalyzerNodeとやらを使ってみました。
細かいことはともかくとして、大雑把に使い方を。

なんかこんな感じのやつが出来る。マイクの付いた新しめのブラウザでご覧下さい。

ソースコードはこんな感じです。

<audio muted></audio>
<canvas width=640 height=480></canvas>
<script>
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;

var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');

canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;

navigator.getUserMedia(
	{audio : true},
	function(stream){
		document.querySelector('audio').src = URL.createObjectURL(stream);
		var audioContext = new AudioContext();
		var analyser = audioContext.createAnalyser();
		var timeDomain = new Float32Array(analyser.frequencyBinCount);
		var frequency = new Uint8Array(analyser.frequencyBinCount);
		audioContext.createMediaStreamSource(stream).connect(analyser);

		(function animation(){
			analyser.getFloatTimeDomainData(timeDomain);
			analyser.getByteFrequencyData(frequency);

			context.clearRect(0, 0, canvas.width, canvas.height);

			context.strokeStyle = 'blue';
			context.beginPath();
			context.moveTo(0, canvas.height - frequency[0]*canvas.height/255);
			for(var i=0; i<frequency.length; i++){
				context.lineTo(
					i*canvas.width/frequency.length,
					canvas.height - Math.max(0, frequency[i]*canvas.height/255)
				);
			}
			context.stroke();

			context.strokeStyle = 'red';
			context.beginPath();
			context.moveTo(0, canvas.height/2 + timeDomain[0]*canvas.height/2);
			for(var i=0; i<timeDomain.length; i++){
				context.lineTo(
					i*canvas.width/timeDomain.length,
					canvas.height/2 + timeDomain[i]*canvas.height/2
				);
			}
			context.stroke();

			requestAnimationFrame(animation);
		})();

	},
	console.log
);
</script>

配列とAudioContextとやらを作って、AnalyzerNodeAudioSourceNodeに接続。
あとはgetFloatTimeDomainDataってやつで波形、getByteFrequencyDataってやつで周波数(波形をフーリエ変換したやつ)を取得出来ます。
どちらもgetFloatを使うと浮動小数点で、getByteから始まるやつを使うと0から255までの値で取得出来ます。分かりやすくて良いね。

マイクからリアルタイムに音を取得したい場合はcreateMediaStreamSourceの代わりにcreateMediaElementSourceを使います。大体こんな感じ。

<audio src="music.mp3" controls></audio>
<script>
	var audioContext = new AudioContext();
	var analyser = audioContext.createAnalyser();
	audioContext.createMediaElementSource(document.querySelector('audio')).connect(analyser);
</script>

それ以外の使い方は一緒です。getUserMediaとかやらなくて良いだけもっとシンプル。

普通にcanvasを使っているので、わりと何でも出来ます。楽しい。

余談ですが、google chromeでgetUserMediaを使おうとする場合はhttpsを使わないといけないようです。Firefoxとかは分からん。
そんなわけでこのページもHTTPSになってるはず。

curlを使ってメールを受信するのを試したので、今度は送信をやってみます。SMTPってやつですね。

とりあえず、送信する文章を作ります。

$ cat mail.txt
To: send-to@example.com
From: send-from@example.com
Subject: this is a test

hello world!

こんなやつ。
最低限このくらいのヘッダを入れておくことをおすすめしますが、ヘッダ無しで本文だけ書いちゃっても送信出来ます。

で、送信します。

$ curl smtps://smtp.example.com:465 --mail-from 'send-from@example.com' --mail-rcpt 'send-to@example.com' -u username -T mail.txt

こんな感じ。

gmailの場合はfromアドレスを宜しくやってくれるので、もう少し簡単に以下のように送信出来ます。

$ curl smtps://smtp.gmail.com:465 --mail-rcpt 'send-to@example.com' -u username -T mail.txt

他のサーバーでは試していませんが、多分省略出来るところもあるはず。

標準入力から内容を指定することも可能で、その場合は以下のようにします。

$ <mail.txt curl smtps://smtp.example.com:465 --mail-from 'send-from@example.com' --mail-rcpt 'send-to@example.com' -u username -T -

シェルスクリプトなんかに組み込む場合は以下のようにしてパスワードも書いちゃうと良いかも。

$ <mail.txt curl smtps://smtp.example.com:465 --mail-from 'send-from@example.com' --mail-rcpt 'send-to@example.com' -u username:password -T -

勿論、取り扱いには十分注意、です。

ちなみに何も考えずに日本語を指定したところ、なんとなく受信に成功しました。受信するサーバーやクライアントによっては大丈夫なようです。
ただ、マルチバイトのデータを送るのはあまりお行儀が宜しくないのでほどほどに。出来ればちゃんとエンコーディングしましょう。面倒臭いけれどね。

ほとんどのエンジニアには解けるパズル2を解いていたらcurlが楽しくなってしまったので、curlの勉強をしようと思いまして。
んで色々調べていたら、どうもcurlはIMAPも取り扱えるらしい。なんでやねん、と思いつつ試してみたので、やり方をメモ。

今回はgmailで試すのでgmailのアドレスを書いていますが、おそらくIMAPサーバーならどこででも使えます。試してません。

curlでメールを送信する記事もあります。あわせてどうぞ。

メールの件数を取得する

とりあえず、メールボックスの一覧を取得します。

$ curl -u username 'imaps://imap.gmail.com:993'
Enter host password for user 'username':
* LIST (\HasNoChildren) "/" "INBOX"
* LIST (\HasChildren \Noselect) "/" "[Gmail]"
* LIST (\All \HasNoChildren) "/" "[Gmail]/&MFkweTBmMG4w4TD8MOs-"
* LIST (\HasNoChildren \Trash) "/" "[Gmail]/&MLQw33ux-"
--以下略--

環境にもよると思いますが、なんかいっぱい出てきます。ずらずら。文字化け(?)は気にしてはいけない。

そしたら、INBOXに入ってるメールの件数を取得してみます。

$ curl -u username 'imaps://imap.gmail.com:993' -X 'EXAMINE INBOX'
Enter host password for user 'username':
* FLAGS (\Answered \Flagged \Draft \Deleted \Seen $Forwarded $MDNSent $NotPhishing $Phishing Junk NonJunk)
* OK [PERMANENTFLAGS ()] Flags permitted.
* OK [UIDVALIDITY 123456789] UIDs valid.
* 10051 EXISTS
* 0 RECENT
* OK [UIDNEXT 12345] Predicted next UID.
* OK [HIGHESTMODSEQ 1234567

一部適当な数字で置き換えていますが、だいたいこんな出力。
気にすべきは、10051 EXISTSってところ。10051件のメールがあります。わお。

メールを読む

そしたら今度は、いよいよメールを読んでみます。

$ curl -u username --silent 'imaps://imap.gmail.com:993/INBOX;UID=10051;SECTION=TEXT' | nkf
Enter host password for user 'username':
ここからメールの本文。ずらずらと。

--silentオプションを外すと、ダウンロードの進捗状況が表示されます。無くても良い。
nkfはメールをデコードするために使っています。必要無い場合もあるし、別のコマンドにしないといけない場合もあるかも。
UID=10051のところで指定している数字がメールの番号で、数字を大きくすると新しい、小さくすると古いメールになります。
;SECTION=TEXTを外すとヘッダー込みのデータが、;SECTION=HEADERにするとヘッダーのみのデータを取得出来ます。

未読/既読の操作

でまあ、こうなると未読メールの一覧も取得したくなるわけです。取得してみます。

$ curl -u username 'imaps://imap.gmail.com:993/INBOX' -X 'SEARCH UNSEEN'
Enter host password for user 'username':
* SEARCH 10046 10050

こんな感じ。
お察しの通り、表示された番号がメールのUIDです。さっきのメールを見るコマンドを使えば目的のメールを見ることが出来ます。
取得するだけで既読フラグが付くようで、わりと良い感じです。

既読フラグを操作したいときはSTOREコマンドで以下のように。

$ curl -u username 'imaps://imap.gmail.com:993/INBOX' -X 'STORE 10050 -Flags \Seen'
Enter host password for user 'username':
* 10050 FETCH (FLAGS ())

$ curl -u username 'imaps://imap.gmail.com:993/INBOX' -X 'STORE 10050 +Flags \Seen'
Enter host password for user 'username':

大体同じ感じのコマンド。
違うのはFlagsの前の+-だけです。+なら既読に、-なら未読に。

なんでも出来る感じあって良いね、curl。もっときちんと使いこなせるようになりたいものです。

参考: Curl: Recent IMAP changes

[ << ] [ 9 ] [ 11 ] [ 13 ] [ >> ]