Ubuntu上のOBSでVirtualCamを使う(デスクトップ映像を仮想カメラに送る)

Zoomなどでデスクトップ画面をカメラ映像として共有するのに使える。 参考: https://github.com/CatxFish/obs-virtual-cam/issues/17 Environment Ubuntu 18.04 FFmpeg 3.4.6-0ubuntu0.18.04.1 v4l2loopback #ed2b709 OBS Studio 25.0.8 #14b0565 obs-v4l2sink #1ec3c8a はOBS Studioがクラッシュして使えなかった。 How to https://github.com/obsproject/obs-studio https://github.com/umlaeute/v4l2loopback # sudo apt install v4l2loopback-dkms # これはバージョンの問題で使えないかも git clone https://github.com/umlaeute/v4l2loopback.git cd v4l2loopback make sudo make install sudo depmod -a # 仮想カメラを作成(モジュールをロード) sudo modprobe v4l2loopback devices=1 video_nr=10 card_label="OBS Cam" # 映像転送サーバを立てる(OBS→仮想カメラ) ffmpeg -an -listen 1 -i rtmp://127.0.0.1:1935/live -f v4l2 /dev/video10 # 仮想カメラを削除 sudo modprobe -r v4l2loopback カメラデバイスの一覧を確認するにはsudo apt install v4l-utilsして以下のコマンド。 ...

2020年5月15日 · aoirint

Vue 入門

Node.js(npm+Browserifyなど)でパッケージ管理したり、サーバサイドで事前処理(.vueファイル、vue-cli)して配信ファイルを生成したりしてややこしいけれど、基本的にVue(Vue.js)はブラウザ上で動作するBootstrap++みたいなクライアントサイドフレームワークという理解。 参考 はじめに — Vue.js この「はじめに」をベースにサンプルを並べていく。 何もしないHTML <!DOCTYPE html> <meta charset="utf-8"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- <script src="https://cdn.jsdelivr.net/npm/vue"></script> --> <h2>Hello Vue!</h2> <p> This is not Vue! CDNから開発用のVue.jsを持ってくるだけ。これをベースにいじっていく(SRIは略)。 テストするときはpython3 -m http.server --bind 127.0.0.1とか、php -S 127.0.0.1:8000とか、静的コンテンツを開ければなんでもよし。 テンプレート的用法 適当に使ってみる <!DOCTYPE html> <meta charset="utf-8"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- <script src="https://cdn.jsdelivr.net/npm/vue"></script> --> <h2>Hello Vue!</h2> <p id="body"> {{ body_content }} <script> (function() { var app = new Vue({ el: '#body', data: { body_content: 'This is BODY!', }, }); })(); </script> Django/Jinjaのように{{ variable }}の形式で埋め込み位置を指定。Vueオブジェクトを作って初期値を与える。 ...

2020年5月10日 · aoirint

Zoom API (OAuth)を試したメモ

お試しのためのOAuthアクセストークン(一時)を得るサンプルをクローン。 git clone https://github.com/zoom/zoom-oauth-sample-app.git cd zoom-oauth-sample-app npm install https://github.com/zoom/zoom-oauth-sample-app ngrok(remote.itみたいなやつ)をダウンロード(実行ファイル)。ngrok.ioのサブドメインにポートを転送する。 https://ngrok.com/ ./ngrok http 4000 OAuth AppをZoom上に作成。 https://marketplace.zoom.us/develop/create 設定を書く.envファイルを作成。 touch .env clientID=Zoom OAuth AppのClient ID clientSecret=Zoom OAuth AppのClient Secret redirectURL=ngrokのURL 起動。 npm run start API Document: https://marketplace.zoom.us/docs/api-reference/introduction 上のURLでテスト呼び出しができるので、アクセストークンをとりあえず使いまわして検証。 管理者でない場合は得られる情報が結構限られる(進行中のミーティングの参加者リストは管理者でないととれなさそう)。管理者の場合はOAuthではなくJWTを使ったほうが良さそう。今回の目的は達成できなさそうだったのでこれで終了(トークンとらなくても入出力サンプルはある)。 JWT参考:インタラクション2020のリモート開催で使われたシステム https://github.com/hasevr/i2020zoom

2020年5月9日 · aoirint

Install TexLive on Ubuntu 18.04

