[GCP] ローカル(mac)からGCEにCyberduckで接続したい

$ ssh-keygen
-> .ssh/id_rsaと.ssh/id_rsa.pubが生成される

Setting -> Metadata -> SSH Key -> addItem -> add Public SSH Key
L id_rsa.pubを貼り付ける

### コマンドラインから接続
$ ssh ${ExternalIP} -i id_rsa
->
mac@instance-1:~$

### Cyberduckから接続
同様に、ExternalIPに対して、SSH Private Keyを、.ssh/id_rsaで設定して接続

きたあああああああああああああああああああああ
ここまできたらGCEの3割ぐらいは前進したかな
大満足🥺 後はデプロイ周りとネットワーキング、ELB

[ubuntu20.04] openCVをinstallしたい

$ sudo apt-get update
$ sudo apt-get install libopencv-dev python3-opencv
$ python3
Python 3.8.10 (default, Sep 28 2021, 16:10:42)
[GCC 9.3.0] on linux
Type “help”, “copyright”, “credits” or “license” for more information.
>>> import cv2
>>> cv2.__version__
‘4.2.0’

$ sudo apt-get install python3-pip
$ pip3 install pillow

import cv2

img = cv2.imread("src/test.jpg")

imgG = img.mean(axis=2)

from PIL import Image
imgP = Image.fromarray(imgG)
imgP = imgP.convert('RGB')
imgP.save('src/test2.jpg')

$ wget https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_alt.xml

### face-detection
$ wget https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_default.xml

import cv2
 
cascade_file = "haarcascade_frontalface_default.xml"
cascade = cv2.CascadeClassifier(cascade_file)
 
img = cv2.imread("src/face.jpg")
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 
face_list = cascade.detectMultiScale(img_gray, minSize=(50,50))
 
if len(face_list) == 0:
    print("false")
    quit()
 
for (x,y,w,h) in face_list:
    print(" 顔の座標=", x, y, w, h)
    red = (0, 0, 255)
    cv2.rectangle(img, (x, y), (x+w, y+h), red, thickness=5)
 
cv2.imwrite("src/face-detect.png", img)

マスク画像

マスクでも行けるのは行けるのか

[Node.js] AWS Kinesis Video Streamのclipのmp4をDownloadする

### kvs起動
gst-launch-1.0 avfvideosrc device-index=0 ! videoconvert ! video/x-raw,format=I420,width=1280,height=720 ! vtenc_h264_hw allow-frame-reordering=FALSE realtime=TRUE max-keyframe-interval=45 bitrate=512 ! h264parse ! video/x-h264,stream-format=avc,alignment=au,profile=baseline ! kvssink stream-name=MyKinesisVideoStream storage-size=512 access-key=”YourAccessKeyId” secret-key=”YourSecretAccessKey” aws-region=”ap-northeast-1″

### node.js側

const fs = require('fs');
const AWS = require('aws-sdk')

AWS.config.update({accessKeyId: "***",
  secretAccessKey: "***",region: "ap-northeast-1"});

async function main(){

	const streamName = 'MyKinesisVideoStream';
	const kinesisvideo = new AWS.KinesisVideo();

	const param = {
		APIName: "GET_CLIP",
		StreamName: streamName
	};
	const e = await kinesisvideo.getDataEndpoint(param).promise();
	const kinesisvideoarchivedmedia = new AWS.KinesisVideoArchivedMedia({endpoint: e.DataEndpoint});

	startTime = new Date(2021, 10, 13, 23, 40, 30); // UTC時間
	endTime = new Date(2021, 10, 13, 23, 41, 38); // UTC時間

	const params = {
        ClipFragmentSelector: { 
          FragmentSelectorType: "PRODUCER_TIMESTAMP",
          TimestampRange: {
            EndTimestamp: endTime,
            StartTimestamp: startTime 
          }
        },
        StreamName: streamName
    };
    const data = await kinesisvideoarchivedmedia.getClip(params).promise();

	const filePath = "test.mp4"
	fs.writeFileSync(filePath, data.Payload);
}

main()

$ node get-mp4.js
うおおおおおおおおおおおおおおおおおおおお

