20190527のNode.jsに関する記事は8件です。

APL(Alexa Presentation Language)のSpeakItemでmp3を鳴らす

こんにちは

APLのSpeakItemの中でaudioタグを書いてもmp3が鳴らない仕様があり永らく悩んでいたのですが、APLでmp3を鳴らす方法を見つけたのでざっくり共有します。

例えば

hoge.mp3をAPLで鳴らすAPLを送るとします。
解説の都合上、datasourcesとExecuteCommandsから先に。

datasources-1
"datasources": {
  "pagerAnimationData": {
    "properties": {
      "topicSsml": [
        "<speak><audio src=\"https://s3-ap-.../hoge.mp3\" /></speak>"
      ],
    },
    "transformers": [
      {
        "inputPath": "topicSsml",
        "outputName": "topicSpeech",
        "transformer": "ssmlToSpeech"
      },
      {
        "inputPath": "topicSsml",
        "outputName": "topicText",
        "transformer": "ssmlToText"
      }
    ]
  }
}
ExecuteCommands(抜粋)
{
  "type": "SpeakItem",
  "componentId": "talk_0"
}

鳴らない

さて、以下のようにDocumentを書いておいても鳴りません。

document-1(抜粋)
{
  "type": "Text",
  "id": "talk_0",
  "text": "(音声再生中)",
  "speech": "${payload.pagerAnimationData.properties.topicSpeech[0]}",
  "position": "absolute",
  "width": 0,
  "height": 0
}

以下でもダメでした。

document-1a(差分)
  "speech": "${payload.pagerAnimationData.properties.topicSsml[0]}",

鳴る

下記のように、speechに直接URLを指定すると鳴らす事が出来ます。

datasources-2
"datasources": {
  "pagerAnimationData": {
    "properties": {
      "topicSsml": [
        "(ここにはSSML書かない)"
      ],
      "topicSound": [
        "https://s3-ap-.../hoge.mp3"
      ]
    },
    "transformers": [
      {
        "inputPath": "topicSsml",
        "outputName": "topicSpeech",
        "transformer": "ssmlToSpeech"
      },
      {
        "inputPath": "topicSsml",
        "outputName": "topicText",
        "transformer": "ssmlToText"
      }
    ]
  }
}
document-2
{
  "type": "Text",
  "id": "talk_0",
  "text": "(音声再生中)",
  "speech": "${payload.pagerAnimationData.properties.topicSound[0]}",
  "position": "absolute",
  "width": 0,
  "height": 0
}

気をつける点

開発コンソールのシミュレータでは鳴らない(動作が止まる)のでご注意ください。
・念のためtransformersの影響を受けない場所に置いたほうがいいかも。(未検証)

参考

Alexa Command SpeakItem coupled with self provided mp3 ? - Forums

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WindowsでNodejsのバージョン管理がしたいので、nvm-windowsをインストールしてみた

  • いくつかのWindowsマシンに導入してみたが、うまくいかないマシンがあったのでメモ
    • 過去に書いて未投稿だったものを公開するので、内容が古い可能性もあります

基本は以下の通りでOK

npm -vできなかった場合 :sob:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.js + Puppeteer を使って無料でデスクトップより大きなスクリーンショットを撮る 4k 8k

はじめに

建築系のCG制作プロダクションで3DCGモデラーをしています。

建築の仕事をしていると、広範囲・高解像度の地図とか航空写真が欲しい時があります。
一番簡単なのは、国土地理院の地理院地図から画像を保存することです。
無料ですし、簡単で大変便利です。ただ、この地図、若干、古いんです

もっと新しい地図が欲しければ、ゼンリンやMapFanみたいな地図会社の有料サービスを利用するか、
GoogleマップやYahooマップでスクリーンショットを撮るしかありません。

高解像度のスクリーンショット

"無料で"というと、スクリーンショットを撮ることになります。

ただ、"広範囲・高解像度" となると、デスクトップよりずっと大きな画像になります。
普通にスクリーンショットを撮ろうとすると1画面に収まりません。デュアルディスプレイでも無理です。