普段TeXを書くときはAtom + latex + pdf-viewなのですが、うまくpdf-viewが動作してくれなくなった(空のタブが開いたりする)ので検証ついでに(関係ないとは思いつつ)TeXのバージョンを上げてみたくなった。aptからインストーラでのインストールに変更。 TeXはインストールに時間がかかっていけない..。dockerイメージ化したいが、毎回dockerコンテナ付けるとめっちゃオーバーヘッドできそう。up -dしてexecで動かせば速いのかな? 一般ユーザでdockerコマンド実行できるようにもしないといけないか。 sudo apt purge texlive-* 東京周辺ならJAIST、山形大学などのミラーサーバに繋がるかと思います。 wget http://mirror.ctan.org/systems/texlive/tlnet/install-tl-unx.tar.gz SHA-512 (2020-04-11) https://ctan.org/tex-archive/systems/texlive/tlnet sha512sum install-tl-unx.tar.gz 6fbca1895f0f08645e2ff97b34b9b07d659af7d25de1edc6e123fc472f3dd05db42edc9e5450fd09fae548f5259f93d7f98f63d29dfe6ff7e069685ba202661b install-tl-unx.tar.gz tar xf install-tl-unx.tar.gz cd install-tl-* sudo ./install-tl Actions: <I> start installation to hard disk <P> save installation profile to 'texlive.profile' and exit <H> help <Q> quit Enter command: I Installing to: /usr/local/texlive/2020 Installing [0001/3978, time/total: ??:??/??:??]: texlive.infra [420k] Installing [0002/3978, time/total: 00:01/02:06:37]: texlive.infra.x86_64-linux [143k] おうちの回線では1h-2hくらい。おやすみなさい.. ...

2020年4月12日 · aoirint

nginx basic auth, reverse proxy, static files

