CakePHP」カテゴリーアーカイブ

CakePHP + jQuery webcam plugin

プロフィールの画像を直接取得できればいいかなぁって思い、このプラグインを使ってみました。

最初は、jQueryだけでwebカメラの操作ができるんだって思っていました。
でも実際は、flashとjQueryを組み合わせて使います。

概要

  • ウェブカメラからの画像を画面にキャプチャする(html5 canvas)
  • ウェブカメラからの画像を取得しサーバー上に保存する

※デスクトップキャプチャソフト等も使えます。

完成イメージ

参考サイト

配布元
Ajalog.7z:jQueryでWebカメラを制御する

環境

  • XAMPP
  • CakePHP1.3.5
  • jQuery1.4.3
  • jQuery webcam plugin

準備

  1. 配布元からファイルをDL&展開
  2. 展開してできたファイルを適当な場所に設置(e.g. app/webroot/js/jquery.webcam.js app/webroot/swf/jscam.swf and jscam_canvas_only.swf)
  3. ウェブカメラを接続 or デスクトップキャプチャ等のソフトをインストール

webcam plugin

swfファイル

次の2つがあります。使いたい状況に応じて設定します。

  1. jscam.swf
  2. jscam_canvas_only.swf

1.はすべての機能が使えます。
2.はcanvasに描画する機能のみです。サーバー側にsaveしたい場合は1.を使います。

function

  • capture(delay):delay秒後にcaptureします
  • save(file): キャプチャ画像を保存 mode:”save”時にfile名を設定するとサーバー側に保存
  • getCameraList():有効なカメラリストの取得
  • setCamera(index):getCameraList()のindexでカメラを切り替える

mode

  • callback
  • save
  • stream

の3種類があります。
callbackは各コールバック関数を呼びます。
saveはcallbackと変わりませんが、save(file)を実行するときにデータを指定したファイルパスへ送信します。
streamは配布元を参照して下さい。

他のパラメータは、配布元を参照してください。

キャプチャした画像をcanvasに描画する処理は上記の参考サイトに書いてあるので、ここではサーバー側の処理を行います。

mode:“save”
onSave():画像の保存完了後に呼び出される。
保存画像を表示させるには、
このコールバックの中でページを書き換え処理を入れるか、
リダイレクトを行えばいいと思います。

jQuery関係のファイルは適当な場所で読み込む。
app/views/webcams/upload

	<strong>Webカメラから画像を設定</strong>
		<div id="jquery_camera"></div>
		<div id="camerastatus" style="margin-left: 10px;">
			<strong>カメラリスト</strong>
			<ul id="cams"></ul>
			<div id="status"></div>
			<button id="btn">キャプチャ</button>
		</div>
		<?php $this->Html->scriptStart(array('inline' => false)); ?>
			$(function(){
				var width = 320;
				var height = 240;
				$("#jquery_camera").webcam({
					width: width, // webcamの横サイズ
					height: height,// webcamの縦サイズ
					mode: "save",
					//swffile: "/swf/jscam_canvas_only.swf",
					swffile: "/swf/jscam.swf",
					// captrue(delay)が実行されたとき、残り時間を引数にもち、
					// 1秒ごとに呼び出される
					// e.g. delay = 5のときは remainが5,4,...,1と変化して呼び出される。
					onTick: function(remain) {
						if(0 == remain){
							$("#status").text("Cheese!");
						}else{
							$("#status").text(remain + "seconds remaining...");
						}
					},
					// mode:saveの場合
					// サーバー側での保存が完了し、サーバーからのレスポンスがくると呼ばれる
					onSave : function () {
						//キャプチャした画像をwebcam.saveメソッドで保存すると呼び出される。
						$("#status").text("done!!");
						var url = "リダイレクト先";
						window.location = url;
					},
					// Capture時に呼び出される
					onCapture: function() {
						webcam.save('/users/upload/<?= $this->data['User']['id'] ?>');
					},
					// debug用
					debug: function(type, string) {
						$("#status").html(type + ": " + string);
					},
					// 読み込み完了時
					onLoad: function() {
						var cams = webcam.getCameraList();
						for(var i in cams) {
							$("#cams").append("<li>" + cams[i] + "</li>");
						}
						$("#btn").click(function(){
							webcam.capture();
						});
					}
				});
			})
	<?php $this->Html->scriptEnd(); ?>