ブラウザのエクステンションに、"ページ全体のスクリーンショットを撮る"ものがありますが、
画像のキャッシュなどの問題で、キレイに撮るのはなかなか大変です。

なので以前は、仕方なくスクリーンショットをたくさん撮って、Photoshopで合成してました...。

Chromeを自動操作出来るpuppeteer

puppeteernode.js上で動くChromeを自動操作するためのライブラリです。
大変短いコードで簡単にWEBページのスクリーンショットを撮れます。
Puppeteer API

本来、WEBテスト用のツールですが、"ウィンドウサイズを指定"出来るので、
4kでも8kでも任意のサイズのスクリーンショットを撮れます。

インストール

node.js Install
puppeteer Install

実践

以下、Yahooマップの写真モードでやってみました。

main.js
// yahoo maps in Japan
const url = 'https://yahoo.jp/scdMa0'; //マップの表示設定をした後、URLを取得(アドレスバーのじゃなくて、アイコンの"URLボタン"のほうから取る)

(async() => {
    const puppeteer = require('puppeteer');
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.setDefaultNavigationTimeout(120000);
    const response = await page.goto(url,{waitUntil:"networkidle2"});
    let n = 4;
    let k = 1024;
    // 4k = 4096 pixel x 4096 pixel 
      try {
            let map_area = '#map';
            await page.setViewport({width:n*k,height:n*k}); // ウィンドウサイズを指定
            for (let i = 2; i > 0; i--) { // ブラウザにキャッシュさせるために2回繰り返す
                await page.waitFor(90000); //通信環境にもよると思いますが、少し待たないと画像が全部来ないです。
                if(i == 1){
                    let img_name = 'map_'+ n +'k' + i + '.jpg';
                    const map_area_Handle = await page.$(map_area);
                    await map_area_Handle.screenshot({path: img_name});
                    console.log(img_name);
                }
        }

      } catch (e) {
        console.log(e);

        throw e;
      } finally{
          await browser.close();
      }
})();



run.bat
node main.js

結果

最大ズームで8k画像(8192 pixel x 8192 pixel)を取得出来ました。
sct20190527090741.png

画像サイズについて

ウチの通信環境だと、8kはうまくいかない時があります。
画像タイルが全部ロードされず、歯抜けになってしまうことがあります。

12kでも試してみましたが、全然撮れません...。半分しか画像が来ません。
4kくらいまでならちゃんと撮れます。

扱いやすいサイズにする

そもそも、あまり画像サイズがデカいと後で扱いにくいので、
最終的に、大きくても4kに収まるようにするのがよいと思います。
理想的には2k以下が軽くていいです。大抵は事足ります。

広さが足りなければ、ズームアウトすればいいですし、
一部分だけでも高解像度が欲しければ、そのエリアと周囲を分けるといいと思います。

動くことは動くけど

シンプルなコードですが、ちゃんと絵が撮れるようになるまでちょっと苦労しました。
画像が全部ロードされるまで待つ方法が分からず、結局、時間指定です。

node.jsって何?ってところから始めたので、エンジニアでもなんでもない自分にとっては上出来ですが...。
うまい方法わかる方いらっしゃいましたら、ご教授ください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ゼロから始める生体認証webアプリケーション作成(1) node.jsチュートリアル

はじめに

初めてQiitaの記事を書くので、拙いところがあると思いますが見てくれると嬉しいです。
今回、webアプリケーションで生体認証を実装することを目標に、JavaScript等の必要な知識を勉強しながら実装します。

今回の目標

環境の構築、簡単なnode.jsの実装

1. node.jsのインストール

こちらの記事を参考にしました。
【Mac】node.jsインストール方法
Node.jsとは
Node.js を5分で大雑把に理解する

2. HTMLファイルの読み込み

実際にnode.jsをローカルホストで試してみます。
Node.jsサーバーの実装

server.js
//html,fsオブジェクトの生成
var http = require('http');
var fs = require('fs');

//リンクの作成
var html_paths = {index:'../html/index.html'};
var html_pages = {index:fs.readFileSync(html_paths.index,'utf-8')};

