Springroll Book

ホームページに戻る

このページについて

主に趣味で得た知識や技術、テクニックについて適当に記録する備忘録です。
また、このページはRustで書かれたmdbookというOSSによって生成されています。

内容

Competitive Programming

競技プログラミングについて色々まとめる

目標

  • AtCoder 青(Rating 1600↑)
  • Codeforces 紫(Rating 2000↑)

やること

Web Development

Web開発について色々まとめる

基礎技術

  • Web
  • Django
  • JavaScript
  • JQuery
  • HTML
  • CSS
  • Vue.js
  • 応用情報技術者試験レベル
  • SQL
  • TCP/IP
  • WebAPI

ClipHype

ローカルでの開発環境構築手順

本番環境と近づけるためにDockerを使う。

  1. Dockerイメージのビルド

Dockerfileの場所を指定して、そのDockerfileをもとにイメージをビルドする

$ docker build -t cliphype:1.0 .
  1. Dockerコンテナ起動
docker run -it -p 8000:8000 -v <directory_path>:/root/cliphype --name cliphype cliphype:1.0

ここで、コンテナ起動時に自動的にdocker_start.shが実行され、諸々設定される

  1. 開発サーバの起動
$ python3 manage.py runserver 0.0.0.0:8000

Concat-clips インスタンスの構築

必要なパッケージのインストール

$ sudo apt update
$ sudo apt install -y ffmpeg curl build-essential python3 python3-dev python python-dev libx11-dev libxext-dev libxext6 xvfb libxi-dev libglew2.1 libglew-dev pkg-config
$ sudo apt install -y mysql-server mysql-client
$ sudo apt install -y nodejs npm
$ curl https://sh.rustup.rs -sSf | sh

ffmpeg-concatのインストール

$ sudo chmod 777 /usr/local/lib
$ sudo chmod 777 /usr/local/bin
$ npm install -g ffmpeg-concat

concat-clips.rsのビルド

$ git clone https://github.com/halmk/ClipHype.git
$ cd ClipHype/aws/ec2/concat-clips
$ cargo build --release
$ cp target/release/concat-clips ~/

インスタンス起動時に自動実行させるための設定

  • concat-clips.service
[Unit]
Description=service to lanuch concat-clips

[Service]
EnvironmentFile=/etc/sysconfig/concat-clips_env
WorkingDirectory=/home/ubuntu/
ExecStart=/bin/sh /home/ubuntu/concat-process.sh
User=ubuntu

[Install]
WantedBy=default.target
  • concat-clips_env
PATH=/home/ubuntu/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
DATABASE_URL=mysql://root:*****@*****/cliphype
AWS_ACCESS_KEY_ID=*****
AWS_SECRET_ACCESS_KEY=*****

サービスの設定

$ sudo vi /etc/systemd/system/concat-clips.service
$ sudo mkdir /etc/sysconfig
$ sudo vi /etc/sysconfig/concat-clips_env
$ sudo systemctl enable concat-clips

デプロイ手順

mainブランチにdevelopブランチをマージ

  • GithubのPullRequestからマージする
  • maindevelop

本番サーバでClipHypeをPull

$ sudo systemctl stop gunicorn
$ git pull
$ cd cliphype
$ python3 manage.py makemigrations
$ python3 manage.py migrate

AWSサービスの置き換え

Lambda

  • 元の関数のトリガーを削除/無効化
  • 新しい関数のトリガーを作成
  • 環境変数を本番用に変更

SQS

  • Lambda関数トリガーの設定

RDS

本番サーバの起動

$ pkill celery
$ nohup celery -A cliphype worker --loglevel=INFO --concurrency=1 >> ~/celery.log &
$ sudo systemctl restart nginx
$ sudo systemctl start gunicorn

クリップのタイトルを描画する

ffmpeg-python

  • pythonでffmpegのコマンドが操作できる
  • 変数が扱いやすい
  • パイプラインで記述するので、足し引きが楽

AutoClipBotによって作成されたクリップを表示する

  • 現状、ユーザによって作成されるクリップは限りがあり、面白いシーンやすごいシーンが起こっても誰もクリップを作成しないことは多々ある。コメントからそれらのシーンを読み取ることで、もれなくクリップを作成できる。

  • 一定期間内(たぶん24時間以内)なら長さやタイトルの編集も可能。

  • 自動クリップの仕組み自体は他のレポジトリとして、ClipHypeからは切り離す。 -> autoclip-bot-ttv

  • 自動で作成されたクリップを管理するデータベースを作る -> cliphype.autoclip

  • バックエンドでは、APIを作成し情報を提供する形にする