### トラブルシューティング
ずっとこれが出てたんだが、何かなと思ってたら
$ node get-mp4.js
(node:137900) UnhandledPromiseRejectionWarning: ResourceNotFoundException: No fragments found in the stream for the clip request.

jsでtimestampを作るとき、monthは -1なのね。
new Date(2021, 10, 13, 23, 40, 30); // 2021/11/13 23:40:30

new Date(2021, 11, 13, 23, 40, 30) でやってたから、No fragments foundだった。。あほやわ
よっしゃあああああああああああああああああああ

[Go言語] テキストの文字数を取得したい

まずダミーテキストを用意します。

/src/test.txt

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

main.go

import (
	"fmt"
	"unicode/utf8"
	"os"
	"io/ioutil"
)

func main() {
	f, err := os.Open("src/test.txt")
	if err != nil{
		fmt.Println("error")
	}
	defer f.Close()
	b, err := ioutil.ReadAll(f)
	// fmt.Println(string(b))
	count := utf8.RuneCountInString(string(b))
	fmt.Println(count)
}

$ go run test.go
445

utf8.RuneCountInString(b)とすると cannot use b (type []byte) as type string in argument to utf8.RuneCountInString となるので、stringで指定する必要がある

OKOK
続いて、KVSからmp4ダウンロード^^

[Go言語] MP4の時間(duration)を取得する

// コマンドラインでffprobeを実行した場合
$ ffprobe src/video.mp4
ffprobe version 4.2.4-1ubuntu0.1 Copyright (c) 2007-2020 the FFmpeg developers
// 省略
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from ‘src/video.mp4’:
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: mp42mp41isomavc1
creation_time : 2021-07-20T06:13:11.000000Z
Duration: 00:00:14.56, start: 0.000000, bitrate: 1530 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280×720, 1527 kb/s, 25 fps, 25 tbr, 25 tbn, 50 tbc (default)
Metadata:
creation_time : 2021-07-20T06:13:11.000000Z
handler_name : L-SMASH Video Handler
encoder : AVC Coding

### goでffprobe
$ go get github.com/vansante/go-ffprobe

package main

import (
	"log"
	"time"
	"context"

	ffprobe "github.com/vansante/go-ffprobe"
)

func main() {
	ctx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancelFn()

	data, err := ffprobe.ProbeURL(ctx, "src/video.mp4")
	if err != nil {
	    log.Panicf("Error getting data: %v", data)
	}
	log.Print(data.Format.Duration())
	
}

$ go run test.go
2021/11/13 21:37:01 14.56s

mp4が作成された日時とdurationが表示される
OKKKKKKKKKKKKKKKKKKKK

[Go Revel] Paginationを実装したい2

### previous, nextを書いていく
app.go

	var start, end, previous, next int
	
	// p はcurrentのint
	previous = p - 1
	next = p + 1

	return c.Render(content, previous, next)

html

    <nav class="pagination" role="navigation" aria-label="pagination">
      <a href="/paging?page={{.previous}}" class="pagination-previous">Previous</a>
      <a href="/paging?page={{.next}}" class="pagination-next">Next page</a>
    </nav>

ただし、previousとnextは、currentが最初もしくは最後のページの場合、非表示にする
app.go

	current = p
	previous = p - 1
	next = p + 1
    <nav class="pagination" role="navigation" aria-label="pagination">
      {{if ne .current 1}}
      <a href="/paging?page={{.previous}}" class="pagination-previous is-left">Previous</a>
      {{end}}
      <a href="/paging?page={{.next}}" class="pagination-next is-right">Next page</a>
    </nav>

うわああああああああああ、条件分岐が永遠増えていく…

これは次行こう

[Go Revel] Paginationを実装したい1

1. まずgetパラメータでpageの値を取得する
string型での取得

	var page int
	var s string=c.Params.Get("page")
	page, _ = strconv.Atoi(s)
	fmt.Println(page)

http://192.168.34.10:9000/paging?page=1
-> 1

2. ページのスタートと終わりの値を計算
例えば、1ページ5つの値のみを表示するとする場合、l(limit)=5として、startとendの値を求めます。

	var l int = 5
	var start, end int
	start = (p - 1) * l
	end = start + l
	fmt.Println(start)
	fmt.Println(end)

http://192.168.34.10:9000/paging?page=2
2 // 2ページ目
5 // start
10 // end