//サーバーリクエスト処理(何度も使うので関数化しました)
function res_write(res,target,text_type) {
  res.writeHead(200,{'Content-Type':text_type});
  res.write(target);
  res.end();
}
//サーバーの作成
var server = http.createServer(function(req,res){
  var target;
  switch (req.url) {
    case '/':
    case '/index':
      res_write(res,html_pages.index,'text/html');
      break;

    default:
      res.writeHead(404,{'Content-Type':'text/plain'});
      res.end('not fond');
      return;
  }

});

server.listen(1234);
console.log('Server has been started');
index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>sample</title>
</head>
<body>
  <h1>test.html</h1>
</body>
</html>

結果
スクリーンショット 2019-05-27 17.16.46.png

localhost:/1234に接続できました。

3. JavaScriptの読み込み

簡単なjavascriptファイルを作成

test.js
function test(){
  alert('test');
}
test();

javascriptのファイルを読み込めるようにserver.jsに追記します

server.js
var js_paths={test:'./test.js'};
var js_pages= {test:fs.readFileSync(js_paths.test,'utf-8')};
server.js
case '/test.js':
      res_write(res,js_pages.cam,'text/plain'); break;

index.htmlにjavascriptファイルを読み込む記述をします。

index.html
<script type="text/javascript" src="./test.js"></script>

結果 javascriptのファイルをHTML上に読み込むことができました。
スクリーンショット 2019-05-27 17.33.42.png

まとめ

  • node.jsの環境を構築することができた。
  • node.jsの簡単な実装。

次回は、JavaScriptで画像を加工する方法を実装します。
感想、アドバイス等あればお願いします。

おまけ

node.jsの参考書(amazonへのリンクです)
JavaScriptエンジニアのためのNode.js入門

kindle unlimitedなら無料、kindle版も350円と安くてオススメです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ゼロから始める生体認証webアプリケーション作成(1)

はじめに

初めてQiitaの記事を書くので、拙いところがあると思いますが見てくれると嬉しいです。
今回、webアプリケーションで生体認証を実装することを目標に、JavaScript等の必要な知識を勉強しながら実装します。

今回の目標

環境の構築、簡単なnode.jsの実装

1. node.jsのインストール

こちらの記事を参考にしました。
【Mac】node.jsインストール方法
Node.jsとは
Node.js を5分で大雑把に理解する

2. HTMLファイルの読み込み

実際にnode.jsをローカルホストで試してみます。
Node.jsサーバーの実装

server.js
//html,fsオブジェクトの生成
var http = require('http');
var fs = require('fs');

//リンクの作成
var html_paths = {index:'../html/index.html'};
var html_pages = {index:fs.readFileSync(html_paths.index,'utf-8')};

//サーバーリクエスト処理(何度も使うので関数化しました)
function res_write(res,target,text_type) {
  res.writeHead(200,{'Content-Type':text_type});
  res.write(target);
  res.end();
}
//サーバーの作成
var server = http.createServer(function(req,res){
  var target;
  switch (req.url) {
    case '/':
    case '/index':
      res_write(res,html_pages.index,'text/html');
      break;

    default:
      res.writeHead(404,{'Content-Type':'text/plain'});
      res.end('not fond');
      return;
  }

});

server.listen(1234);
console.log('Server has been started');
index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>sample</title>
</head>
<body>
  <h1>test.html</h1>
</body>
</html>

結果
スクリーンショット 2019-05-27 17.16.46.png

localhost:/1234に接続できました。

3. JavaScriptの読み込み

簡単なjavascriptファイルを作成

test.js
function test(){
  alert('test');
}
test();

javascriptのファイルを読み込めるようにserver.jsに追記します

server.js
var js_paths={test:'./test.js'};
var js_pages= {test:fs.readFileSync(js_paths.test,'utf-8')};
server.js
case '/test.js':
      res_write(res,js_pages.cam,'text/plain'); break;

index.htmlにjavascriptファイルを読み込む記述をします。

index.html
<script type="text/javascript" src="./test.js"></script>

結果 javascriptのファイルをHTML上に読み込むことができました。
スクリーンショット 2019-05-27 17.33.42.png

まとめ

  • node.jsの環境を構築することができた。
  • node.jsの簡単な実装。