Basic auth Nginx で Basic 認証 - Qiita auth_basic "Authentication Required"; auth_basic_user_file DIRECTORY/.htpasswd; Reverse proxy Nginxによるリバースプロキシの設定方法 - Qiita proxy_set_header HOST $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location / { proxy_pass http://localhost:8000; } Static files Nginxの静的ファイル配信でハマった - shoya.io location /static/ { root PARENT_OF_STATIC_DIRECTORY; }

2020年3月27日 · aoirint

Let's Encrypt certbot Error Ubuntu(ImportError: cannot import name 'constants')

間違えてOSのパッケージリポジトリからcertbotを入れてしまった. コマンド sudo certbot --nginx エラー1(初期状態) ImportError: cannot import name 'constants' エラー2(pip3 uninstall certbotの後) AttributeError: module 'acme.challenges' has no attribute 'TLSSNI01Response' Certbot - Ubuntubionic Nginx sudo pip3 uninstall certbot acme sudo apt purge certbot python-certbot-nginx # HERE: register official ppa repository (see official guide) sudo apt install certbot python-certbot-nginx

2020年3月27日 · aoirint

PyTorch pydub.AudioSegmentをtorch.Tensorに変換する

import numpy as np import torch import torchaudio import torchaudio.transforms as T ''' in: pydub.AudioSegment out: torch.Tensor (float32) ''' def to_tensor(audio): sample_width = audio.sample_width sample_bits = 8 * sample_width sample_max_int = 2 ** sample_bits sample_channels = audio.channels samples = np.asarray(audio.get_array_of_samples()) samples = samples.reshape((-1, 2)).transpose((1, 0)) # LRLR -> Channel, Samples samples = samples.astype('f') / sample_max_int samples = torch.from_numpy(samples).type(torch.float32) return samples

2020年3月26日 · aoirint

OpenGL 2.1/4.1(GLFW)でOpenCVの画像を表示する(Python, Mac)

pip3 install PyOpenGL glfw モジュールバージョン PyOpenGL==3.1.5 glfw==1.11.0 システムのOpenGLバージョン Vendor : b'Intel Inc.' GPU : b'Intel Iris OpenGL Engine' OpenGL version : b'4.1 INTEL-14.4.23' OpenGL 2.1 mcfletch/pyopengl: Repository for the PyOpenGL Project Python3で始めるOpenGL4 - CodeLabo Python GLFWでOpenGLバージョン指定とウィンドウ表示 - CodeLabo PythonでOpenCVの画像をOpenGLで表示する - Qiita Vendor : b'Intel Inc.' GPU : b'Intel Iris OpenGL Engine' OpenGL version : b'2.1 INTEL-14.4.23' glDrawPixels import cv2 from OpenGL.GL import * import glfw if __name__ == '__main__': img = cv2.imread('lena.png', 1) img_gl = cv2.cvtColor(cv2.flip(img, 0), cv2.COLOR_BGR2RGB) glfw.init() # These parameters need to be changed according to your environment. # Mac: https://support.apple.com/ja-jp/HT202823 # glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4) # glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1) # glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True) # glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE) width = img.shape[1] height = img.shape[0] window = glfw.create_window(width, height, 'Lena', None, None) glfw.make_context_current(window) print('Vendor :', glGetString(GL_VENDOR)) print('GPU :', glGetString(GL_RENDERER)) print('OpenGL version :', glGetString(GL_VERSION)) while not glfw.window_should_close(window): glClearColor(0, 0, 0, 1) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, img_gl) glfw.swap_buffers(window) glfw.poll_events() glfw.destroy_window(window) glfw.terminate() Texture import cv2 from OpenGL.GL import * import glfw if __name__ == '__main__': img = cv2.imread('lena.png', 1) img_gl = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) glfw.init() # These parameters need to be changed according to your environment. # Mac: https://support.apple.com/ja-jp/HT202823 # glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4) # glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1) # glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True) # glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE) window = glfw.create_window(256, 256, 'Lena', None, None) glfw.make_context_current(window) print('Vendor :', glGetString(GL_VENDOR)) print('GPU :', glGetString(GL_RENDERER)) print('OpenGL version :', glGetString(GL_VERSION)) height, width = img.shape[:2] glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_gl) while not glfw.window_should_close(window): glClearColor(0, 0, 0, 1) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glEnable(GL_TEXTURE_2D) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glBegin(GL_QUADS) glTexCoord2d(0.0, 1.0) glVertex3d(-1.0, -1.0, 0.0) glTexCoord2d(1.0, 1.0) glVertex3d(1.0, -1.0, 0.0) glTexCoord2d(1.0, 0.0) glVertex3d(1.0, 1.0, 0.0) glTexCoord2d(0.0, 0.0) glVertex3d(-1.0, 1.0, 0.0) glEnd() glfw.swap_buffers(window) glfw.poll_events() glfw.destroy_window(window) glfw.terminate() OpenGL 4.1 / GLSL PythonでVAOによるGLSLシェーダープログラミング! - CodeLabo Suspected fragment shader problem, No color, OpenGL 4, GLFW 3, GLEW - OpenGL / OpenGL: Basic Coding - Khronos Forums 床井研究室 - 第2回 テクスチャの割り当て Vendor : b'Intel Inc.' GPU : b'Intel Iris OpenGL Engine' OpenGL version : b'4.1 INTEL-14.4.23' import sys from OpenGL.GL import * import glfw import numpy as np import cv2 vertex_shader_text = ''' #version 410 core in vec3 vPosition; out vec2 vTextureCoord; void main(void) { vTextureCoord = vec2((vPosition.x + 1.0) / 2, (vPosition.y + 1.0) / 2); gl_Position = vec4(vPosition, 1.0); } ''' fragment_shader_text = ''' #version 410 core uniform sampler2D vTexture; in vec2 vTextureCoord; out vec4 flagColor; void main(void) { flagColor = texture(vTexture, vTextureCoord).rgba; } ''' def init_context(): print('Initializing context..') glfw.init() glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4) glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1) glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True) glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE) global window window = glfw.create_window(512, 512, __file__, None, None) glfw.make_context_current(window) print('Vendor :', glGetString(GL_VENDOR)) print('GPU :', glGetString(GL_RENDERER)) print('OpenGL version :', glGetString(GL_VERSION)) def init_texture(): print('Initializing texture..') img = cv2.imread('lena.png', 1) img_gl = cv2.cvtColor(cv2.flip(img, 0), cv2.COLOR_BGR2RGB) global width, height height, width = img.shape[:2] global texture texture = glGenTextures(1) glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, texture) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glPixelStorei(GL_UNPACK_ALIGNMENT, 1) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_gl) def init_shader(): print('Initializing shader..') global vertex_shader vertex_shader = glCreateShader(GL_VERTEX_SHADER) glShaderSource(vertex_shader, vertex_shader_text) glCompileShader(vertex_shader) if not glGetShaderiv(vertex_shader, GL_COMPILE_STATUS): print('Vertex shader is not OK') print(glGetShaderInfoLog(vertex_shader)) sys.exit(1) else: print('Vertex shader is OK') global fragment_shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER) glShaderSource(fragment_shader, fragment_shader_text) glCompileShader(fragment_shader) if not glGetShaderiv(fragment_shader, GL_COMPILE_STATUS): print('Fragment shader is not OK') print(glGetShaderInfoLog(fragment_shader)) sys.exit(1) else: print('Fragment shader is OK') global program program = glCreateProgram() glAttachShader(program, vertex_shader) glDeleteShader(vertex_shader) glAttachShader(program, fragment_shader) glDeleteShader(fragment_shader) glLinkProgram(program) if not glGetProgramiv(program, GL_LINK_STATUS): print('Shader program is not OK') print(glGetProgramInfoLog(program)) sys.exit(1) else: print('Shader program is OK') def init_vao(): print('Initializing vao..') # anti-clockwise vertices = np.array([ -1.0, -1.0, 0.0, # left bottom 1.0, -1.0, 0.0, # right bottom -1.0, 1.0, 0.0, # left top -1.0, 1.0, 0.0, # left top 1.0, -1.0, 0.0, # right bottom 1.0, 1.0, 0.0, # right top ], dtype=np.float32) global vertex_vbo vertex_vbo = glGenBuffers(1) global vertex_vao vertex_vao = glGenVertexArrays(1) glBindVertexArray(vertex_vao) glEnableVertexAttribArray(0) glBindBuffer(GL_ARRAY_BUFFER, vertex_vbo) glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW) glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, None) glBindVertexArray(0) def render(): glUseProgram(program) glUniform1i(glGetUniformLocation(program, 'vTexture'), 0) glBindVertexArray(vertex_vao) glDrawArrays(GL_TRIANGLES, 0, 6) glBindVertexArray(0) if __name__ == '__main__': init_context() init_texture() init_shader() init_vao() print('Start rendering..') while not glfw.window_should_close(window): glClearColor(0, 0, 0, 1) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) render() glfw.swap_buffers(window) glfw.poll_events() glfw.destroy_window(window) glfw.terminate() PyOpenGL Documentation PyOpenGL · PyPI glfw · PyPI

2020年3月23日 · aoirint

Fisheye distortion

OpenCV: Camera Calibration and 3D Reconstruction OpenCV: Fisheye camera model 歪みなしカメラ画像の座標変換 - えやみぐさ カメラ座標 $$ P_c = \left( \begin{array}{c} X_c \ Y_c \ Z_c \end{array} \right) $$ $$ x’ = X_c / Z_c \ y’ = Y_c / Z_c \ r^2 = x’^2 + y’^2 \ \theta = {\rm atan}(r) $$ 歪み補正 / Distortion correction $$ \theta_d = \theta ( 1 + k_1 \theta^2 + k_2 \theta^4 + k_3 \theta^6 + k_4 \theta^8 )\ x’’ = \frac{ \theta_d }{r} x’ \ y’’ = \frac{ \theta_d }{r} y' $$ ...

2020年3月21日 · aoirint

Lens Distortion

OpenCV: Camera Calibration and 3D Reconstruction 歪みなしカメラ画像の座標変換 - えやみぐさ カメラ座標 $$ P_c = \left( \begin{array}{c} X_c \ Y_c \ Z_c \end{array} \right) $$ $$ x’ = X_c / Z_c \ y’ = Y_c / Z_c \ r^2 = x’^2 + y’^2 $$ 歪み補正 / Distortion correction $$ x’’ = x’ \frac{ 1 + k_1\ r^2 + k_2\ r^4 + k_3\ r^6 }{ 1 + k_4\ r^2 + k_5\ r^4 + k_6\ r^6 } + 2 p_1 x’ y’ + p_2 (r^2 + 2 x’^2) + s_1 r^2 + s_2 r^4 \ y’’ = y’ \frac{ 1 + k_1\ r^2 + k_2\ r^4 + k_3\ r^6 }{ 1 + k_4\ r^2 + k_5\ r^4 + k_6\ r^6 } + p_1 (r^2 + 2 y’^2) + 2 p_2 x’ y’ + s_1 r^2 + s_2 r^4 $$ ...

2020年3月21日 · aoirint