Nuxt.js Tips
nuxt.jsのtipsです
componentに値を渡す場合
送る側
<template> <MyComponent /> </template> <script> import MyComponent from "~/components/MyComponent.vue" export default { components: { MyComponent } } </scipt>
受け取る側(MyComponet.vue)
<script> export default { props: { aaa, bbb, ccc } } </script>
型チェックをしたい場合
<script> export default { props: { aaa: String, bbb: Boolean, ccc: Array } } </script>
propsに直接文字列を入れる場合
<MyComponent :myprop="StringDayo" />
とすると
Raw expression: :myprop="StringDayo"
となる
解決策
<MyComponent myprop="StringDayo" /> or <MyComponent :myprop="'StringDayo'" />
props等の変数をhtmlの要素にいれたい
<template> <nuxt-link to="this.link"> Link Dayo </nuxt-link> </template> <script> export default { props: { link: String } } </script>
これだとpropsのlinkが呼ばれずに/this.linkというリンクが参照されてしまう
解決策としては変数を使いたいときには要素の前に:をつける
<nuxt-link :to="this.link">
画像をpropsとして読み込む
<template> <div> <img :src="image_src" /> </div> </template> <script> export default { props: { filename: String, }, data() { return { image_src: require(`~/assets/img/${this.filename}`) } } } </script>
methodsを追加する場合
<template> <div class="foobar" @mouseover="mouseOn()" @mouseout="mouseOut()"> hogefuga </div> </template> <script> export default { methods: { mouseOn() { document.getElementById(foobar).style.color = "red"; }, mouseOut() { var img = document.getElementById(foobar); img.style.color = "gray"; } } } </scrip>
ページ読み込み時に処理を行いたいとき
<script> export default { mounted() { alert('foobar'); } } </script>
jsonファイルを読み込んで表示する
{ "aaa": true "bbb": false "ccc": "hogehoge" }
/pages/test.vue
<script> export default { data() { return { json: require(`static/json/test.json`) } } } </script>
▼v-for
要素を繰り返えしたいときに使う
上のjsonファイルを使う
<template> <div> <ol> <li v-for"(value, index) in json" property1="index" property2="value"></li> </ol> </div> </template> <script> export default { data() { return { json: require(`static/json/test.json`) } } } </script>
v-bind:class
クラス属性を条件分岐で設定するしないを分ける
<template> <div> <ol> <li v-for"(value, index) in json" v-bindclass="{ active: aaa }"></li> // 描画される(aaa === true) <li v-for"(value, index) in json" v-bindclass="{ active: bbb }"></li> // 描画されない(bbb === false) </ol> </div> </template> <script> export default { data() { return { json: require(`static/json/test.json`) } } } </script>
nuxt generateで動的ルーティングもbuild対象にする
nuxtは_foobar.vueといったアンダースコアで始まるvueファイルを作ることで動的にルーティングすることができる。
しかしこの動的ルーティングはデフォルトでnuxt generateの静的ファイルビルドの対象外となっている
以下のようにnuxt.config.jsで明示的に指定してやることで静的なルーティングがビルドされる
module.exports = { generate: { routes:[ '/hogehoge', '/fuga/fuga' ] } }
また、ファイル数が多くなって直接編集が面倒になったときは、以下のようにもできる
staticファイル以下のjsonファイルを読み込んでroutingに設定している
const fs =require('fs') const filename = fs.readdirSync("./static/").map(x => x.match(/(.*)(?:\.([^.]+$))/)[1]) module.exports = { generate: { routes: filenames } }
ホットリロードで開発サーバをたてる
npm run dev
listen portを開ける
上記のnpm run devでデバッグサーバをたてることが可能になるが、デフォルトではlocalhostからしかアクセスできない。
なのでnuxt.config.jsで以下のように指定する
module.exports = { server: { host: '0.0.0.0' } }
rss.xmlを設定する
nuxt generate時にrss.xmlを更新する方法
まずstatic/rss.xmlを作る
<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0"> <channel> <title>My Home Page</title> <link>https://my-home-page.com/</link> <description>このページはぼくのホームページぃぃぃ!!!</description> <lastBuildDate>${generate by modules}</lastBuildDate> <language>ja</language> <item> <title>日記</title> <link>https://my-home-page/blog/</link> <description>はじめての日記</description> <pubDate>Fri, 01 Mar 2019 18:00:00 +0900</pubDate> </item> </channel>
このstaticファイルの内容はコンパイルされずにそのままdist以下に配置されるので、
nuxt generateが終わった時点で${generate by modules}のところを書き換えてやればよい
modules/hook/generate.js
require('date-utils') const fs = require ('fs') const now = new Date() const rss = fs.readFileSync("static/rss.xml", "utf-8").replace("<lastBuildDate>${generate by modules}</lastBuildDate>", `<lastBuildDate>${now.toFormat('DDD, DD MMM YYYY HH24:MI:SS +0900')}</lastBuildDate>`) module.exports = function () { this.nuxt.hook('generate:done', async generator => { fs.writeFileSync("dist/rss.xml", rss); }) }
moduleを書いたら、nuxt.config.jsで指定する
module.exports = { modules: [ '@/modules/hook/generate' ] }
bootstrapを読み込む際に二重で読み込まれるのを防ぐ
nuxt.config.js modules.exports = { modules: [ ['bootstrap-vue/nuxt', { css: false }] ] }
v-if/v-else-if/v-else
コンポーネント等の表示切替をv-if等を使って切り替えることができる
<template> <div> <img v-if="this.type==='image'" :src="src"></img> <video v-else-if="this.tyep==='movie'" :src="src" autoplay loop muted></video> <p v-else>missing media</p> </div> </template> <script> export default { props: { type: String, link: String }, data() { return { src: require(`~/assets/img/${this.link}`) } } } </script>
v-for内でv-ifを使う
v-forとv-ifを同じ要素内で使うことは推奨されていない
<template> <div> <div v-for="(value, index) in objects"> <div v-if="value">aaa</div> <div v-if="index===0">bbb</div> </div> </div> </template>
外部リソースを読み込む(bootstrapとかjqueryとか)
<script> export default { head () { return { script: [ { src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js' }, { src: 'https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js' } ], link: [ { rel: 'stylesheet', href: 'https://fonts.googleapis.com/css?family=Roboto' } ] } } } </script>
custom layoutを読み込む
<script> export default { layout: 'custom' } } </script>
▼404ページの作成
pages/404/index.vueに作成する
▼動的ルーティングで値を受け取る
pages/_id.vue
<template> <div> {{parameter}} </div> </template> <script> export default { asyncData({ params }) { return { parameter: params.id } } } </script>
AWS S3でStatic website hostingを使うけど、bucketへの直リンクアクセスを制限したい場合
AWS S3に配置した静的コンテンツを使ってcloud front経由でwebsiteを公開するときに、S3 bucket自体をoriginとして指定する場合はorigin access identityでcloud frontからのアクセスのみを許可するということが可能になる。
しかし、S3のstatic website hosting機能を使ってエンドポイントを発行した場合は、このorigin access identityが使えない
この場合S3 bucket側でcloud frontからのアクセスのみを許可するといったスマートなアクセス制限はできない。
IPアドレスによる制限は可能だが、ここで指定するIPは実際にアクセスするユーザのIPレンジではなく、cloud frontのIPを指定しなければいけない。それでもいいのだが、このIPは変わる可能性もあるし、大量にルールを書かなければいけないので避けたい。
解決方法としては、cloud frontからcustome headerとして任意の文字をrefererで送り、S3 bucket側でその特定のheaderがある場合のみGetObjectできるといったbucket policyを設定してやればよい
※static website hosting機能にこだわるのは、サブディレクトリでもindex補完機能を使いたいから
(cloud front側で使えるindex補完はrootディレクトリのみとなっている)
1. S3のwebsite hosting機能をonにする
3. bucket policyを設定する
{ "Version": "2008-10-17", "Id": "http referer policy", "Statement": [ { "Sid": "Referer-Allow", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::example-bucket/*", "Condition": { "StringLike": { "aws:Referer": "foobar" } } }, { "Sid": "Explicit deny to ensure requests are allowed only from specific referer.", "Effect": "Deny", "Principal": "*", "Action": "s3:*", "Resource": "arn:aws:s3:::example-bucket/*", "Condition": { "StringNotLike": { "aws:Referer": "foobar" } } } ] }
この時点でまず指定したheaderの有無でアクセス制限がかかっているか確認する
curl --header 'referer:foobar' ${static website hosting Endpoint URL} →アクセスできる curl --header 'referer:fizzbazz' ${static website hosting Endpoint URL} →アクセスできない(403エラー)
4. cloudfrontの設定
- Origin Domain Name
- static website hostingのエンドポイントURLを入力
- custome Header
後は普通に設定すればOKです
distributingが終わったら、一応cloudfrontのdomainにアクセスして確認しまs
(*****.cloudfront.netってやつ)
opencvとpythonで色抽出
OpenCVを使ってPythonで特定の色を画像から抜き出します
色を数値で表す方法としてRGBがまず上がりますが、今回はHSVという値を使います。
HSV色空間 - Wikipedia
RGBは時のごとくRed, Green, Blueで値で色を表現しますが、
HSVとは色相(Hue)、彩度(Saturation)、明度(Value)で色を表現し画像認識なんかでよく使われます
元データ
この某イカの絵のピンク部分を抜き出していきまs
ソース
#!/usr/bin/python import numpy as np import cv2 # image info image_file = 'ika.jpg' img = cv2.imread(image_file) # detect pink hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) lower = np.array([150, 100, 100]) # 紫に近いピンク upper = np.array([175, 255, 255]) # 赤に近いピンク img_mask = cv2.inRange(hsv, lower, upper) img_color = cv2.bitwise_and(img, img, mask=img_mask) # debug cv2.imwrite("ika_hsv.jpg", img_color)
実行結果
触手の紫を消すために少し修正
lower = np.array([157, 100, 170]) upper = np.array([175, 255, 255])
いい感じにピンクが抽出できました
Microsoft Azureでラズベリーパイから cloud live streamingする方法
Microsoft AzureのMedia Servicesを使ってラズベリーパイからストリーミングを行う方法です
背景的なもの
現在パブリッククラウドサービスはAWS, Azure, GCP等があり、それぞれストリーミングに関しては以下のようなサービスを提供しています
(IBMはプライベートクラウドに力をいれているらしく今回は調査対象外)
Cloud Growth Rate Increases; Amazon, Microsoft & Google all Gain Market Share | Synergy Research Group
AWS(wowza)
メディアストリーミングチュートリアル - Amazon CloudFront | AWS
Install Wowza Streaming Engine on Raspberry Pi
Azure Media Services
今回はAzureを利用してみます
Media Services : azure.microsoft.com
構成
- チャネル、プログラム、StreamingEndpointsからなる
- 各Media Servicesアカウントには、複数のチャネル、複数のプログラム、複数のStereamingEndpointsを含めることができる
- 帯域幅とセキュリティのニーズに応じて、StreamingEndpointサービスを一つまたは複数のチャネル専用にすることができる
- StreamingEndpointはどのチャネルからでもプルできる
channel
- Media Servicesにおいてライブストリーミングコンテンツの処理を担う
- ライブストリーミングコンテンツを処理するためのパイプラインを表す
- 入力エンドポイントであり、その取り込みURLをライブトランスコーダーに対して指定する
- チャネルはライブトランスコーダからライブ入力ストリームを受け取り、1つまたは複数のStreaming Endpointを介してストリーミングできる状態にする
- ストリームはあらかじめプレビューし、確認した上で処理、配信するが、チャネルはその際にしようするプレビューエンドポイントも提供する
- チャネル作成時に取り込みようURLとプレビューURLを取得できる
- チャネルが開始済み状態である必要はない
- ライブトランスコーダーからチャネルへのデータのプッシュを開始する準備ができたら、チャネルを開始する必要がある
- ライブトランスコーダーがデータの取り込みを開始した後、ストリームをプレビューできる
- チャネルの状態
- 停止済み:初期状態。ストリーミングの許可はされていない
- 開始中:チャネルを開始している。更新やストリーミングはできない。
- 実行中:ライブストリームを処理できる
- 停止中:チャネルを停止している
- 削除中:チャネルを削除している
Azureの設定
流れとしては以下のようになります
1. Azure Media Servicesのアカウント作成
2. StreamingEndpointsの開始
3. チャネルの作成
4. live eventの作成
5. channel とlive eventのstart
1. Create Azure Media Services Account
Media Servicesを選択
Addを選択
データを入力していきます
- Account Name
- Subscription
- Resource Group
- Location
- Storage Account
作成が完了すると、Media Servicesの一覧に新しい項目が追加されます
2. Start Streaming Endpoint
1で作成したMedia Serviceのアカウントを選択しOverview BladeからStreaming Endpointを選択します
そのまま以下の通りEndpointを開始します
3. Start Channel
Live Streaming BladeからCustom Createを選択します
- Setting
- Endoding type: Pass Through
- Pass Throughはsingle bit encoding
- クライアント側の通信速度に応じて画質を変更するmulti bit encodingも可能だが、その分遅延が発生するので今回はやらない
- Encoding UnitもPass Throughの際は関係ない(Reserved Unit0でよい)
- Name:なんでも
- Description: なんでも
- Automatically start the channel after creation: チェック外す
- Endoding type: Pass Through
- Ingest
- Streaming protocol: RTMP
- Preview
- 変更の必要なし
- Create
channelが作成されるとLive Streaming Bladeに作成されたChannelが表示されます
作成されたChannelを選択し、INGEST URL(Primary)をメモしておきます
4. Create Live Event
ChannelのメニューからLive Eventを選択します
Live Eventのデータを入力します
- Name
- asset name
- archive window
- 最小設定可能時間は5分
- archive自体は項目にDayもあるしStorageに余裕がある限り保存できそう
- ただし一回のストリーミングに関しては連続して8時間以下が推奨とのこと
Live Eventが作成されたら、Streaming URLをメモしておきます
5. Start Channel & Live Event
最後にChannelとLive Eventを開始します
Raspberry Piの設定
設定
# カメラの確認 $ modprobe bcm2835-v4l2 # ラズパイカメラを利用する場合 $ v4l2-ctl --list-device mmal service 16.1 (platform:bcm2835-v4l2): /dev/video0 # 音声入力デバイスの確認 $ arecord -l **** List of CAPTURE Hardware Devices **** ### 今回はマイク機能なしのカメラを利用 # 映像フォーマット、解像度、フレームレートの組み合わせの確認 $ v4l2-ctl -d /dev/video0 --list-formats-ext ioctl: VIDIOC_ENUM_FMT Index : 0 Type : Video Capture Pixel Format: 'YU12' Name : Planar YUV 4:2:0 Size: Stepwise 16x16 - 3280x2464 with step 2/2 Index : 1 Type : Video Capture Pixel Format: 'YUYV' Name : YUYV 4:2:2 Size: Stepwise 16x16 - 3280x2464 with step 2/2 Index : 2 Type : Video Capture Pixel Format: 'RGB3' Name : 24-bit RGB 8-8-8 Size: Stepwise 16x16 - 3280x2464 with step 2/2 Index : 3 Type : Video Capture Pixel Format: 'JPEG' (compressed) Name : JFIF JPEG Size: Stepwise 16x16 - 3280x2464 with step 2/2 Index : 4 Type : Video Capture Pixel Format: 'H264' (compressed) Name : H.264 Size: Stepwise 16x16 - 3280x2464 with step 2/2 Index : 5 Type : Video Capture Pixel Format: 'MJPG' (compressed) Name : Motion-JPEG Size: Stepwise 16x16 - 3280x2464 with step 2/2 Index : 6 Type : Video Capture Pixel Format: 'YVYU' Name : YVYU 4:2:2 Size: Stepwise 16x16 - 3280x2464 with step 2/2 Index : 7 Type : Video Capture Pixel Format: 'VYUY' Name : VYUY 4:2:2 Size: Stepwise 16x16 - 3280x2464 with step 2/2 Index : 8 Type : Video Capture Pixel Format: 'UYVY' Name : UYVY 4:2:2 Size: Stepwise 16x16 - 3280x2464 with step 2/2 Index : 9 Type : Video Capture Pixel Format: 'NV12' Name : Y/CbCr 4:2:0 Size: Stepwise 16x16 - 3280x2464 with step 2/2 Index : 10 Type : Video Capture Pixel Format: 'BGR3' Name : 24-bit BGR 8-8-8 Size: Stepwise 16x16 - 3280x2464 with step 2/2 Index : 11 Type : Video Capture Pixel Format: 'YV12' Name : Planar YVU 4:2:0 Size: Stepwise 16x16 - 3280x2464 with step 2/2 Index : 12 Type : Video Capture Pixel Format: 'NV21' Name : Y/CrCb 4:2:0 Size: Stepwise 16x16 - 3280x2464 with step 2/2 Index : 13 Type : Video Capture Pixel Format: 'BGR4' Name : 32-bit BGRA/X 8-8-8-8 Size: Stepwise 16x16 - 3280x2464 with step 2/2 # 映像フォーマット一覧の確認 $ ffmpeg -f v4l2 -list_formats all -i /dev/video0 ffmpeg version N-89701-gb2be76c Copyright (c) 2000-2018 the FFmpeg developers built with gcc 4.9.2 (Raspbian 4.9.2-10) configuration: --arch=armel --target-os=linux --enable-gpl --enable-libx264 --enable-nonfree libavutil 56. 7.100 / 56. 7.100 libavcodec 58. 9.100 / 58. 9.100 libavformat 58. 3.100 / 58. 3.100 libavdevice 58. 0.100 / 58. 0.100 libavfilter 7. 10.100 / 7. 10.100 libswscale 5. 0.101 / 5. 0.101 libswresample 3. 0.101 / 3. 0.101 libpostproc 55. 0.100 / 55. 0.100 [video4linux2,v4l2 @ 0x2f3d1b0] Raw : yuv420p : Planar YUV 4:2:0 : {16-3280, 2}x{16-2464, 2} [video4linux2,v4l2 @ 0x2f3d1b0] Raw : yuyv422 : YUYV 4:2:2 : {16-3280, 2}x{16-2464, 2} [video4linux2,v4l2 @ 0x2f3d1b0] Raw : rgb24 : 24-bit RGB 8-8-8 : {16-3280, 2}x{16-2464, 2} [video4linux2,v4l2 @ 0x2f3d1b0] Compressed: mjpeg : JFIF JPEG : {16-3280, 2}x{16-2464, 2} [video4linux2,v4l2 @ 0x2f3d1b0] Compressed: h264 : H.264 : {16-3280, 2}x{16-2464, 2} [video4linux2,v4l2 @ 0x2f3d1b0] Compressed: mjpeg : Motion-JPEG : {16-3280, 2}x{16-2464, 2} [video4linux2,v4l2 @ 0x2f3d1b0] Raw : Unsupported : YVYU 4:2:2 : {16-3280, 2}x{16-2464, 2} [video4linux2,v4l2 @ 0x2f3d1b0] Raw : Unsupported : VYUY 4:2:2 : {16-3280, 2}x{16-2464, 2} [video4linux2,v4l2 @ 0x2f3d1b0] Raw : uyvy422 : UYVY 4:2:2 : {16-3280, 2}x{16-2464, 2} [video4linux2,v4l2 @ 0x2f3d1b0] Raw : nv12 : Y/CbCr 4:2:0 : {16-3280, 2}x{16-2464, 2} [video4linux2,v4l2 @ 0x2f3d1b0] Raw : bgr24 : 24-bit BGR 8-8-8 : {16-3280, 2}x{16-2464, 2} [video4linux2,v4l2 @ 0x2f3d1b0] Raw : yuv420p : Planar YVU 4:2:0 : {16-3280, 2}x{16-2464, 2} [video4linux2,v4l2 @ 0x2f3d1b0] Raw : Unsupported : Y/CrCb 4:2:0 : {16-3280, 2}x{16-2464, 2} [video4linux2,v4l2 @ 0x2f3d1b0] Raw : bgr0 : 32-bit BGRA/X 8-8-8-8 : {16-3280, 2}x{16-2464, 2} /dev/video0: Immediate exit requested
撮影
Azure Media Servicesは、音声データと音声コーデックを指定して送信しないとエラーになり受け付けてもらえません
- 無音(音声データなし)はNG
- 無音(音声データあり)はOK
ラズパイカメラやUSBカメラのみでマイクがない場合は、ffmpeg側で無音の音声データを付加してAzure Media Services側に送信する必要があります
# ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}... $ ffmpeg -vsync passthrough -f v4l2 -vcodec h264 -framerate 30 -video_size 320x180 -i /dev/video0 -f lavfi -i aevalsrc=0 -shortest -strict -2 -c:a aac -b:a 7350 -ar 7350 -g 60 -keyint_min 60 -c:v copy -preset ultrafast -b:v 150k -maxrate 150k -bufsize 150k -f flv $INGESTURI/mystream
- $INGESTURLはAzure側でチャネルを設定した際にメモしたものです
- さらに注意点として、ffmpegで送信する場合にはINGEST_URIの後ろにmystream等の名前をつけないとエラーになります
- mystreamに特に意味はなく、なんでもOKです
ffmpegのオプションに関しては
- f fmt: force format
- V4l2: Video for linux
- alsa: audio
- hw: 1,0 audioのinput の指定
- c:v videoのcodec
- c:a audioのcodec
- framerate / フレームレート
- r / set frame rate
- s / size,set frame size(WxH)
- i / input deviceの指定
- /dev/video0 / 接続されているvideoデバイスの一つ
- vcodec / force video codec
- ultrafast /
- acodec / audio codec
- libfaac / 同上
- ab / audio bitrate(pleas use -b:a)
- b / video bitrate(please use -b:v)
- sc_thresold / シーンチェンジ検出の閾値(0でdefault, -1 でシーンチェンジ検出無効)
たまに落ちる場合は以下みたくして対応
#!/bin/bash modprobe bcm2835-v4l2 INGESTURI="rtmp://*****************************************************" # primary while : do ffmpeg -vsync passthrough -f v4l2 -vcodec h264 -framerate 30 -video_size 320x180 -i /dev/video0 -f lavfi -i aevalsrc=0 -shortest -strict -2 -c:a aac -b:a 7350 -ar 7350 -g 60 -keyint_min 60 -c:v copy -preset ultrafast -b:v 150k -maxrate 150k -bufsize 150k -f flv $INGESTURI/mystream sleep 10 done
遅延に関して
だいたい色々チューニングをした結果、16,7秒くらいの遅延が発生します。
Azure側の処理の都合上、最短で15-20秒は遅延が発生するらしいです。
Azure Media Player RTMP Latency
現在Microsoft側でも低レイテンシ版の開発をしているとのことですが、あまり優先度は高くないとのこと。
Azure Media Services: Top (187 ideas) – Customer Feedback for Microsoft Azure
ちなみにGCPの中の人とも話す機会があったのですが、大体おんなじくらいの遅延は発生しますとのこと。
これは現在のクラウドストリーミングのサービスや技術が、大人数にむけて配信することをターゲットとしており、秒単位で遅延を減らす方向にはシフトしていないとのこと。
ブラウザでの表示
AzureのUI上で確認できますが、ストリーミングをWebブラウザに表示する方法です
HTML
<head> <link href="//amp.azure.net/libs/amp/2.1.5/skins/amp-default/azuremediaplayer.min.css" rel="stylesheet"> <script src="//amp.azure.net/libs/amp/2.1.5/azuremediaplayer.min.js"></script> </head> <body> <video id="azuremediaplayer" class="azuremediaplayer amp-default-skin amp-big-play-centered" tabindex="0"></video> </body>
$(function() { var myOptions = { "nativeControlsForTouch": false, controls: true, autoplay: true, width: "640", height: "400", } myPlayer = amp("azuremediaplayer", myOptions); myPlayer.src([ { "src": "$Streaming URL without protocol", "type": "application/vnd.ms-sstr+xml" } ]); });
tips
windowsからの配信
配信がうまくいかずに、まずは問題の切り分けとしてWindowsから配信テストを行う方法
### 接続したUSBカメラ等が認識しているか確認 $ ffmpeg -f dshow -list_devices true -i dummy [dshow @ 0000000000150980] DirectShow video devices (some may be both video and audio devices) [dshow @ 0000000000150980] "MS-M103HU USB Camera" [dshow @ 0000000000150980] Alternative name "@device_pnp_******************23196}\global" [dshow @ 0000000000150980] DirectShow audio devices [dshow @ 0000000000150980] Could not enumerate audio only devices (or none found). dummy: Immediate exit requested ## 2行目のMS-M103HU USB Cameraが今回接続したUSBカメラ(以降はこの名前をオプションとして指定する) ## Alternative nameも利用することができる。同じ種類のカメラを複数接続したときに利用するっぽい ### 検出されたカメラの仕様を確認する $ ffmpeg -f dshow -list_options true -i video="MS-M103HU USB Camera" [dshow @ 00000000003a09c0] DirectShow video device options (from video devices) [dshow @ 00000000003a09c0] Pin "Capture" (alternative pin name "0") [dshow @ 00000000003a09c0] pixel_format=yuyv422 min s=1280x720 fps=12 max s=1280x720 fps=12 [dshow @ 00000000003a09c0] pixel_format=yuyv422 min s=1280x720 fps=12 max s=1280x720 fps=12 [dshow @ 00000000003a09c0] vcodec=mjpeg min s=1280x720 fps=30 max s=1280x720 fps=30 [dshow @ 00000000003a09c0] vcodec=mjpeg min s=1280x720 fps=30 max s=1280x720 fps=30 ## このカメラだと2パターンの録画しか出来ない
テスト撮影
# ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}... # -f fmt: force format # V4l2: Video for linux # alsa: 音声 # hw: 1,0 音声の入力指定 # -c:v videoのcodec # -c:a audioのcodec ### infile options ## input optionはカメラが対応していないものを指定してもエラーが返って来る # このカメラは1280x720しか対応していないので他の解像度を指定してもダメ > ffmpeg -f dshow -video_size 640x480 -i video="MS-M103HU USB Camera" [dshow @ 00000000003b0a00] Could not set video options video=MS-M103HU USB Camera: I/O error # このカメラは12FPS(yuvj)か30FPS(mjpeg)しか対応していないので他のFPSを指定してもダメ > ffmpeg -f dshow -framerate 24 -i video="MS-M103HU USB Camera" [dshow @ 00000000006809c0] Could not set video options video=MS-M103HU USB Camera: I/O error # 選択可能なFPSの場合は適したコーデックが自動で選択される > ffmpeg -f dshow -framerate 30 -i video="MS-M103HU USB Camera" Stream #0:0: Video: mjpeg (MJPG / 0x47504A4D), yuvj422p(pc, bt470bg/unknown/unknown), 1280x720 [SAR 96:96 DAR 16:9], 30 fps, 30 tbr, 10000k tbn, 10000k tbc > ffmpeg -f dshow -framerate 12 -i video="MS-M103HU USB Camera" Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 1280x720, 12 fps, 12 tbr, 10000k tbn, 10000k tbc # コーデックを指定する場合は対応したFPSじゃないとダメ > ffmpeg -f dshow -vcodec mjpeg -framerate 12 -i video="MS-M103HU USB Camera" [dshow @ 00000000005c0c00] Could not set video options video=MS-M103HU USB Camera: I/O error ### output option # mp4ファイルで出力したいとき(yuv420p) > ffmpeg -f dshow -vcodec mjpeg -framerate 30 -video_size 1280x720 -i video="MS-M103HU USB Camera" -pix_fmt yuv420p rec.mp4 # 出力動画のFPSを落としたいとき(-r 3) > ffmpeg -f dshow -vcodec mjpeg -framerate 30 -video_size 1280x720 -i video="MS-M103HU USB Camera" -pix_fmt yuv420p -r 3 rec.mp4
実際にWindowsからストリーミング
ffmpeg \ -rtbufsize 100M \ -vsync passthrough \ -f dshow \ -vcodec mjpeg -framerate 30 \ -video_size 1280x720 \ -i video="MS-M103HU USB Camera" \ -f lavfi \ -i aevalsrc=0 -shortest \ -strict -2 \ -c:a aac \ -b:a 128k \ -ar 44100 \ -r 30 \ -g 60 \ -keyint_min 60 \ -b:v 400000 \ -c:v libx264 \ -preset ultrafast \ -bufsize 400k \ -maxrate 400k \ -f flv rtmp://<your channel>/mystream
これでもうまくいかない場合はWirecastがAzure media servicesに対応しているので、まずはWirecast経由でストリーミングできるか確認
最新動向
この投稿を書いてる途中にlow latency modeが実装されたとのこと
ポストによると8-10秒まで落とすことが出来るらしく、更に2秒以下のultra low latency modeの開発がはじまったらしい
Reduce live streaming latency for Azure Media Services live streaming – Customer Feedback for Microsoft Azure
azure.microsoft.com
さらにRTSPのサポートの開発もはじまったとのこと
Directly ingesting RTSP – Customer Feedback for Microsoft Azure
RasperryPiでリアルタイムクロック(RTC-8564NB)を使ってアラームを設定する
ラズベリーパイで以下のRTCを使う方法です
akizukidenshi.com
事前準備
RTC-8564NBはラズベリーパイとi2cという通信方式で通信を行います
事前にraspi-configでi2c通信を有効にしておきます
接続&認識
上記の秋月の製品はソケット等もついているのでそのままブレッドボード等でラズベリーパイに接続します
接続したらまずはラズベリーパイがRTCをきちんと認識しているか、されていたらアサインされたアドレスの確認をします
$ sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- 51 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
次にRTC用のドライバを適用させます
$ sudo sh -c "echo pcf8563 0x51 > /sys/class/i2c-adapter/i2c-1/new_device" $ sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
- 8564ではなく8563になっていますが、8563はラズパイにデフォルトで入っていて、かつ8564互換になっています
- UUは認識しているだけではなく、実際にOSが利用している状態です
時刻あわせ
初期状態のRTCは時刻が正確ではない可能性があるので、まずはシステム側の時間を使って時刻をあわせます
# (念のために)システム側の時刻を最新にupdate(要ネットワーク) $ sudo ntpdate -v ntp.nict.jp $ date Wed 16 Oct 22:08:02 JST 2018 # 次に実際にRTCにシステムの時刻を反映させます $ sudo hwclock -w # (逆にRTCの時刻にシステム側を合わせたい場合はsオプションを使います) $ sudo hwclock -s # 実際に一致しているかはcオプションで確認します $ sudo hwclock -c hw-time system-time freq-offset-ppm tick 1539694800 1539694800.003842 1539694811 1539694811.004140 25 0 1539694822 1539694821.004745 39 0
Alarm機能設定
このRTCは設定した時間で割り込みを行うAlarm機能があります
端子はオープンドレインなのでAlarmがオンになるとLOWになります
AF/AIEの設定
割り込みのタイミングとして、決まった時間で割り込みを行うAIE(Alarm Interrupt Enable)と、決まった周期で割り込みを行うTIE(Time Interrupt Enable)という設定があります
そして、割り込みが発生した時点でそれぞれAF(Alarm Flag)、もしくはTF(Timer Flag)がセットされます
これが1になっていると割り込みが発生しないので、都度フラグクリアをしないといけません
# OSがRTCを掴んでいるので一時的に外します $ sudo modprobe -r rtc_pcf8563 # AIEをセットし、AFをクリアします(TF/TIEも今回利用しないのでクリアします) $ sudo i2cset -y 1 0x51 0x01 0x02 b # 確認 $ sudo i2cget -y 1 0x51 0x01 0x02
今回はAFをクリアして、かつAIEをセットしたいので、上記のレジスタのAddress01(0x01)のbit1だけ1であとは0にします
00000010b(2進数)は16進数で0x02になのでそれをvalueとして送ります
Alarm時刻の設定
次に実際にAlarmの時刻を設定します
レジスタのAddress 09~0Cがそれぞれ以下のように対応しています
- 0x09: Minute Alarm
- 0x0A: Hour Alarm
- 0x0B: Day Alarm
- 0x0C: Weekday Alarm
例えば毎日10:30にAlarmが発生するように設定します
(RTCにはUTCで時間が入っているのでUTC基準で入力します)
# Minutes Alarm(30分) sudo i2cset -y 1 0x51 0x09 0x30 # Hour Alarm(10時) sudo i2cset -y 1 0x51 0x0A 0x10 # Day Alarm(0x80: AE) sudo i2cset -y 1 0x51 0x0B 0x80 # Weekday Alarm(0x80: AE) sudo i2cset -y 1 0x51 0x0C 0x80
注意したいのが単純に30分なら16進数に変更して30 -> 0x1Eとすればよいのではなく、レジスタテーブルに記載してある通りに入力する必要があります
30分の場合は00110000bになり、16進数にすると0x30になります
(このRTCでは仕様上直感的に10進数ライクに数字を入れられるように設計されています)
0x80とはAE(アラーム制御ビット)で、これをセットすると値に関わらずにそのAddressはAlarm状態になります
今回はDayとWeekDayのAEを設定しているので、日にちや週に関わらず毎日毎週10:30になるとAlarmが発生することになります
以上で設定は完了です
設定した時間になると/INTピンがLOWになります
Hiveのselect文でカラム名を一緒に表示させる方法
hive.cli.print.header
hive> set hive.cli.print.header=true; hive> use ${db名}; hive> select * from ${table名};
もしくはeオプションで
./hive -e "set hive.cli.print.header=true;select * from ${db名}.${table名}" > result.tsv
raspbian stretchインストール方法
raspbianの最新OSのStrechのインストール方法です
versionは4.14, release dateは2018-04-18です
install
イメージのダウンロード
www.raspberrypi.org
まずは上のサイトからイメージをダウンロードします
raspbianにはGUI付きのRASPBIAN STRETCH WITH DESKTOPと、CUIのみのRASPBIAN STRETCH LITEがありますが、今回はRASPBIAN STRETCH WITH DESKTOPを使います
SDカードへイメージの書き込み
DD for Windowsを利用してダウンロードしてきたイメージをSDカードに焼きます
Target DiskをSDカードに、Target FileをダウンロードしたイメージにしてRestoreを選択すると以下のように書き込みがはじまります
起動
raspbianを書き込んだSDをラズベリーパイに差し込み、HDMIディスプレイとUSBマウス・キーボードも差し込んでmicro USB電源ケーブルをさせばラズベリーパイが起動します
(マウスやキーボードは電源をいれた後でも構いませんが、ディスプレイだけは電源接続時に接続していないと、後で接続しても認識しません)
しばらく待っていると以下のような画面が表示されます
確認
ちゃんとstrechがinstallされているか確認します
$ lsb_release -a No LSB modules are available. Distributor ID: Raspbian Description: Raspbian GNU/Linux 9.4 (stretch) Release: 9.4 Codename: stretch
その他
local IPの固定
$ sudo cp -ip /etc/dhcpcd.conf{,.org} $ sudo vi /etc/dhcpcd.conf # uncomment and change below lines 50 static ip_address=192.168.179.101/24 51 static routers=192.168.179.1 52 static domain_name_servers=192.168.179.1
ユーザー名変更
デフォルトのpi/raspberryから変更する方法
### login as pi user # create temporary user $ sudo useradd -M tmp $ sudo gpasswd -a tmp sudo $ sudo passwd tmp ## すぐ消すので適当につける ### reboot and login as tmp user $ sudo usermod -l nouziru pi $ sudo usermod -d /home/nouziru -m nouziru $ sudo groupmod -n nouziru pi $ sudo passwd nouziru ### reboot and login as nouziru user $ sudo userdel tmp
raspi-config設定
$ sudo raspi-config # 自動ログイン無効 3. Boot Options > Desktop / CLI > B3 Desktop Desktop GUI, requiring user to loginを選択 # TimeZone変更 4. Internatinalization Option > Timezon > Azia > Tokyoを選択 # カメラ・SSH・I2C・Serial有効化 5. Interfacing Options > Camera => Yes > SSH => Yes > I2C => Yes > Serial > Serial Login => No > Serail Interface => Yes # setting後に再起動するか確認されるので再起動
sshのポート変更
$ sudo cp -ip /etc/ssh/sshd_config{,.org} $ sudo vi /etc/ssh/sshd_config ### uncomment and change below line 13 Port 10022
音声テスト
### confirm audio output system $ speaker-test -t sine -f 1000