次回は、JavaScriptで画像を加工する方法を実装します。
感想、アドバイス等あればお願いします。

おまけ

node.jsの参考書(amazonへのリンクです)
JavaScriptエンジニアのためのNode.js入門

kindle unlimitedなら無料、kindle版も350円と安くてオススメです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Nuxt v2.7 で実行時に「TypeError: fsevents.watch is not a function」のエラーで起動できない

Nuxt v2.7.1にしたら、起動できなくなった

Nuxt v2.7.x で、yarn dev 実行時に以下のエラーが出た。

fsevents-handler.js
  const stop = fsevents.watch(path, callback);
                        ^

TypeError: fsevents.watch is not a function
    at createFSEventsInstance (/Users/masaakikakimoto/Documents/nuxt_firebase_sns/node_modules/@nuxt/builder/node_modules/chokidar/lib/fsevents-handler.js:57:25)
    at setFSEventsListener (/Users/masaakikakimoto/Documents/nuxt_firebase_sns/node_modules/@nuxt/builder/node_modules/chokidar/lib/fsevents-handler.js:111:16)
    at FsEventsHandler._watchWithFsEvents (/Users/masaakikakimoto/Documents/nuxt_firebase_sns/node_modules/@nuxt/builder/node_modules/chokidar/lib/fsevents-handler.js:296:18)
    at initWatch (/Users/masaakikakimoto/Documents/nuxt_firebase_sns/node_modules/@nuxt/builder/node_modules/chokidar/lib/fsevents-handler.js:433:27)
    at LOOP (fs.js:1787:14)
    at process._tickCallback (internal/process/next_tick.js:176:11)
npm ERR! code ELIFECYCLE
npm ERR! errno 1

調べると以下のIsuueがHit
https://github.com/nuxt/nuxt.js/issues/5725

nodejs のバージョンを下げることで解決した。

とりあえずnode v10.15.3でNuxtが正常起動することを確認しました。

(※v12系やv9系では、エラーが出るようだ。)

※追記 おまけ

気を良くして、いろいろとパッケージを追加していたら、またまたNuxtが起動しなくなった。

エラー内容

 ERROR  Failed to compile with 1 errors                       friendly-errors 17:07:19

This dependency was not found:                                friendly-errors 17:07:19
                                                              friendly-errors 17:07:19
* core-js/modules/es7.promise.finally in ./.nuxt/client.js    friendly-errors 17:07:19
                                                              friendly-errors 17:07:19
To install it, you can run: npm install --save core-js/modules/es7.promise.finally

corejs v2.6.5を入れ直すことで解決した。

yarn add core-js@latest2.6.5
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

API を使って LINEWORKS BOT を登録する

私もそうですが、BOT を登録するときは Developer Console 画面で行っていると思います。
ですが、「Console 画面にはログインして欲しくないけど、Bot を登録する権限はあげたい」とか「似たような(決して同じではない) Bot をユーザごとに登録したい」などのレアな要望が、たまーにあるのです。(そう、私にはあったのです^^)

そんなときには!
API を使って BOT 登録すれば要望が実現させることができるのですYO!

LINEWORKS API で BOT を登録するためには

LINEWORKS BOT を登録するためには複数の API を使用します。
API を以下の順番で使用して、 BOT を登録した上で指定ユーザにメッセージを送信します。

  1. トーク Bot のテナント登録
  2. トーク Bot のドメイン登録
  3. メッセージ受信サーバー追加
  4. トーク Bot からメッセージ送信

実際のコード

さて、それではコードをさらしたいと思います。
今回はのちの勉強のため、JavaScript で記述しています。

  • request モジュールを使っているので npm install request してインストールしておきます。
  • api_id などはご自身の Developer Console を確認して値を入れてください。
registerBot.js
const api_id = "api id";
const consumer_key = "consumer key";
const token = "server list token";
const account_id = "ryo_saeba@hunter.city";
const domain_id = 00000000;
const callback_url = "https;//www.xyz.jp/callback";