CakePHP

app/controllers/webcams_controller.php

・・・
	function upload($id = null){
		$this->laout = '';
		$updir = ini_get('upload_tmp_dir');
		$str = file_get_contents("php://input");
		$filepath = $updir . DS . 'user.jpg';
		file_put_contents($filepath, pack("H*", $str));
		// これ以降にDBへの登録処理をおこなう
		// e.g.下の処理はMediaPluginを使った時の処理の例
		$this->data['Picture']['title'] = '';
		$this->data['Picture']['description'] = '';
		$this->data['Picture']['model'] = 'User';
		$this->data['Picture']['foreign_key'] = $id;
		$this->data['Picture']['file'] = $filepath;
		if($this->Picture->save($this->data)){
			@unlink($filepath);
			exit();
		}else{
			//失敗時の処理
		}
・・・

CakePHP + ZendFramework (Gdata)でYouTubeアプリ作成

ZendFramework (Gdata)を使ってYouTubeのデータを操作

ZendFrameworkのGdataを使用して、YouTubeのデータ処理を行ってみました。

概要

YouTubeのAPIには
動画のデータ操作を行うData API
プレイヤーの操作を行うPlayer APIがあります。
この2つのAPIを利用して以下を行います。

  • YouTubeのApiを使って、ほしいデータを検索(Data API)
  • HP上に動画プレイヤーを設置する(Player API)
  • 検索した動画を設置した動画プレイヤーで再生する

他にも動画のアップロード等ができますが、そちらは、参考資料を参考にしてください。
クライアントライブラリはPHPとjavascriptだけではなく、Javaなどのほかの言語でも提供されています。

完成イメージ

環境

参考資料

Zend Gdataの設定

  • 上記のリンクからGdataの圧縮ファイルをDL&展開しておく
  • 展開したなかのlibraryディレクトリの中のZendディレクトリをvendorsまたはapp/vendorsに設置する。i.e.vendors/Zend or app/vendors/Zend
  • ここからZendFrameworkLoader Componentを作成する。i.e. app/contorollers/components/zend.phpを作成

app/contorollers/components/zend.php

<?php
class ZendComponent extends Object {

	/**
	 * Controller Startup Initialisation 
	 * Add APP/vendor to include path 
	 *  
	 * @throws Exception 
	 */
	public function startup() {
		$include = get_include_path();
		// Zendディレクトリをapp/vendorsに設置した場合
//		$include.= PATH_SEPARATOR . APP . 'vendors' . DS;
		// Zendディレクトリをvendorsに設置した場合
		$include.= PATH_SEPARATOR . VENDORS;
		$successful = set_include_path($include);

...........

}
?>

Controllerの作成

app/controllers/youtube_controller.php

<?php
class YoutubeController extends AppController{
	public $name = 'Youtube';
	public $uses = '';
	public $layout = 'default';
	public $components = array('Zend');
	
	public function index(){
		// YouTubeクラスのロード
		$this->Zend->loadClass('Zend_Gdata_YouTube');
		$yt = new Zend_Gdata_YouTube();
		// Queryの作成
		$query = $yt->newVideoQuery();
		$query->videoQuery = '世界卓球 -パチンコ -AKB';
		$query->startIndex = 1; // 開始番号
		$query->maxResults = 10; // 検索取得数
		$query->orderBy = 'viewCount'; // 閲覧数順
		
		// Feedの取得
		$videoFeed = $yt->getVideoFeed($query);
//		$videoFeed = $yt->getUserFavorites('username'); // ユーザのお気に入りの動画を取得
		// 取得したFeedをView変数に設定する
		$this->set('videoFeed', $videoFeed);
	}
}
?>

ZendFrameworkは使ったことがなかったので、知らなかったのですが、
クラス名はディレクトリの階層をアンダーバー”_”で区切ってつけられています。
たとえば。。
Zend_Gdata_YouTubeクラスは
Zend/Gdata/YouTube.phpにあります。
この命名規約のため階層が深くなれば、newするときのメソッド名が長くなります。
短くするために、上のコードのように
$query = $yt->newVideoQuery();
でnewできるようになっています。
VideoQueryは実際は、
Zend/Gdata/YouTube/VideoQuery.php
にあります。

さらに、$query->startIndexとメンバ変数のように設定している箇所があります。
しかし、クラス、継承しているクラスを見てみると、そのようなメンバ変数はありません。
ここの実際のメソッドはsetStartIndex()です。
setter&getterはメンバ変数のように扱える仕組みになっているようです。

Viewの作成

app/views/layouts/default.ctp

.....
<head>
	<?php echo $this->Html->charset(); ?>
	<title>
		<?php __('CakePHP: the rapid development php framework:'); ?>
		<?php echo $title_for_layout; ?>
	</title>
	<?php
		echo $this->Html->meta('icon');

		// ==============================================
		// CSS
		// ==============================================
		echo $this->Html->css('cake.generic');
		
		// ==============================================
		// javascript
		// ==============================================
		echo $this->Html->script('swfobject');
		echo $this->Html->script('jquery-1.4.3.min');
		echo $scripts_for_layout;
	?>
</head>
.......

app/views/youtube/index.ctp

<!-- TEST作成のため、CSSは直接書いている-->
<h1>test</h1>
<div id="yt" style="width: 800px;margin: auto;">
	<div style="float: left;">
		<div id="ytapiplayer">
		You need Flash player 8+ and JavaScript enabled to view this video.
		</div>
	</div>
	<div style="margin-left: 5px; float: left;width:260px; height:375px; overflow: scroll;">
		<?php
		foreach ($videoFeed as $videoEntry) {
			// サムネイルの取得
			$videoThumbnails = $videoEntry->getVideoThumbnails();
			// サムネイルは4つ取得できる(ここでは1つだけ表示した)
			foreach ($videoThumbnails as $thumbnail) {
				echo $this->Html->image($thumbnail['url'], array('height' => 90, 'width' => 120, 'id' => $videoEntry->getVideoId(), 'class' => 'youtube', 'title' => $videoEntry->getVideoTitle(), 'alt' => $videoEntry->getVideoTitle()));
				break;
			}
		}
		?>
	</div>
</div>
<script type="text/javascript">
	var ytplayer = null;
	// playerの準備が完了後に呼び出されるコールバック
	// playerを制御するには必ず実装が必要
	function onYouTubePlayerReady(playerid){
		// プレイヤーを取得(swfobjectで指定したidを指定する)
		ytplayer = document.getElementById("myytplayer");
//		ytplayer.cueVideoById();
	}
	
	var params = { allowScriptAccess: "always" };
	var atts = { id: "myytplayer" };
	swfobject.embedSWF("http://www.youtube.com/v/u1zgFlCw8Aw?enablejsapi=1&playerapiid=ytplayer", 
	"ytapiplayer", "500", "375", "8", null, null, params, atts);
	$(function(){
		$("img.youtube").click(function(){
			ytplayer.loadVideoById($(this).attr("id"));
		});
		$("img.youtube").hover(function(){
			$(this).css("cursor", "pointer")
				.fadeTo("fast", 0.5);
		},function(){
			$(this).fadeTo("fast", 1);
		})
	});
	
</script>

imgタグのid属性に動画のidを設定しています。
サムネイルがクリックされたときに、その動画が再生されます。