3. 配列からスライス(要素を取り出す)

	text := [15][2]string{
		{"1","content"},
		{"2","content"},
		{"3","content"},
		{"4","content"},
		{"5","content"},
		{"6","content"},
		{"7","content"},
		{"8","content"},
		{"9","content"},
		{"10","content"},
		{"11","content"},
		{"12","content"},
		{"13","content"},
		{"14","content"},
		{"15","content"},
	}
	fmt.Println(text[start:end])

http://192.168.34.10:9000/paging?page=2
-> [[6 content] [7 content] [8 content] [9 content] [10 content]]

4.全部をつなげて、templeteに出力

func (c App) Paging() revel.Result {

	var p int
	var s string=c.Params.Get("page")
	p, _ = strconv.Atoi(s)
	fmt.Println(p)

	var l int = 5
	var start, end int
	start = (p - 1) * l
	end = start + l
	fmt.Println(start)
	fmt.Println(end)

	text := [15][2]string{
		{"1","content"},
		{"2","content"},
		{"3","content"},
		{"4","content"},
		{"5","content"},
		{"6","content"},
		{"7","content"},
		{"8","content"},
		{"9","content"},
		{"10","content"},
		{"11","content"},
		{"12","content"},
		{"13","content"},
		{"14","content"},
		{"15","content"},

	}
	fmt.Println(text[start:end])
	content := text[start:end]
	return c.Render(content)
}

html側

    <h1>paging</h1>
    <ul>
    {{range .content}}
    <li>{{ index . 0 }} {{.}}</li>
    {{end}}
    </ul>

問題は、view側のページネーションのbuttonをどう実装するか…
0から作るの大変だな..

[Go言語]Revelで連想配列の値をrangeで表示する

app.go

func (c App) Paging() revel.Result {

	text := [3][2]string{
		{"20211113","2021/11/13"},
		{"20211112","2021/11/12"},
		{"20211111","2021/11/11"},
	}
	fmt.Println(text)
	fmt.Println(text[0][1])
	return c.Render(text)
}

views
L indexを使う

    <ul>
    {{range .text}}
    <li>{{ index . 0 }} {{.}}</li>
    {{end}}
    </ul>

ウヒョーーーーーー

.[0] で表示できないので、かなり時間がかかりました。

[Go言語] 配列と連想配列

### 配列

	var arr[2] string
	arr[0] = "2021/11/13"
	arr[1] = "2021/11/12"
	fmt.Println(arr)

[2021/11/13 2021/11/12]

### 連想配列(map)
組み込み関数make()を使用して宣言する

	mapTest := make(map[string]string, 2)

	mapTest["train"] = "JR"
	mapTest["bus"] = "kanachu"
	fmt.Println(mapTest)

map[bus:kanachu train:JR]

### 多次元配列

	text := [3][2]string{
		{"20211113","2021/11/13"},
		{"20211112","2021/11/12"},
		{"20211111","2021/11/11"},
	}
	fmt.Println(text)
	fmt.Println(text[0][1])

[[20211113 2021/11/13] [20211112 2021/11/12] [20211111 2021/11/11]]
2021/11/13

うん、なんかOKっぽい

[BlumaCSS] ul liで黒点を表示

			<ul>
				<li><a href="">2021/12/10</a></li>
				<li><a href="">2021/12/10</a></li>
				<li><a href="">2021/12/10</a></li>
				<li><a href="">2021/12/10</a></li>
				<li><a href="">2021/12/10</a></li>
				<li><a href="">2021/12/10</a></li>
				<li><a href="">2021/12/10</a></li>
				<li><a href="">2021/12/10</a></li>
			</ul>

これだけだと、黒点が表示されないので、class=”content”で囲む

			<div class="content">
			<ul>
				<li><a href="">2021/12/10</a></li>
				<li><a href="">2021/12/10</a></li>
				<li><a href="">2021/12/10</a></li>
				<li><a href="">2021/12/10</a></li>
				<li><a href="">2021/12/10</a></li>
				<li><a href="">2021/12/10</a></li>
				<li><a href="">2021/12/10</a></li>
				<li><a href="">2021/12/10</a></li>
			</ul>
			</div>

なるほどー