自動でハイライト動画を持続的に生成する

  • 最初に試すコストがユーザ視点では大きいので、ある程度自動で生成する
  • ハイライト動画エリアにタブで追加する(?)
  • 動画編集機能の追加も必要
  • 生成基準
    • 1つの配信ごとに生成
    • 複数の配信で1つ生成(クリップの長さの合計で決める)
    • AutoClipを含めるかどうか
    • クリップの再生数を指定して追加

Twitch API

ClipHypeで使用しているAPIの詳細や認可フロー、ユーザ認証方法についてまとめる

レート制限

  • リクエストのレート制限はユーザごとに主にリクエスト数で決められる
  • 毎分800ずつポイントが再分配される
  • 一部のAPIは消費ポイントが異なる
  • ポイントがなくなった場合は429(Too Many Requests)レスポンスが返ってくる

OAuth client credentials flow

  • サーバ側でユーザ情報なしにAPIを叩く方法
  • あるユーザの許可が必要になるようなAPIは使用できない
  • server-to-serverでのみ使用すべきでユーザ側では使ってはいけない
  • 使用できるトークンはapp access token

app access tokenを取得するリクエスト

POST https://id.twitch.tv/oauth2/token
    ?client_id=<your client ID>
    &client_secret=<your client secret>
    &grant_type=client_credentials
    &scope=<space-separated list of scopes>

レスポンスでbearer tokenがもらえるので、有効である間そのトークンを使用してAPIを叩く

ClipHype DevBlog

2021/08

動画内のクリップにタイトルを描画する機能を追加

クリップのタイトルを挿れることで、その動画の内容と期待するもの(笑いや驚きなど)の理解を助け、短いクリップでも状況の把握が簡単になるので結構嬉しい機能。

個人的には、クリップの最初の数秒だけ表示をするよりもクリップ全体で表示を続ける方が何も考えずにまったりと見れると思ってて、タイトルの表示がなくなって数秒後に見ている動画の注目すべきポイントが何か分からなくなるような状態を避けられる。

表示するテキストのエフェクトとかフォントを色々選択できればもっと嬉しいけど、ffmpegを使ってる関係でエフェクト(影、合成など)は限界がある。フォントはフォントファイルを用意すれば何でも使えるので、今後実装予定。今は、日本語が使えるようにNoto Sansを使っていて、Googleフォントからutfファイルをダウンロードして必要なサイズのものだけLamdbaで使えるようにしている。

開発用環境のコストが気になる