// トーク Bot のテナント登録
const request = require('request');
const uri_text = "https://apis.worksmobile.com/" + api_id;
let options = {
    uri: uri_text + "/message/registerBot/v4",
    headers: {
        "Content-type": "application/json",
        "consumerKey": consumer_key,
        "Authorization": "Bearer " + token
    },
    json: {
        "name": "test bot",
        "photoUrl": "https://developers.worksmobile.com/favicon.png",
        "description": "defeat the promise process bot",
        "managerList": [account_id]
    }
};
request.post(options, (error, response, body) => {
    if(body.errorMessage) return;
    let botNo = body.botNo;
    // トーク Bot のドメイン登録
    options.uri = uri_text + "/message/registerBotDomain/v3"
    options.json = {
        "botNo": botNo,
        "domainId": domain_id,
        "usePublic": true,
        "usePermission": false
    }
    request.post(options, (error, response, body) => {
        if(body.errorMessage) return;
        // メッセージ受信サーバー追加
        options.uri = uri_text + "/message/setCallback/v2";
        options.json = {
            "botNo": botNo,
            "callbackUrl": callback_url,
            "callbackEventList": ["text", "sticker", "image"]
        };
        request.post(options, (error, response, body) => {
            if(body.errorMessage) return;
            // トーク Bot からメッセージ送信
            options.uri =  uri_text + "/message/sendMessage/v2",
            options.json = {
                "botNo": botNo,
                "accountId": account_id,
                "content": {"type":"text","text":"BOT 登録が完了しました(^ω^)"}
            };
            request.post(options, (error, response, body) => {
                console.log(body);
                if(body.errorMessage) return;
                console.log("success");
            });
        });
    });
});

これを node registerBot.js で実行すれば BOT が登録されます!
1558664439.png

無事に BOT 登録が完了しました(^ω^)ヤッタネ

今回のコードは・・・長い!

4回 API を実行するので、わかっていたことですが、長いですね!
なるべく短くしようと optionslet して使いまわしたりしたのですが、やはり長いです。
しかも requestCallback を4回もしているので、ネストが深い。

ここからさらに、Bot 利用メンバーの登録 API を使ってユーザを限定させたり、Bot を含むトークルーム作成 API を使って複数人トークルームを作ったりするとさらにネストが増えていきます。
DB と繋いで botNo やトークルーム ID を DB に登録する処理なんかを追加するとさらにネストします。

いっぺんに色んなことをしようとすると、どんどん階層が深く、深く…
頭の痛い話ですね!( ゚Д゚)

今回、Callback 関数でコードを記述しましたが、Javascript には promise というオブジェクトがあり、これを使えば階層を浅く、見やすくできるようです。
Qiita にも先輩方の記事がたくさん上がっているので是非読んでみようと思います!

おわりに

ここまでお付き合いいただきありがとうございました。
次はこのコードを promise を使った記述で階層を浅く、見やすく処理をしたいと思います!
promise 使えなきゃ JavaScript でコード書けるって言っちゃいけないよね(笑)』って言われて涙目になったからじゃないデスヨ。
えぇえぇ、違いますとも。日々精進あるのみなのです。
・・・がんばるます(つ□T)
もっといっぱい勉強しないとな、と感じる毎日です。

ではまた!(^^)/

参考にさせていただきましたm(_ _)m

LINEWORKS Developers

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

TypeScript地獄の地図と幻の型たち

地獄の管理人、その名はTypeScript

※前回の記事 地獄からの使者、その名はTypeScript ~ 固かった型の形 ~ 2

1. 気が付くとそこは迷宮

 地獄の地図

image.png

 初学者がTypeScriptを始めようとするのなら、おそらくはどこかしらの解説記事をみることになるだろう。ところがTypeScriptは迷宮の入り口なのである。知らずに進めば、GPSもコンパスも役に立たない永劫の樹海を彷徨うことになるだろう。

 まずは入り口でこう問われることになる

『おぬしの進むべき道は、前か後ろか?』

 大抵の人間はこう答えるだろう。

「もちろん前に進む、そのために来たのだ!」

 その答えに対して、再び問われる。

『ふむ、まあ良いだろう。では次の問いだ。おぬしは環境を重んじるか?』

 大半の人間にはその意味が分からない。しかし分からないままこう答える。

