Springroll Book
このページについて
主に趣味で得た知識や技術、テクニックについて適当に記録する備忘録です。
また、このページはRustで書かれたmdbookというOSSによって生成されています。
内容
Competitive Programming
競技プログラミングについて色々まとめる
目標
- AtCoder 青(Rating 1600↑)
- Codeforces 紫(Rating 2000↑)
やること
- ABC埋め (???/???)
- Codeforces1600埋め (???/???)
- AtCoder 競プロ典型90問
Web Development
Web開発について色々まとめる
基礎技術
- Web
- Django
- JavaScript
- JQuery
- HTML
- CSS
- Vue.js
- 応用情報技術者試験レベル
- SQL
- TCP/IP
- WebAPI
ClipHype
ローカルでの開発環境構築手順
本番環境と近づけるためにDockerを使う。
- Dockerイメージのビルド
Dockerfileの場所を指定して、そのDockerfileをもとにイメージをビルドする
$ docker build -t cliphype:1.0 .
- Dockerコンテナ起動
docker run -it -p 8000:8000 -v <directory_path>:/root/cliphype --name cliphype cliphype:1.0
ここで、コンテナ起動時に自動的にdocker_start.sh
が実行され、諸々設定される
- 開発サーバの起動
$ 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
からマージする main
←develop
本番サーバで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
では、クリップを選択するたびにvuex
のselected_clips
に情報を追加するselected_clips
もクリップ表示コンポーネントの下に表示する- それらが終わったら、
/highlights
に移動する - 最終的に、諸々設定したらハイライト動画生成リクエストを送り、
/videos/:id
に移動する
-
Vuex
で管理するデータstreamerName
: 指定した配信者の名前streamerId
: 指定した配信者のIDarchiveStartedAt
: アーカイブの開始時刻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による開発フロー
大まかな手順
- Issuesで問題を設定する
- そのIssueに対応したBranchをローカルで作成する
- そのBranchで開発を進める
- 作業が終わったらPushする
- 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クレート)
- ...