基本的に追加で料金がかかるのはRDSの開発用DBで、作業するときだけインスタンス立ち上げたいけど時間がかかるのでついつい放置しがち。このままだと月1万になっちゃう(ア

その他の稼働させるサービスは追加のコストはかなり小さいけど、スポットインスタンスでc5.xlargeとか使ってると少し気になってくる。

AMI生成がめんどう

concat-clipsを実行するインスタンスのAMIを生成するときの手順が多い

  • ec2インスタンス起動
  • インスタンス内でconcat-clipsをビルド
  • concat-clipsサービスの修正
  • AMIを生成(割と時間かかる)
  • 起動したインスタンスを終了
  • spot-request関数の環境変数を新しいAMIに変更

ここらへんも自動化できるのかな?シェルスクリプト使えるようになればここらへんもターミナルだけでできて楽になるかも

2021/09

ClipHype開発に区切りをつけてCI/CDとか、リファクタリングとかやりたい。

  • モーダル上でタイトル変更
  • リクエストしたハイライト動画の復元
  • 動画ダウンロードをLambdaに移す
  • クリップの情報にHype値を追加する

2021/12

TODO

Vue CLIを使った大規模向けの開発方法を身につける

  • Vue.jsのリアクティブシステム(data,computed,filters,methods...)の復習
  • コンポーネントの基礎(~12/29)
  • Vue Router(~12/31)
  • 単一ファイルコンポーネント
  • Vuex

SPIに対応できるDjangoの振る舞いを考える

リファクタリング

  • Djangoのモジュール構成や関数の配置を見直す
  • Vue.jsの実装をコンポーネントに分割する(段階的に適用する)

2022/01

リファクタリング

Vue.jsの実装をコンポーネントに分割する(段階的に適用する)

  • Atomic Designに沿って、コンポーネントの構成を考える
  • Djangoとどうやって連携させるかがよく分かってない
  • VueCLIはソースファイルをコンパイルすることでhtmlファイルとjsファイルを生成するから、そのhtmlファイルがDjangoから認識できればいいだけだからtemplateファイル群置き場だけ指定できるようにするだけであとはあんまり気にしなくても連携できそう
  • どのバージョン使うか検討する必要があるけど、Vue.js v3 が2020年9月にリリースされたからせっかくだからVue.js v3を使ってみる
  • 色々仕様変更はあるけどその都度移行ガイドや公式ドキュメント見ながらすすめる
  • まずは、Githubでブランチを切ってfrontendって名前のディレクトリの中でVueCLI使ってフロントエンド開発を進めていく
  • その前に今のindex.html(ホームページ)をなくしてアプリページをそのままホームページとする

コンポーネント設計

  • viewsディレクトリはrouterに指定するコンポーネントとして使うので、結局Atomic Designでいうところのtemplatesに該当すると思う

  • molecules以下をcomponentsディレクトリで管理して、moleculesを組み合わせたものをviews内のコンポーネントで定義する

  • まずは、トップダウンでひな形を作っていく

  • ログイン情報とか、リクエスト処理とかをどこで管理するか

  • ログイン情報はどこからでもアクセスできるようにしたいからvuexで管理するのが良さそう

  • APIリクエスト関連のいろんなとこで使えそうな関数はmixinにする?

  • ChStreamerFormで入力された配信者のIDを取得して、それらの情報を次のChArchiveViewに渡したい

  • vue-routerの動的ルートマッチングを使うといい感じにできそう

  • /streamer/euriece/archive/12345/clips

  • こうするか、これらの情報はvuexで管理するか

  • ハイライト動画に使うクリップの情報はvuexで管理しないと難しそう

    • 兄弟関係にあるコンポーネント間のデータ送受信はvuexが楽
    • 一人に対してのハイライト動画作成なら動的ルートマッチングの方法はブックマークとかに使えて良さそうではある
    • でもちょっと複雑?
    • /euriece/archive/12345/highlights
    • そもそもarchive選択はクリップ取得期間の1つの選択肢で普通に日時範囲指定でクリップ取得するケースもあるからclipsとクリップ取得エリアは同じページのほうが利便性良さそう
    • でもやっぱり、シンプルなアプリケーションにしたいからアーカイブの選択からクリップを絞り込むのを基本にするのが良さそう
    • その上でアーカイブの複数選択とかを追加していく形で。
    • cliphype.com/euriece/archiveでアーカイブ選択
  • クリップ表示コンポーネントは汎用的にしたい

  • 全体の流れ

    • propsでクリップ取得のリクエストに使うパラメータを指定可能にする
    • cliphype.com/eurieceにアクセスしたら/archivesに飛ばす
    • /archivesで取得するクリップの情報を選択し、/clipsに移動
    • ここでは、vuexのパラメータに値をセットするだけ
    • /clipsに行ったら、取得するクリップをvuexから取得する
    • /clipsでは、クリップを選択するたびにvuexselected_clipsに情報を追加する
    • selected_clipsもクリップ表示コンポーネントの下に表示する
    • それらが終わったら、/highlightsに移動する
    • 最終的に、諸々設定したらハイライト動画生成リクエストを送り、/videos/:idに移動する
  • Vuexで管理するデータ

    • streamerName: 指定した配信者の名前
    • streamerId: 指定した配信者のID
    • archiveStartedAt: アーカイブの開始時刻
    • archiveEndedAt: アーカイブの終了時刻
    • selectedClips: 選択したクリップのメタデータ配列
  • Vuexで定義するメソッド

    • streamerNameからstreamerIdを取得
  • mixinを用いたコンポーネントの共通部分の抽出

    • TwitchAPI関連をまとめたもの
    • AwsAPI関連をまとめたもの
    • など

CI/CD

  • バックエンドのテストを作る
  • フロントエンドのテストを作る
  • CircleCIでマージする前にテストを実行する
  • mainブランチにマージするときにはデプロイまでやる

AWS サービス

使用経験のあるサービス

EC2

OSを載せた仮想サーバ

  • Djangoで作成したWebアプリを公開するためのWebサーバ(Python)
  • 競プロの問題を復習するためのTwitter通知Botを稼働(Rust)

Lambda

サーバレスコンピューティングサービス、イベント発生時にコードを実行

  • S3に上がった動画ファイルの解像度をスケールする(Node.js, Python)
  • 動画にテキストを描画する(Python)
  • 必要な動画ファイルが揃ったらSQSにメッセージを送信する(Node.js, Python)
  • 動画作成処理のためのスポットインスタンスを立ち上げる(Python)

S3

オブジェクトストレージ

  • 動画の保存
  • ログファイルの保存

SQS

完全マネージド型のメッセージキューイングサービス

  • 動画処理タスクを管理するキュー

IAM

AWSのサービスやリソースへのアクセスを安全に管理

IAMユーザは、AWSを利用するアカウントにAWSのサービスに対しての操作権限を与える機能
IAMポリシーは、AWSサービスやリソースに対する操作権限の設定をする機能
IAMロールは、AWSのサービスに対して操作権限を与える機能

CI/CD

CircleCI + AWS CodeDeployによるテスト・デプロイの自動化

参考

  • https://qiita.com/hkanazawa/items/4064bf447bd3866b1c3d
  • https://dev.classmethod.jp/articles/circleci-codedeploy/

内容

CodeDeploy

  • アプリーケションを作成する
  • デプロイグループの設定
  • デプロイロールの設定
  • ...

CodeDeployの設定ファイル - appspec.yml

  • デプロイ対象とデプロイ先を記述する
  • S3からソースコードをpullした後に実行させることをAfterInstallに記述する
  • https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/reference-appspec-file.html#appspec-reference-server
  • https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/deployments-create-console.html
  • https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/application-revisions-appspec-file.html#add-appspec-file-server

Circle.ciの設定ファイル - circle.yml -> .circleci/config.yml

  • CI環境でテストする内容をtestに記述する
  • CodeDeployによるデプロイ内容をdeploymentに記述する
  • https://circleci.com/docs/ja/2.0/language-python/?section=examples-and-guides
  • https://circleci.com/developer/orbs/orb/circleci/aws-code-deploy

aws-cliのインストール(macos)

https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-mac.html

$ curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
$ sudo installer -pkg AWSCLIV2.pkg -target /
$ aws --version
aws-cli/2.2.25 Python/3.8.8 Darwin/19.6.0 exe/x86_64 prompt/off

デプロイ

  • RDS(MySQL5.6)に接続するときにエラーが出た
$ mysql -u root -p -h <エンドポイント>

解決方法
https://www.ytyng.com/blog/ubuntu-mysql-ssl-failed/

  • gunicorn,celeryが実行できない

venvなしだとceleryへのパスが通ってない($HOME/.local/bin)ので、そのパスを通す
pip show -f <package> | grep './bin'で実行ファイルへのパスが分かる

開発環境を構築

個々のインスタンスに対して本番用と開発用を準備する

Webサーバ

  • 本番用

インスタンス: EC2 - Ubuntu20.04
サーバ: Nginx + gunicorn

  • 開発用

インスタンス: Docker - Ubuntu20.04
サーバ: Djangoの開発サーバ

S3

  • 本番用

バケット: cliphype

  • 開発用

バケット: cliphype-dev

RDS - MySQL

  • 本番用

  • 開発用

Lambda

  • 本番用

トリガー: s3のバケットにcliphypeを指定する

  • 開発用

トリガー: s3のバケットにcliphype-devを指定する

Spot Instance

  • 本番用

  • 開発用

Other

その他のプログラミング言語のtipsや資格試験等に関することをまとめる

プログラミング言語

ツール

資格試験

ブログ

2021/08

TyporaでVimキーバインド使いたい

ファイルツリー使えるようになってて驚いた。キーバインドでVimが使えれば最高なんだけどなあ。論文書くときに使ってるOverleafはキーバインドでVimが使えて最高。ただ基本的にブログは上から下に書くし修正も少ないからあんまり必要にない気がする。

Windows10の仮想デスクトップの切り替え

PCはMacbook pro 2015(古い)とデスクトップPCの2台持ってるけど、スペックの関係でデスクトップPC使うことが多い。Macbookは仮想デスクトップが簡単に切り替えられて(ctrl+num)快適だけど、windowsはctrl+start+right or leftで特に矢印キーがホームポジションからかなり離れてて辛い。

AutoHotKeyってのを使うと入力したキーを他のキーに変換してくれるので、ショートカットキーのショートカットキーみたいになって自分の好きなキーに設定できるっぽい。

設定でctrl+start+j or k で移動できるようにした。vim好きの僕にはjkが使いやすいので。

;Switch to right virtual desktop
^#K::
Send, {LControl down}#{Right}
return

;Switch to left virtual desktop
^#J::
Send, {LControl down}#{Left}
return

2022/01

プログラミング関係の技術書の読み方

サンプルコードを多く載せている書籍だと自分で動かしながら読むと学習効率が良いが、どこまでコードが理解できるかが重要になる。自分で載っているコードを全て打つのは、打っている途中で写経してる気分になって頭が動かなくなりやすい。逆に全てコピペで済ますのはコードの細かい部分の理解が進まなくなる。そこで、コードをコピペした上で各コードの説明をコメント文として書き込むことで主体的に取り組むことができる気がする。

Basic Command

IssuesとPullRequestによる開発フロー

大まかな手順

  1. Issuesで問題を設定する
  2. そのIssueに対応したBranchをローカルで作成する
  3. そのBranchで開発を進める
  4. 作業が終わったらPushする
  5. PullRequestを送る

詳細

Issuesで問題を設定する

そのIssueに対応したBranchをローカルで作成する

ローカルで作業内容とissueの番号からなるBranchを作成する

$ git checkout -b <作業内容>#<issueの番号>

リモートにそのBranchをPushしておくことで、作業開始が周りに分かる

$ git push origin <作業内容>#<issueの番号>

そのBranchで開発を進める

なるべくこまかく変更をcommitすることでコードレビューがしやすくなる コミットメッセージはテンプレートを決めておくと良い

  • 作業内容の対応するissue番号
  • 作業の方向性を表すAdd Update Move Remove Change Rename等の動詞
  • 作業内容の説明(外部に公開する場合は英語)
#<issue番号> <Add/Updateなど> <作業内容の説明>

作業が終わったらPushする

ローカルの変更をPushする Branchの派生元のBranchを最新にしてからPushする

作業が完了してからPushしてもいいけど作業途中でPushすることで途中経過を見せることができる

PullRequestを送る

GithubからPullRequestを送る

色々取り消したいとき

ローカルリポジトリ

間違ったCommitをしてしまったとき

  • git reset --soft <コミットID>

該当のコミットに移動し、ステージング コミットメッセージを直したい、コミットし直したいときに使用する
ステージングしたファイルはステージングされたまま

  • git reset --mixed <コミットID>

該当のコミットに移動し、 コミットをまとめてやりすぎたときとかに使用する
コミットの取り消し+ステージングされたファイルも取り消される(addする前になる)

  • git reset --hard <コミットID>

間違えて違うブランチで作業してたときとかに使用する
変更したファイルそのものが取り消される

リモートリポジトリ

間違ったコミットをPushしてしまったとき

  • git revert <コミットID>

該当のコミットの変更を取り消ししたコミットができる git resetを使ってしまうと色々厄介なことになる
revertすると、コミットの履歴は残りrevertしたというコミットが作られる(仕方ない)

Rust

Rustに対しての印象

Rustは2015年に1.0版がリリースされた新しめのプログラミング言語である。Rustと検索するとサバイバル系FPSゲームの方も出てくるが、ここで扱うのはプログラミング言語の方。

Rustの最も大きな特徴はガーベジコレクションを持たず、独自のメモリ安全性を保証するシステム(所有権、借用、ボローチェッカー)を持っていること。これによって、GCによるランタイムの肥大化を防ぎつつ処理速度も維持している。コンパイル時にメモリ安全に関するエラーは全て出てくれるので、コンパイルを突破さえすれば安全なコードである保証ができる点が嬉しい。あとはアルゴリズム面で上手く動作しているかに集中できる。

Rust自体の目指しているところはC/C++から置き換わることであり、それらが多く用いられるシステムプログラミングや組み込みシステムの分野に使用されることに焦点が当てられている。これによって、Rustではランタイムが軽量になるように設計される。

メモリ安全を保証するシステムによって、実装が複雑化すると思われるが、実際は制約に従うことでよりシンプルな設計を意識することができる。(最近は、書き慣れすぎてコンパイルエラーさえ出なくなってきた)

より高級なレイヤー(Web開発、機械学習、並列処理)においては、新しい言語ということもあり環境が整っていない印象。Web開発では、バックエンドフレームワークとしてactix-web、rocket、tideなどがある。最近では、tokioチームがaxumを発表し、クセが少ないということで注目している。Rustの使い所としては、処理時間と消費メモリのコストが重要かつ部分的な場面。例えば、AWS Lambdaで使用する例が増えている。 個人的には、新しいものに無闇に手を出さずに他言語の重厚なフレームワークを使いこなすことに注力したい。ただ、素朴なフレームワークを介してWeb開発の理解も深めたいといったところで、簡単なWebAPIの実装とかに使ってみたい。

TODO

  • TRPL読み直す
  • 非同期処理の勉強(tokioクレート)
  • ...

yabai

lazygit

ubersicht

TOEIC