「環境は良い方がいいなぁ」

 気がついたらフロントエンドでエコシステムをぶん回して、わけも分からずWebPackを設定する結果となる。この時点で、TypeScriptをまともに動かすための設定地獄が始まるのだ。

 初学者がTypeScriptの真の地獄を回避するために必要なこと

 まずは用途を明確にする。ターゲットはフロントエンドなのかバックエンドなのか?
 大抵の場合は、フロントエンドにTypeScriptを使おうとする人が多いと思われる。逆にバックエンドでTypeScriptを使うのはそれほど苦労しない。フロントエンドでTypeScriptを使おうとする者が地獄に填まりやすいのである。

 そもそものTypeScriptを地獄とせしめているのは何か?それはnode_modulesに潜んでいる魑魅魍魎である。こいつらとの接触しなければ、新月の闇夜も安心して越せる。地獄からの誘いを回避できるのだ。

 しかし基本文法を脱した先にあるTypeScriptの解説記事は、気軽にimportというキーワードが書いてある。これがある時点で.tsから.jsに変換される際に、面倒なお約束ごとが生成されるのだ。

 フロントエンドでTypeScriptを扱おうと思ったら、まずはimportとは一切関わらずにプログラムを組んだ方が良い。地獄へ踏み込むのは、ある程度慣れた後だ。ノーマルモードを選択せず、いきなりヘルモードで始めて叩きのめされるのはCXな課長のお約束とするだけで十分だろう。まあ、ノーマルモードに戻っても、結局叩きのめされるのだが。

2. TypeScriptの真の力、それは幻を生み出す力

 幻の混入した図

 
image.png

 TypeScriptには二種類の挙動がある。トランスコンパイル時に、古いターゲット環境に合わせて互換コードが出力する挙動と、書いたものが蜃気楼のように消える挙動である。

 互換コード出力機能は大変便利な機能である反面、TypeScriptの本懐の機能では無い。では、TypeScriptの真の機能は何か、それは幻を生み出す力なのだ。

 幻の力とは何なのか。その片鱗を見いだすためのコードはこれだ。

const value = "今日は世界"
const typeName = typeof value
type typeName2 = typeof value
console.log(typeName) //'string'
//console.log(typeName2) //error

 TypeScriptではtypeofの扱いがJavaScriptと違う。typeNameはJavaScriptの挙動として文字列の"string"という実態を持つが、typeName2はTypeScriptの挙動で実態を持たない。ただの幻なのだ。何をどうやってもtypeName2を出力する方法は存在しない。この実体を持つtypeofと、持たないtypeofの違いをきちんと理解しておかないと、TypeScriptでの転生無双どころか六道輪廻の宿業が終わらない。

 出力できないものをわざわざ作るのは何故か?それがTypeScriptの型定義なのである。ただし、ここで勘違いしてはならないのは、JavaScriptの型とTypeScriptの型は根本的に別物だと言うことだ。JavaScriptの型は実行時に実体を持ち、TypeScriptの型定義はただの蜃気楼である。たどり着いてみると、何も存在しないのだ。

const value2:number = "あいうえお" as any as number
console.log(typeof value2) //string

型に何を指定しようと、TypeScriptの型はコンパイル時のエラーチェックまででその寿命を終える。そして型に何が指定されていようと、出力コードには一切の影響を与えない。実行時にエラーを発生させることも無い。コンパイルが終わった時点で、幻を作り出していた霧は、綺麗さっぱり消え去るのだ。

 その他に幻の代表格、interfaceがある。このinterfaceは実行時に、その型の内容を取り出すことは出来ない。変数の中に、たまたま定義したとおりの実態が入っていれば話は別だが、結局のところ自分で実態を用意しない限り、触れることはかなわないのである。

4. 幻、それはヘブンへの誘いの光

 地獄、そう、そこはヘルなのだ。ヘルであっても腹は減る。しかし幻の力の使い道を知っていれば話は別だ。幻の導く先にこそ、ユートピアでありヘブンであり、真の極楽が広がっているのだ。必要なのは、幻と侮ること無く信じて付いていくことなのだ。

 終着点、そこにあるものはきっと・・・

 成仏

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む