ましろの興味が書く

UnityとかVRChatとかプログラミングとか電子工作とかロマンあふれるガジェットに興味があるぞ

pc キッティング

pcのキッティング

入れるソフト

  • vivaldi
  • vscode
  • wiztree
  • everything
  • QTTabBar win11になって標準機能になったdd
  • autohotkey
  • ctrl2cap
  • powertoys
  • ule4jis 標準設定で英字配列にできる
  • IME Cursor
  • chocolatey wingetで代用

ule4jis -> windows設定の英語キーボード(101/102キー)で代用できそう
chocolatey -> wingetのほうが商用ライセンス的に良さそう

winget

仕事用
winget install VivaldiTechnologies.Vivaldi
winget install Microsoft.VisualStudioCode
winget install -s msstore powertoys
winget install git.git
winget install AutoHotkey.AutoHotkey
winget install Google.JapaneseIME

プライベート
winget install Discord.Discord
winget install File-New-Project.EarTrumpet
winget install VB-Audio.Voicemeeter.Banana
winget install OpenJS.NodeJS.LTS
winget install 7zip.7zip
winget install voidtools.Everything

google ime 設定

keymap.txt

status   key command
Composition Backspace   Backspace
Composition Ctrl a  MoveCursorToBeginning
Composition Ctrl Backspace  Backspace
Composition Ctrl d  MoveCursorRight
Composition Ctrl Down   MoveCursorToEnd
Composition Ctrl e  MoveCursorToBeginning
Composition Ctrl Enter  Commit
Composition Ctrl f  MoveCursorToEnd
Composition Ctrl g  Delete
Composition Ctrl h  Backspace
Composition Ctrl i  ConvertToFullKatakana
Composition Ctrl k  MoveCursorLeft
Composition Ctrl l  MoveCursorRight
Composition Ctrl Left   MoveCursorToBeginning
Composition Ctrl m  Commit
Composition Ctrl n  MoveCursorToEnd
Composition Ctrl o  ConvertToHalfWidth
Composition Ctrl p  ConvertToFullAlphanumeric
Composition Ctrl Right  MoveCursorToEnd
Composition Ctrl s  MoveCursorLeft
Composition Ctrl t  ConvertToHalfAlphanumeric
Composition Ctrl u  ConvertToHiragana
Composition Ctrl Up MoveCursorToBeginning
Composition Ctrl x  MoveCursorToEnd
Composition Ctrl z  Cancel
Composition Delete  Delete
Composition Down    MoveCursorToEnd
Composition Eisu    ToggleAlphanumericMode
Composition End MoveCursorToEnd
Composition Enter   Commit
Composition ESC Cancel
Composition F10 ConvertToHalfAlphanumeric
Composition F2  ConvertWithoutHistory
Composition F6  ConvertToHiragana
Composition F7  ConvertToFullKatakana
Composition F8  ConvertToHalfWidth
Composition F9  ConvertToFullAlphanumeric
Composition Ctrl Space  IMEOff
Composition Henkan  Convert
Composition Hiragana    InputModeHiragana
Composition Home    MoveCursorToBeginning
Composition Katakana    InputModeFullKatakana
Composition Left    MoveCursorLeft
Composition Muhenkan    SwitchKanaType
Composition Right   MoveCursorRight
Composition Shift Backspace Backspace
Composition Shift ESC   Cancel
Composition Shift Left  MoveCursorLeft
Composition Shift Muhenkan  ConvertToFullAlphanumeric
Composition Shift Right MoveCursorRight
Composition Shift Space Convert
Composition Space   Convert
Composition Tab PredictAndConvert
Composition VirtualLeft MoveCursorLeft
Composition VirtualRight    MoveCursorRight
Composition VirtualEnter    Commit
Conversion  Backspace   Cancel
Conversion  Ctrl a  SegmentFocusFirst
Conversion  Ctrl Backspace  Cancel
Conversion  Ctrl d  SegmentFocusRight
Conversion  Ctrl Down   CommitOnlyFirstSegment
Conversion  Ctrl e  ConvertPrev
Conversion  Ctrl Enter  Commit
Conversion  Ctrl f  SegmentFocusLast
Conversion  Ctrl g  Cancel
Conversion  Ctrl h  Cancel
Conversion  Ctrl i  ConvertToFullKatakana
Conversion  Ctrl k  SegmentWidthShrink
Conversion  Ctrl l  SegmentWidthExpand
Conversion  Ctrl Left   SegmentFocusFirst
Conversion  Ctrl m  Commit
Conversion  Ctrl n  CommitOnlyFirstSegment
Conversion  Ctrl o  ConvertToHalfWidth
Conversion  Ctrl p  ConvertToFullAlphanumeric
Conversion  Ctrl Right  SegmentFocusLast
Conversion  Ctrl s  SegmentFocusLeft
Conversion  Ctrl Shift Space    InsertFullSpace
Conversion  Ctrl t  ConvertToHalfAlphanumeric
Conversion  Ctrl u  ConvertToHiragana
Conversion  Ctrl Up ConvertPrev
Conversion  Ctrl x  ConvertNext
Conversion  Ctrl z  Cancel
Conversion  Delete  Cancel
Conversion  Down    ConvertNext
Conversion  Eisu    ToggleAlphanumericMode
Conversion  End SegmentFocusLast
Conversion  Enter   Commit
Conversion  ESC Cancel
Conversion  F10 ConvertToHalfAlphanumeric
Conversion  F6  ConvertToHiragana
Conversion  F7  ConvertToFullKatakana
Conversion  F8  ConvertToHalfWidth
Conversion  F9  ConvertToFullAlphanumeric
Conversion  Ctrl Space  IMEOff
Conversion  Henkan  ConvertNext
Conversion  Hiragana    InputModeHiragana
Conversion  Home    SegmentFocusFirst
Conversion  Katakana    InputModeFullKatakana
Conversion  Left    SegmentFocusLeft
Conversion  Muhenkan    SwitchKanaType
Conversion  PageDown    ConvertNextPage
Conversion  PageUp  ConvertPrevPage
Conversion  Right   SegmentFocusRight
Conversion  Shift Backspace Cancel
Conversion  Shift Down  ConvertNextPage
Conversion  Shift ESC   Cancel
Conversion  Shift Henkan    ConvertPrev
Conversion  Shift Left  SegmentWidthShrink
Conversion  Shift Muhenkan  ConvertToFullAlphanumeric
Conversion  Shift Right SegmentWidthExpand
Conversion  Shift Space ConvertPrev
Conversion  Shift Tab   ConvertPrev
Conversion  Shift Up    ConvertPrevPage
Conversion  Space   ConvertNext
Conversion  Tab PredictAndConvert
Conversion  Up  ConvertPrev
Conversion  VirtualLeft SegmentWidthShrink
Conversion  VirtualRight    SegmentWidthExpand
Conversion  VirtualEnter    CommitOnlyFirstSegment
DirectInput Eisu    IMEOn
DirectInput F13 IMEOn
DirectInput Ctrl Space  IMEOn
DirectInput Henkan  Reconvert
DirectInput Hiragana    IMEOn
DirectInput Katakana    IMEOn
Precomposition  Backspace   Revert
Precomposition  Ctrl Backspace  Undo
Precomposition  Ctrl Shift Space    InsertFullSpace
Precomposition  Eisu    ToggleAlphanumericMode
Precomposition  Ctrl Space  IMEOff
Precomposition  Hiragana    InputModeHiragana
Precomposition  Henkan  Reconvert
Precomposition  Katakana    InputModeFullKatakana
Precomposition  Muhenkan    InputModeSwitchKanaType
Precomposition  Shift Muhenkan  ToggleAlphanumericMode
Precomposition  Shift Space InsertAlternateSpace
Precomposition  Space   InsertSpace
Prediction  Ctrl Delete DeleteSelectedCandidate
Suggestion  Down    PredictAndConvert
Suggestion  Shift Enter CommitFirstSuggestion
Composition ASCII   InsertCharacter
Composition Kanji   IMEOff
Composition OFF IMEOff
Composition ON  IMEOn
Conversion  Kanji   IMEOff
Conversion  OFF IMEOff
Conversion  ON  IMEOn
DirectInput Kanji   IMEOn
DirectInput ON  IMEOn
Precomposition  ASCII   InsertCharacter
Precomposition  Kanji   IMEOff
Precomposition  OFF IMEOff
Precomposition  ON  IMEOn

エクスプローラー右クリック戻す

エクスプローラーで右クリックした際のそのほかのオプションを標準表示できるようレジストリをいじるコマンド

右クリメニュー
reg add "HKEY_CURRENT_USER\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /v "a" /t "REG_DWORD" /d ""
reg add "HKEY_CURRENT_USER\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /ve

戻したいとき
reg.exe delete “HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}” /f

autohotkey

vhk v2.0 対応版がgithubにあります。 https://github.com/masirof/autohotkey-setting

ahk

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#InstallKeybdHook ;for debug key history
#HotkeyModifierTimeout, 100
#UseHook on


; vkeb is 無変換(デスクトップの場合hhkb)
; vl1d is 無変換(ノートパソコン)
vkeb & j::Send, {Blind}{down}
vkeb & k::Send, {Blind}{up}
vkeb & h::Send, {Blind}{left}
vkeb & l::Send, {Blind}{right} ;[;]p
; vkeb & p::Send, {Backspace} ;削除
; vkeb & [::Send, {BackSpace}
vkeb & vkba::Send, {Enter} ;無変換+;=削除
; vkeb & vkbb::Send, {Enter} ;無変換+;=削除
; vkeb & c::Send, {alt} ;無変換+;=削除
; キーリピート(押しっぱなし)が発生する

; vkeb & tab::send, {Blind}<#{tab}<
vkeb & tab::#Tab ;無変換+tab = win+tab
vkeb & d::alttab ;無変換+d = alt+tab
vkeb & Space::!Space

vkeb & x::Send, {F5}
vkeb & /::Send, {F12}
vkeb & e::#e ;無変換+e = win+e
vkeb & v::#v
vkeb & r::#r
; vkeb & tab::Send, {esc}

; end desktop keyboard


; ノートパソコン
vk1d & j::Send, {Blind}{down}
vk1d & k::Send, {Blind}{up}
vk1d & h::Send, {Blind}{left}
vk1d & l::Send, {Blind}{right} ;[;]p
; vk14::Ctrl
vk14::
    Send, {Blind}{Ctrl downtemp}
    KeyWait, vk14
    Send, {Blind}{Ctrl up}
    Return
; vk1d & p::Send, {Backspace} ;削除
; vk1d & [::Send, {BackSpace}
vk1d & vkba::Send, {Enter} ;無変換+;=削除

; vk1d & vkbb::Send, {Enter} ;無変換+;=削除
; vk1d & c::Send, {alt} ;無変換+;=削除
; キーリピート(押しっぱなし)が発生する


; vk1d & tab::send, {Blind}<#{tab}<
vk1d & tab::#Tab ;無変換+tab = win+tab
vk1d & d::alttab ;無変換+d = alt+tab
vk1d & Space::!Space

vk1d & x::Send, {F5}
vk1d & /::Send, {F12}
vk1d & e::#e ;無変換+e = win+e
vk1d & v::#v
vk1d & r::#r
; vk1d & tab::Send, {esc}

vk1d & c::
    Send, {Blind}{alt downtemp}
    KeyWait, c
    Send, {Blind}{alt up}
    Return

; かな ahk reload
vk16:: Reload

; f13 ahk pause
f13:: Pause


; vkf2 is カタカナひらがなローマ字
vkff::Send, {Enter}
; vk1c::Send, {Enter}

;vka5(corne chocolate Ralt)
; Ralt+escape押してしまうのでRalt+tabに変更
vka5 & Escape::!Tab


vkeb & c::
    Send, {Blind}{alt downtemp}
    KeyWait, c
    Send, {Blind}{alt up}
    Return

vkeb & ,::
    if GetKeyState("Shift"){
        send {Blind}{Shift}
        send {Blind}{End}
        Return
    }else if GetKeyState("ctrl"){
        send {Blind}{ctrl}
        send {Blind}{End}
        Return
    }else{
        send {End}
        Return
    }
    Return

vkeb & m::
    if GetKeyState("Shift"){
        send {Blind}{Shift}
        send {Blind}{Home}
        Return
    }else if GetKeyState("ctrl"){
        send {Blind}{Ctrl}
        Send {Blind}{Home}
        Return
    }else{
        send {Home}
        Return
    }
    Return

vkeb::
KeyWait,vkeb,D, T0.2 ;2度押しでwindowsキー
if(!ErrorLevel){
    send {Blind}{lwin}
    Return
}
Return

vscode

vscode 拡張機能

code --list-extensions > extensions_list.txt

拡張機能のリストをファイル出力できる(powershell)

code --install-extension [作者名].[拡張機能名]

拡張機能をインストールできる(powershell)

重要 拡張機能

重要

mosapride.zenkaku  
formulahendry.auto-rename-tag  
oderwat.indent-rainbow  
vincaslt.highlight-matching-tag  
chihiro718.whitespacepp  
ecmel.vscode-html-css  

すべて 拡張機能

すべて

abusaidm.html-snippets  
aki77.quick-open-rails  
aki77.rails-partial  
aki77.rails-routes  
alefragnani.Bookmarks  
alexcvzz.vscode-sqlite  
argiolasriccardo90.regions-with-colors  
Asuka.insertnumbers  
castwide.solargraph  
chihiro718.whitespacepp  
christian-kohler.path-intellisense  
CoenraadS.bracket-pair-colorizer  
cweijan.epub-reader  
dbaeumer.vscode-eslint  
donjayamanne.githistory  
ecmel.vscode-html-css  
fabiospampinato.vscode-todo-plus  
formulahendry.auto-rename-tag  
formulahendry.code-runner  
foxundermoon.next-js  
goessner.mdmath  
hoovercj.vscode-power-mode  
IBM.output-colorizer  
James-Yu.latex-workshop  
jebbs.plantuml  
jundat95.react-native-snippet  
kaiwood.endwise  
KevinRose.vsc-python-indent  
kleber-swf.unity-code-snippets  
me-dutour-mathieu.vscode-github-actions  
mosapride.zenkaku  
ms-azuretools.vscode-docker  
MS-CEINTL.vscode-language-pack-ja  
ms-dotnettools.csharp  
ms-python.isort  
ms-python.python  
ms-python.vscode-pylance  
ms-toolsai.jupyter  
ms-toolsai.jupyter-keymap  
ms-toolsai.jupyter-renderers  
ms-toolsai.vscode-jupyter-cell-tags  
ms-toolsai.vscode-jupyter-slideshow  
ms-vscode-remote.remote-containers  
ms-vscode-remote.remote-wsl  
ms-vscode.cpptools  
ms-vscode.mono-debug  
ms-vscode.vscode-serial-monitor  
ms-vsliveshare.vsliveshare  
oderwat.indent-rainbow  
pnp.polacode  
PulkitGangwar.nextjs-snippets  
rebornix.ruby  
redhat.vscode-xml  
redhat.vscode-yaml  
reflectiondm.classynaming  
ritwickdey.LiveServer  
ronaldosena.arduino-snippets  
ryu1kn.partial-diff  
Shan.code-settings-sync  
shardulm94.trailing-spaces  
sianglim.slim  
slevesque.shader  
slevesque.vscode-autohotkey  
stevensona.shader-toy  
streetsidesoftware.code-spell-checker  
Tyriar.shell-launcher  
Tyriar.terminal-tabs  
Unity.unity-debug  
usernamehw.errorlens  
vincaslt.highlight-matching-tag  
vsciot-vscode.vscode-arduino  
vscodevim.vim  
wingrunr21.vscode-ruby  
wraith13.zoombar-vscode  
yzhang.markdown-all-in-one  
Zaczero.bootstrap-v4-snippets  
Zignd.html-css-class-completion  
zrachod.mono-snippets  

vscode settings.json(ユーザー)

設定のjson

{
    "explorer.confirmDelete": true,//削除時確認するか
    "workbench.activityBar.visible": true,//サイドバー
    "workbench.editor.enablePreview": false,
    "workbench.startupEditor": "newUntitledFile",//ウェルカムページ飛ばし
    "workbench.sideBar.location": "left",//サイドバーの位置
    "workbench.colorTheme": "Default Dark+",
    "workbench.colorCustomizations": {
        "editor.findMatchBackground": "#b11b00"
    }, //検索時のマッチ文字を赤く
    "workbench.editor.wrapTabs": true,//タブを折り返すか
    "workbench.editor.tabSizing": "shrink",//タブのサイズを小さく
    "workbench.layoutControl.enabled": false,//4レイアウトボタンoff
    "editor.wordWrap": "on",//文字の折り返し
    "editor.minimap.enabled": false,//ミニマップ
    "editor.parameterHints.enabled": false,//パラメータヒント
    "editor.snippetSuggestions": "top",//スニペットの位置
    "editor.suggest.snippetsPreventQuickSuggestions": false,//タブストップ中に入力補完を有効にする(false)
    "editor.mouseWheelZoom": true,//ctrl+マウスホイールでズーム
    "debug.openDebug": "neverOpen",//デバッグ時に開かない
    "window.title": "${dirty}${rootName}",//ウィンドウのタイトル(短く)
}

vscode keybindings.json

キーバインドのjson

[
    {
        "key": "ctrl+b",
        "command": "-workbench.action.toggleSidebarVisibility"
    },
    {
        "key": "ctrl+shift+2",
        "command": "workbench.action.terminal.focus"
    },
    {
        "key": "ctrl+shift+2",
        "command": "workbench.action.focusActiveEditorGroup",
        "when": "terminalFocus"
    },
    {
        "key": "ctrl+b",
        "command": "workbench.action.toggleSidebarVisibility"
    },
    {
        "key": "ctrl+oem_1 d",
        "command": "-jupyter.moveCellsDown",
        "when": "editorTextFocus && jupyter.featureenabled && jupyter.hascodecells && !notebookEditorFocused"
    },
    {
        "key": "ctrl+d",
        "command": "-list.focusPageDown",
        "when": "listFocus && !inputFocus"
    },
    {
        "key": "ctrl+k ctrl+d",
        "command": "-editor.action.moveSelectionToNextFindMatch",
        "when": "editorFocus"
    },
    {
        "key": "ctrl+k d",
        "command": "-workbench.files.action.compareWithSaved"
    },
    {
        "key": "ctrl+d",
        "command": "-extension.vim_ctrl+d",
        "when": "editorTextFocus && vim.active && !inDebugRepl"
    },
    {
        "key": "ctrl+k ctrl+d",
        "command": "editor.action.moveSelectionToNextFindMatch"
    },
    { 
    "key": "shift+enter", "command": "type",
    "args": { "text": "<br>\n" },
    "when": "editorTextFocus && editorLangId == 'markdown'"
},
{
    "key": "ctrl+tab",
    "command": "-workbench.action.quickOpenNavigateNextInEditorPicker",
    "when": "inEditorsPicker && inQuickOpen"
},
{
    "key": "ctrl+tab",
    "command": "-workbench.action.quickOpenPreviousRecentlyUsedEditorInGroup",
    "when": "!activeEditorGroupEmpty"
},
{
    "key": "ctrl+tab",
    "command": "workbench.action.nextEditor"
},
{
    "key": "ctrl+pagedown",
    "command": "-workbench.action.nextEditor"
},
{
    "key": "ctrl+shift+tab",
    "command": "workbench.action.previousEditor"
},
{
    "key": "ctrl+pageup",
    "command": "-workbench.action.previousEditor"
},
{
    "key": "ctrl+shift+tab",
    "command": "-workbench.action.quickOpenNavigatePreviousInEditorPicker",
    "when": "inEditorsPicker && inQuickOpen"
},
{
    "key": "ctrl+shift+d",
    "command": "-workbench.view.debug",
    "when": "viewContainer.workbench.view.debug.enabled"
},
{
    "key": "ctrl+shift+d",
    "command": "editor.action.selectHighlights",
    "when": "editorFocus"
},
{
    "key": "ctrl+shift+l",
    "command": "-editor.action.selectHighlights",
    "when": "editorFocus"
},
{
    "key": "ctrl+e",
    "command": "latex-workshop.recipes"
},
{
    "key": "ctrl+e",
    "command": "-workbench.action.quickOpen"
},
{
    "key": "ctrl+e",
    "command": "-workbench.action.quickOpenNavigateNextInFilePicker",
    "when": "inFilesPicker && inQuickOpen"
},
{
    // Markdown の行末に、スペース二つと改行を挿入するキーバインド
   "key": "shift+enter",
   "command": "type",
   "args": {"text": "  \r"},
   "when": "editorLangId == markdown"
},
{
    "key": "ctrl+shift+tab",
    "command": "-workbench.action.quickOpenLeastRecentlyUsedEditorInGroup",
    "when": "!activeEditorGroupEmpty"
},
{
    "key": "ctrl+x",
    "command": "editor.action.deleteLines",
    "when": "textInputFocus && !editorReadonly"
},
{
    "key": "ctrl+shift+k",
    "command": "-editor.action.deleteLines",
    "when": "textInputFocus && !editorReadonly"
},
{
    "key": "ctrl+x",
    "command": "-editor.action.clipboardCutAction"
},
{
    "key": "shift+delete",
    "command": "editor.action.clipboardCutAction"
},
{
    "key": "shift+delete",
    "command": "-editor.action.clipboardCutAction"
},
{
    "key": "ctrl+shift+b",
    "command": "-workbench.action.tasks.build",
    "when": "taskCommandsRegistered"
},
{
    "key": "ctrl+shift+b",
    "command": "editor.debug.action.toggleBreakpoint",
    "when": "debuggersAvailable && editorTextFocus"
},
{
    "key": "f9",
    "command": "-editor.debug.action.toggleBreakpoint",
    "when": "debuggersAvailable && editorTextFocus"
}
]

外で作業したかった

作業

作業ができるということは重要だ。この世のすべての行動は作業と言える。食べることも、寝ることも、ゲームすることも、パソコンで記事を書くことも、何かを成し遂げるためにすることは作業と言える。

家ではなかなか作業が出来ずに外に出ようとした。長らく引きこもっていると外を歩いたりして別の環境に自分の身を置くのが恋しくなる。ついでに新しく作った作業セットの実地検証がしたかった。

作業セット

新しい作業セットは、Android スマートフォン + obsidian + 分割キーボードという組み合わせだ。obsidianはmarkdownと呼ばれる便利なテキストフォーマットを編集できる高機能なサービス、アプリだ。この記事はobsidianのテスト用に書いている。

ショルダーバッグひとつという身動きがしやすい装備で外を歩きたかった。いつもはクソでかいバックパックを背負っているため、ショルダーバッグの魅力に取り憑かれてしまった。iPad miniがあれば、iPad mini + 分割キーボードという最高な装備になるのだが、あいにくiPad miniを持ち合わせていない。

作業場所

この組み合わせで作業をするにあたって、イスとテーブルが必要になった。ノートパソコンならば、ラップトップ、膝の上というように座れるところがあればどうにか作業ができる。(床でも作業ができる) だが、この組み合わせを、膝の上に置くには複雑なバランス感覚を制御しなければならず、作業どころではなくなってしまう。また、安定感がなく最悪地面にデバイスが落ちてしまう。

なので、作業をするところ=イスとテーブルが用意されているところ ということになり、ノートパソコンよりもかなり場所を選ぶ。

Google Mapを開いて公園を検索しまくると、イスはあるがテーブルはない。そういう地域に住んでいる。2、3箇所ほど作業できる場所の目処がたった。

急に外に出るのがめんどうくさくなってきた。家にいるのだが、家って食べ物飲み物があるし、ネットがあるし、電源があるし、最強では...? もうここ作業場所でいいのでは。窓を開けて外気分味わえればいいような気がしてきた。

家の中でパソコンがレンダーする自然の風景とDJがかける音楽を聞きながらこの記事を書いた。

youtu.be

この記事は、Android スマートフォン + obsidian + 分割キーボード corne chocolateで作成されました。

MU2023

MU2023

MUとはMusicUnity と呼ばれる音楽DJイベントのことで3回目であるMU2023は2023/03/25-26に羽田空港で行われた.

MU2020,MU2022と来て、2023でも配信してくれるのはとてもありがたいことである.本当にありがとう! 配信するにも色々な費用がかかること、苦労があることがわかるため感謝しかない.完全に文化発展に貢献していてとてもかっこいい. そしてやはり、Music UnityはMU2020の配信から始まったイベントなので配信してくれるのがとてもエモい. MUの主催で、mograの店長であるd-yama氏は今回が最後のMUだと言っており、最後のMUでも配信してくれるのはとてもエモい. 配信イベントで始まり,現地+配信で幕を下ろすのがかなりエモい.感謝しかない.

私は予算の関係上、2日目しか行けず、1日目のMUにはいけなそうなので、配信があるのがとてもありがたかった.アーカイブはないようだ.原盤権の関係でできないと店長がTwitterで嘆いていた.検討してくれてありがとう!

MUが始まるまでの私は

イノタク神のものにつきて心がクレイジークレイジー、
kz(livetune)神の招きにあひて、取るものHand in Hand。

という感じでした.まじで楽しみだった!開催できてうれしみ!

1日目

DJ WILDPARTY

MU2022のワイパのおかげでJägermeisterという曲を知れて,そのおかげでガバキックの音が好きになりました.ありがとうワイパ... 楽しそうなDJのおかげで,食わず嫌い音源なくなるの気持ち良すぎ...

www.youtube.com

今回もJägermeisterかけてくれてうれしい...

www.youtube.com

ウマウマのこれ,ドライブ感というか躍動感が良すぎ...こういうの大好き...

www.youtube.com
Massive New KrewのOTAHEN アンセム良すぎでしょ...これも低音の連打による躍動感,スピード感良すぎ

www.youtube.com
Buzz!!りムーヴメント これめちゃくちゃでんぱ組のなんかに似てて,そっちかなーと思っていたら違いましたww いい曲...

www.youtube.com
ワイパ,ヒステリックナイトガールかけて,PSYQUIさんをMusicUnityに連れて行ってくれてありがとう...

fhana

www.youtube.com

inspiration 喜びとか 言葉を分かち合うたび ああいつか終わりの日が来る そう感じさせるよ initialize その扉を 開ける時が来るのだろう 綺麗な時を閉じ込めて 湖に沈めたの だけど私平気だよと 星の便りに綴る

DJ たぬきゅん

たぬきゅんのことは知らなかったが,オタク向けのDJをしていて,信頼できると思いました. Twitchのコメント欄でd-yama店長が作ったセトリだろこれ!って言われていて笑いましたww

爽健美茶のラップのsoundcloudでは聞いたことあるんですが,あれってchelmicoなのか...どうりで聞いたことある声だと...

ピーナッツくん

DJのひとがlainのTシャツ着ていてうおーになった. マイクが音割れと言うか,途切れていたが,逆に味があってかなり良かった ピーナッツくんのpeanut phenomenonの歌が好きすぎた.ピーナッツくんめっちゃ叫んで歌っててかなりウオー!になった. かなりアツかった.ぽこピーのチャンネルはよく見ているが,ピーナッツくんやっぱアーティストなのかとわからされた.

www.youtube.com
3分からのいけいけいけ!!!すごい
ピーナッツくんには無限に叫んでいてほしい.

ポタロビじゃないひと

DJ NOT PORTER ROBINSON!!! すげえオタク!いいDJ... ポタロビのライブではkzが先で,ポタロビが後という順番でDJしたんですが,今回のMUではそれが逆になるってめちゃくちゃエモくないですか... notポタロビがtell your world流してkzにつなげるの完全に理解してる!!!さすが!!!やば!!!と思いました...

kz

VRChatでのサンリオイベントのalt3でkzさんを見てからというもの,ずっと心がalt3にある気がする.kzさんの曲を聞くとalt3に飛ばされる.
kz,やはりkz.never enderがちゃんと来た…never enderよすぎムリ...

今回の「いつか雲が晴れたなら」のRemixは雲が晴れてましたね... MU2022よりテンションがあがった曲調になっておりめちゃくちゃ晴天の音楽だった... 最初は天気のことで,晴れたって言っているのかと思っていたら,そんなに天気は曇っているのに晴れたって言っていて,流行り病のことかと合点が行きました.

kzって泣けるんだよなぁ...感想かけないんだよなぁ...聞いたら感情が終わるので終わりです. なんなんだあのど直球ないい歌詞...歌詞...

rayの初音ミクが歌うやつとかずるいし,Redialで終わるし,急なBreathでをとはちゃん来るし,終わりや

2日目

アキバでオタクと会う

いよいよ現場!START DASH SENSATIONってコト!?私は一直線にMUの会場に行くというとそうではない.秋葉に寄ったのだ.ここで友人と合流してご飯を食べたりした.人間とご飯を食べると美味しい. 秋葉では無印良品に電子工作のガワに使用するケースを買いに行き、秋月電子ではフェーダー(DJが直線上に動かして音を調節するアレ)を買った.これらのパーツを使用してミキサーでも作ろうかと思ったのだ.

twitter.com
つくりはじめた!

この時点で、MUのアーティストが1組ぐらい終わっていた.なぜ焦ってMU会場に行かないかというと、調達も大事だからである.(どうせオタクの体力もたないから,観光して行こう!)また、1日目の配信が無料であったためもうチケットの半分ほどの元は取っているぐらいの気分であった.そして、最悪Taku Inoueだけ見れれば良いと考えていたのである.

調達も無事に終わり,BatsuくんのDJが始まってしまい,オタクと移動しながら聞き、Aiobahnとナナヲアカリをステージ最後尾で聞き、国士無双になってから何故か人が減り始めたので(国士無双はいいDJをしていた)DJのステージに近づくことができた.国士無双から最後のTaku Inoueまでその場所で立って踊っていた.3時間半ぐらい立って踊ったりノって体を揺らしていたりした.一応,健康に気を使った(健康に気を使うやつは現場に来ない)

現場第一印象

まず,第二ターミナルに着いたがどこから入るのかがわからないww
デカすぎて,人いすぎて,圧巻であった.何あの建築物.ああいう直線的で幾何学的な建築物美しすぎ...
とにかくググると6番の時計台近くに7番出口があるからそれ出て左に歩くと会場の入口に着くらしい. 左に歩き続けるとこれ,星野源の不思議で見た羽田ではになった.そうなのだろうか.もしそうだとしたら,私は星野源である.(?)

www.youtube.com

今回の会場ではラインアレイスピーカーが使われており、普通のスピーカーが円状に音が飛ぶのと違い直線上に音が飛ぶ.
結構前の方にいたのだが、高音がギャザって、キンキンして辛い場面があった.嗅覚疲労のように聴覚疲労をすると音がマイルドになる.脳が頑張ってマイルドにしているのだろう.
低音!低音はすばらしい!腹と喉が圧迫される!すばらしい!この体験だよこの体験!!

Pioneerキャンペーン

Pioneer が新作DJコントローラの体験会をやっていたので適当に教えてもらいつついじらせていただいた.なんとDJコントローラーをハッシュタグと共にツイートするとDJコンが当たるキャンペーンをしていた.また、ツイートを投稿したのを係の人に見せるとトートバックがもらえるキャンペーンをしていていたのでもらってきた!やったー!DJじゃないのに,トートバッグを持っている人になりました.DJコンいいねになりそうで危なかった...

d-yama

個人的に店長のDJも好きで,いい曲を気持ちよくかけるグルーブ感がたまらない. ムーンライト伝説かけるところとか気持ち良すぎる.体が横に揺れる.このムーンライト伝説,めちゃくちゃ治安が悪そうなremixでめちゃくちゃ好き.

ごめんね素直じゃなくて
夢の中なら云える
思考回路はショート寸前
今すぐ 会いたいよ

星間飛行とか,コードギアスのCOLORS James Landino Remixよすぎ...よすぎる 曲選がいい(知っている曲をいいと思っている)のと,DJがめちゃくちゃうまいのでもう最高!

www.youtube.com
これよすぎ

in the blue shirt

in the blue shirt のDJでは、VJであるosirasekita(らしお)さんがMU2020のin the blue shirt の映像を流してエモすぎてトマソンスタジオサイコー!になりました.Batsuさんがハンディカメラを担当してアリムラさんに近づいて、トマソンスタジオ…トマソンスタジオ…になりました.エモい. 寿司のネタとシャリが合体するみたいなVJが好き... パ音のinner blueのin the blue shirt remix?がかなり良かった.inner blue良すぎて何してもいいんだよなぁ!

twitter.com

ダンスは続いてる...ダンスをするのが超大事! 近くに,ハンディカムを持ったBatsuくんがおり,うわ!生Batsuくんじゃん!になってました...

okadada

okadadaのDJはやはり気持ちよさそうにオシャレなクネクネを見せつけるokadadaよすぎるになります.okadadaのヴォサノバkick back好きすぎて、イントロで理解してウオーしていたら周りがあんま知らなそうでうーんになりましたが、kick backだと分かる音がし出すとウオウオして良かったです. okadadaの髪の毛をふぁさーってするやつとか,その場で走る動きとか,動きが良すぎる. okadadaは盛り上げるところは盛り上げるし,自分のやりたいことをやっているような気がしていて良かった. okadadaはやはり独特でとても良い.

www.youtube.com
Little Bitch流れたときのokadadaさんの動き好きすぎて好き

www.youtube.com
sex on the beach良すぎ...

Taku inoue

Like a 雷火 いや,雷火で始まるの雷火すぎない!?と思いました.まじ雷火みてぇ... 今回の心予報はNor remixじゃなくてちょっとあれだったけど,違うRemixか原曲だったので良かったです.

Taku InoueのDJはとにかくやばかった. ほぼ全員のオタクが曲を知っているのである.全員ジャンプするし、手拍子するし、クネクネしている.やはり、分かる人間といると一体感が生まれ、一曲の中で音楽が静かになるタイミングを理解しており同じタイミングで腕を上げるのをやめるとかなり気持ちよい. あと、歌詞を理解しているほぼ全員のオタク達と歌詞を声に出して一緒にいえると気持ちが良い.手拍子するタイミングが一緒であっても気持ちが良い.オタクたちの一体感が半端ない、歓声を上げるとこも、手拍子するタイミングも、手を上げるタイミングも、同じで、一緒に歌詞を声に出した時はもの言えぬ感動がある.イノタク強い曲しかかけなくてオタク足が限界になりました.イノタク俺を許してくれ,もうめちゃくちゃいい曲しかかけないやん...イノタクを許すな イノタクで5回ほど感動してムリで泣いててもうムリだった...

steller stellerには

その手を伸ばして 誰かに届くように

という歌詞があり,その時にイノタクもオタクも手を宇宙に伸ばしてマジで無理だった 届いてくれ... 誰かに届くといいな...

3時12分を現地で体験してからというもの,MVにでてくるような都市の景観を見ると勝手に3時12分になってしまうww イノタク,MCうますぎて常時グダっていたはずなのにおもしろかった...イノタク...すげえ...

クラブイベントが終わるときの「撤収ー!」がめちゃくちゃ好きで,終わりたくないオタクにチャンスをくれているみたいでマジで好き.撤収ー!がないと,心が収まらず撤収ができないのでめちゃくちゃ助かる

まとめ

MUを検索する

twitterで「#MU2023 shazam」とか「#MU2023 [アーティスト名]」とかすると曲が見つかり楽しい.

MU Spotify

適当に聞いたり,調べたりしたMUで流れた曲をまとめました.抜けが多く個人的なものです.

DJっていいよね

楽しい状態で曲聞くと絶対すきになるし,好きなDJが知らない曲かけると絶対すきになるし,音楽ってたのしい. 知らないRemixとか知らない曲でも好きになる確率が1人で聞くよりも高いと思う.音楽は楽しい状態で聞くのが超大事! オタク達と楽しく音楽聞けて楽しかった... VJも今回もすごくよかった...好きなデザインの仕方の素材があり,VJの画面をよく映像として記録した.

MUありがとう!!

MU愛しているぜ! オタク共はインターネットかどっかのクラブにいるからMUがなくなっても楽しく生きていけると思います.

MusicUnityはなくなる。そのために存在する。
だが音楽は永遠だ。それはオタク共も永遠だということだ。

羽田で寝る

終わり、電車で帰ろうとしたら、どうやら4時間ほど帰るまでに終電という名の待機時間があるためどうしようかと考えた.そんなお金をかけず寝れそうなところはどこだろうと考えたら、どっかの誰かが空港を住処にした記事を思い出した.ググると意外にも空港での仮眠法の記事が見つかり、興味で空港で寝ることにした.羽田第二ターミナルでMUは行われたのだが、疲れて適当にスマホを充電していたら警備員に第二ターミナルは24時には閉まるらしく、国際線のある第三ターミナルか駐車場待機場所?みたいなところに行けと言われた.第三ターミナルに行くと言ったらターミナル間をつなぐ無料のバスがあるからそれ使ってというお得情報を手に入れ、第三ターミナルへと向かった. 羽田空港にはフリーwifiがあるのだが、セキュリティが心配なので偉大な方々が解放しているVPNを使わせていただくことにした.この時間でこの文章を少しだけiPadで書いた.小さくてもいいからキーボードは持っていくべきだと感じた.小さい執筆環境ほしいね.

第三ターミナルにいくと日本村みたいなところがあり,いろいろな人種の人々が寝ていたきれいなスラム街があった.人種も関係なくみんなすやすやしていた.もちろん私もそこですやすやした.

kotokoの未来列車 の歌詞とリンクしてかなり良かった
www.youtube.com

ここからは各駅停車の未来行きです
性別も生まれた国も 経験値も問いません
お隣と挨拶して おやつは分け合って
右に見えますのは 地球と言う星
ケンカばかりして でも優しい生き物の星です
君とspace trip!
シリウス スピカ ペテルギウス アークトゥルス ベガ
宙のポケットで生まれた新星のダンス
ガタゴト レールが回るターンテーブルでステップ踏もう!

ここの歌詞の人種関係なく一緒にいろんな国の人と寝ている感じがかなり良かった.音楽と一緒ならどこまでもいけそうだ.

vivaldiで再起動をするクイックコマンドを作る

なぜか「vivaldi://restart」は使えなかったので「chrome://restart」を使うのがミソ.

あとは,コマンドのテストを押してもテストできないので注意

下のツイートのように 「現在のタブでリンクを開く」と「chrome://restart」をしていすれば完了. テストは「クイックコマンド」を表示してコマンド名を入力してテストすると良い.

vscodeというエディタがあり,そこではctrl shift pを押すとクイックコマンドが出て,「reload window」というコマンドが用意されていて,バグったときとかにすぐ再起動できて良い.

vivaldichrome拡張機能を作成していて,無限ループするコードを書くとバグるので,すぐに再起動できると良いので今回の試作を行った.

おもしろ訳をkindleにいれる(EPUB作成,Pythonスクレイピング)

tsurezuregusa.com

こちらのサイトの徒然草の訳が大変おもしろく,現代にあっているため,Kindleで読みたい.

Kindleにはマーカーを引くことによって,いつでも読み返したいところを読み返すことができる大変便利な機能が存在する.

この記事では

  1. pythonスクレイピングする
  2. pythonEPUBファイルを作るための,xhtmlファイルを生成する
  3. EPUBファイルをzip圧縮で作成
  4. kindleに読み込む

を行う.

電子書籍のフォーマット(適当)

リフロー型

文字の大きさなどが変わる

フィックス型

文字の大きさなどが固定

kindleEPUBが使えるようになる

電子書籍にはMOBIとEPUBなどのフォーマットがあり,KindleではMOBIに変換しなければいけないらしかったが,2022年5月にEPUBを対応したらしく,読み込めるようになっている. MOBI形式について調べたが,人間には読み書きできるものではなく,コンピュータが処理する用のデータであった.また,2022年後半からは一部の手段で送信できなくなるので,できるだけ使用を控えたい.

EPUB形式は後述する.結果的にはEPUB形式を採用する.

EPUBフォーマット

EPUB形式のファイルの内部構造

電子書籍づくり実践(EPUBの構造 xhtmlとcss) - 本好きに送る「電子書籍のつくり方」講座

EPUBファイルを入手する

Push to Kindleというchrome拡張を使用して,サイトの1ページのみをEPUB形式に変換.

Push to kindleでページをEPUB形式に変換

EPUBをZIPで展開,圧縮

EPUBは拡張子を.epubから.zipに変換して展開することで中身を展開して,見ることができるらしい.おもしろだ!

zip解凍をして,見ることができる内部
やってみたらたしかに吐き出した.

また,展開したファイルをzipで圧縮して.epubに拡張子を変えることでkindleなどで読み込めるらしい.

やってみたが,できなかった.

ただただzip圧縮して拡張子をEPUBに変えて,読み込みしたEPUBファイルくん

どうやらzip圧縮のコツがあるらしい.

$ cd ディレクトebookへのディレクトリパス $ zip -0 -X ../ebook.epub mimetype $ zip -r ../ebook.epub * -x mimetype $ cd ..

EPUBパッケージ方法

Windows 8.1の場合は、 まず、mimetypeファイルだけを右クリックして「送る」を選び「圧縮(zip形式)フォルダー」を選ぶと、mimetype.zipが出来ます。 次に、mimetype以外のファイルを全てmimetype.zipにドラッグ アンド ドロップして追加します。 最後に、mimetype.zipを例えば○○.epubへファイル名を変えます。

第4話 電子書籍(ePub)の展開と再圧縮 - 電子書籍を作成しよう!(エリファス1810) - カクヨム

上記の方法を行うことで,読み込めるEPUB形式のファイルを生成することができた.

zip -0 -X export_book\turezure_150_4.epub mimetype
zip -r export_book\turezure_150_4.epub * -x mimetype "./export_book/*"

最終的にこのようなコマンドになった

export_bookというディレクトリ以外をzip化する

windows環境ではzip.exeをインストールする

windowsでzipコマンドを使うためにはzip.exeをインストールしなければならない. 筆者のデスクトップ環境ではLiveTexをインストールしたときに一緒にインストールされていて気が付かなかった.

Windows上でzipコマンドを使用する為の方法 | そう備忘録

上の記事を参考にしてインストールを行った.

vscodeEPUBを読む 拡張機能

VSCodeEPUB形式を読む
VSCode拡張機能を使用することでEPUBを読み込むことができた. 見切れるなど,微妙なところもあるが,確認できればいいのでとりあえずこの拡張機能を使用する.

marketplace.visualstudio.com

kindleEPUBファイルを送る

送るには

  • send to kindle(日本だとアプリが使えない,iPhoneの「kindleに送信を使う」)
  • Kindleパーソナル・ドキュメントサービス(メールでファイルを送るやつ)

がある.

ローカルな端末内に保存する方法ではなく,amazonのサーバー内に保存するパーソナルドキュメントにできれば,ラインマーカーを共有することができるはず

send to kindle(iPhoneの「kindleに送信を使う」)を使用して,送信してみた.

iPadkindleで見たところ

軽く見たところ,

  • Kindleで小説を読むみたいに縦書きが良い
  • いらない情報があるので編集したい(画像では見えないが,人気のページリンクや画像)

などの不満がでてきた.

また,全ページを取得し,一つのEPUB形式のファイルにしてkindleで読みたい

markdown, xhtml+cssどちらで書くか

編集するにあたって,

の方法がある.

とりあえず,xhtml+cssEPUBファイルを生成していくように進めていく.

なぜならmarkdownの変換先がEPUBファイルであり,EPUBファイル自体を編集できると便利そうなので.

EPUBを書く

参考になりそうなガイドPDF

電書協 EPUB 3 制作ガイド | デジタル出版者連盟(旧・日本電子書籍出版社協会)

上の記事では,網羅的に内容が書かれているが,読むのが大変である.

自力でいちからEPUB形式の電子書籍を作ってみる! HTML/CSSの知識があれば十分!?|『人文×社会』の中の人|note

上の記事の基本が詰まっている記事 簡単にチュートリアルできるので大変オススメ

本記事では上のnoteをベースにEPUBファイルを作成する

ibookで読むかkindleで読むか

結果を書くとkindleデバッグを行い,kindleで読むことになった.

本がユニークな扱いか

EPUBファイルは,.opfファイルの「dc:identifier」が同じだとiPadアプリのibookでは同じ本として扱われるためデバッグしにくい,そのため変更すると良い(kindleだと別の本として扱われる)

縦書き表示への対応

.opfファイルに

<spine page-progression-direction="rtl">
</spine>

「page-progression-direction="rtl"」をつけることで縦書き表示をすることができる.

.cssファイルには vscode拡張機能で確認したら効果があったスタイルを書く (kindle版に効果があるのかわからないが)

html {
    -webkit-writing-mode: vertical-rl;
    -webkit-text-orientation: mixed;
    -epub-writing-mode: vertical-rl;
    -epub-text-orientation: mixed;
    writing-mode: vertical-rl;
    text-orientation: mixed;
}

を記載しておく.

少し調べると,どうやら「.azk」という拡張子にファイル変換するといけるらしい...?

nOnのなんでも情報館Blog

とりあえず,iPad用の縦書き対応は後回し(スマホで読めれば十分)

Pythonスクレイピング

スクレイピングによってWEBからページ内情報を自動取得する.

自動で各ページから

  • タイトル
  • 現代語訳
  • 原文
  • 注釈

を取得します

import requests
from soupsieve import select
from lxml import html
from bs4 import BeautifulSoup
import time

r = requests.get(url)
soup = BeautifulSoup(r.content, 'lxml')

title = soup.select('header>h1')[0].getText()
modern_translation = soup.select('article > section > p:nth-child(2)')[0].getText()
original_text = soup.select('section > blockquote > p')[0].getText()
annotation_text = soup.select('section > h4 ~ p') #section > h4 の兄弟のpタグから最後のpタグまで

# print(f'現代語訳 {modern_translation}')
# print(f'原文 {original_text}')
# print(f'注釈 {annotation_text}')

annotation_text_list = []
for v in range(len(annotation_text)):
    content = annotation_text[v].get_text().replace('\u3000','')
    if len(content) == 0:
        None
    else:
        annotation_text_list.append(content)

複数のページを一つxhtmlファイルに書き込み

# 初期要素の書き込み
path = 'NOT_export/pywrite_test.xhtml'
with open(path,'w',encoding='utf-8') as f: #w = 上書き a=追加
    first_lines = [
        '<?xml version="1.0" encoding="UTF-8"?>\n'
        '<!DOCTYPE html>\n'
        '<html\n'
        '\txmlns="http://www.w3.org/1999/xhtml"\n'
        '\txmlns:epub="http://www.idpf.org/2007/ops"\n'
        '\txml:lang="ja"\n'
        '>\n'
        '\n'
        '<head>\n'
        '\t<meta charset="UTF-8"/>\n'
        '\t<title>徒然草本文</title>\n'
        '\t<link rel="stylesheet" type="text/css" href="../style/style.css"/>\n'
        '</head>\n'
        '\n'
        '<body>\n'
    ]
    f.writelines(first_lines)

def two_return_to_one_return(content:str): #改行コードを減らす
    content = content.replace('\n\n','\n')
    return content

#真ん中
path = 'NOT_export/pywrite_test.xhtml'
with open(path,'a', encoding='utf-8') as f: #w = 上書き a=追加
    f.write('\n')
    f.write('\t<h1>'+title+'</h1>\n')
    f.write('\t<h2>現代語訳</h2>\n')
    f.write('\t<p style="white-space:pre-line">'+two_return_to_one_return(modern_translation)+'\n\t</p>\n')
    f.write('\t<h2>原文</h2>\n')
    f.write('\t<p style="white-space:pre-line">'+two_return_to_one_return(original_text)+'\n\t</p>\n')
    f.write('\t<h2>注釈</h2>\n')

    for v in range(0,len(annotation_text_list),2): #2づつ
        f.write(f'\t<h4>{annotation_text_list[v]}・・・{annotation_text_list[v+1]}</h4>\n')

#最後
path = 'NOT_export/pywrite_test.xhtml'
with open(path,'a', encoding='utf-8') as f: #w = 上書き a=追加
#     # end
    f.write('</body>\n')
    f.write('</html>')

コード全体

import requests
from soupsieve import select
from lxml import html
from bs4 import BeautifulSoup
import time


def get_text_and_write_file(url:str):
    r = requests.get(url)
    soup = BeautifulSoup(r.content, 'lxml')

    title = soup.select('header>h1')[0].getText()
    modern_translation = soup.select('article > section > p:nth-child(2)')[0].getText()
    original_text = soup.select('section > blockquote > p')[0].getText()
    annotation_text = soup.select('section > h4 ~ p') #section > h4 の兄弟のpタグから最後のpタグまで

    # print(f'現代語訳 {modern_translation}')
    # print(f'原文 {original_text}')
    # print(f'注釈 {annotation_text}')

    annotation_text_list = []
    for v in range(len(annotation_text)):
        content = annotation_text[v].get_text().replace('\u3000','')
        if len(content) == 0:
            None
        else:
            annotation_text_list.append(content)

    def two_return_to_one_return(content:str): #改行コードを減らす
        content = content.replace('\n\n','\n')
        return content

    path = 'NOT_export/pywrite_test.xhtml'
    with open(path,'a', encoding='utf-8') as f: #w = 上書き a=追加
        f.write('\n')
        f.write('\t<h1>'+title+'</h1>\n')
        f.write('\t<h2>現代語訳</h2>\n')
        f.write('\t<p style="white-space:pre-line">'+two_return_to_one_return(modern_translation)+'\n\t</p>\n')
        f.write('\t<h2>原文</h2>\n')
        f.write('\t<p style="white-space:pre-line">'+two_return_to_one_return(original_text)+'\n\t</p>\n')
        f.write('\t<h2>注釈</h2>\n')

        for v in range(0,len(annotation_text_list),2): #2づつ
            f.write(f'\t<h4>{annotation_text_list[v]}・・・{annotation_text_list[v+1]}</h4>\n')

# 初期要素の書き込み
path = 'NOT_export/pywrite_test.xhtml'
with open(path,'w',encoding='utf-8') as f: #w = 上書き a=追加
    first_lines = [
        '<?xml version="1.0" encoding="UTF-8"?>\n'
        '<!DOCTYPE html>\n'
        '<html\n'
        '\txmlns="http://www.w3.org/1999/xhtml"\n'
        '\txmlns:epub="http://www.idpf.org/2007/ops"\n'
        '\txml:lang="ja"\n'
        '>\n'
        '\n'
        '<head>\n'
        '\t<meta charset="UTF-8"/>\n'
        '\t<title>徒然草本文</title>\n'
        '\t<link rel="stylesheet" type="text/css" href="../style/style.css"/>\n'
        '</head>\n'
        '\n'
        '<body>\n'
    ]
    f.writelines(first_lines)

# 真ん中
get_text_and_write_file("https://tsurezuregusa.com/jyo/")
# get_text_and_write_file("https://tsurezuregusa.com/001dan/")

# #url作成
for v in range(1,244):
    time.sleep(1)
    s = f'https://tsurezuregusa.com/{v:03}dan/'
    get_text_and_write_file(s)
    print(s)

get_text_and_write_file('https://tsurezuregusa.com/afterword/')

path = 'NOT_export/pywrite_test.xhtml'
with open(path,'a', encoding='utf-8') as f: #w = 上書き a=追加
#     # end
    f.write('</body>\n')
    f.write('</html>')

不要な要素を正規表現で削除

ファイルを作成してからvscodeを使い,いらない要素を削除します.

改行を見つける正規表現
pre-line">\n

注釈がない注釈
<h2>注釈</h2>\n(?!\t<h4>)

改行していて,空いているやつ
\n\n\t</p>

alt+Enterを押すことで,正規表現でマッチする要素を選択できます(vscode)

css

スマホだと限られたスペースで読みやすく,より多くの情報量を取りたい. そのため,余白が邪魔だったので,cssを書いて余白を詰めている.

html {
        -webkit-writing-mode: vertical-rl;
        -webkit-text-orientation: mixed;
        -epub-writing-mode: vertical-rl;
        -epub-text-orientation: mixed;
        writing-mode: vertical-rl;
        text-orientation: mixed;
}

.title {
        font-family: serif;
        text-align: center;
        padding-top: 2em;
}

.author {
        font-size: 1.5em;
        font-family: serif;
        text-align: center;
        padding-top: 1em;
}

p {
        font-size: 1em;
        font-family: serif;
        margin: 0px;
}

h1 {
        font-size: 1.5em;
        font-family: serif;
        margin-right: 1.5em;
        margin-left: 0.5em;
        padding: 0px;
}

h2 {
        margin: 0px;
}

h4 {
        margin-left: 0px;
        margin-right: 0px;
}

完成

読めればいいので,このくらいで完成にする. kindle徒然草のおもしろい訳を読めるようになったので,私の目的は達成された. この後するのであれば,目次の対応(navigation.xhtml),表紙の対応,配布するなら訳者への許可取りくらいであろうか. 人に見せる品質に到達していないので,私的利用にとどめたい.

Youtubeをズーム,拡大できるChrome拡張を作りました

chrome.google.com

 

 

プログラミングの動画を見るときに,文字が小さくて不便だったので,Youtubeの動画を拡大できるChrome拡張を作ってみました.

 

上を下みたいに拡大できます.

 

 

 

拡大の方法ですが,scaleという文字をドラッグして横に動かす方法になります(scrubberといいます).わからない場合は拡張機能ページのYoutubeリンクを見ていただけるとありがたいです.

(youtube zoom - YouTube)

 

scrubberというやつのデモ

https://masirof.github.io/jqueryScrubber/

 

なにかわからない点や不満やバグなどがあればコメントしていただけると,ありがたいです.

chrome.google.com

https://chrome.google.com/webstore/detail/youtube-zoom/bbafphllnkfgkcbilhekaooohoiabojh

クォータニオンでの回転とPython(ある座標に向かわせたい)

本記事の目的はある座標(ある方向)に回転させたい物体を回転させるプログラムを書くことです。副目的として数学を学ぶことが挙げられます。

本記事ではBlenderPythonを使用します。 Blender2.93 Python3.8.8

回転させたい物体にクォータニオンを使用すると回転軸と角度の4つのパラメーターで回転をさせることができます。

回転軸→外積を使って求める
角度→内積を使って求める
クォータニオン→回転軸と角度を使って求める

計算に手を出す前に,クォータニオンのイメージを想像するとわかりやすくなります。以下の動画には丁寧にわかりやすくイメージを見せてくれています。(33分47秒辺りから)

【Unity道場 博多スペシャル 2017】クォータニオン完全マスター youtu.be

クォータニオンを計算するのは

1.向かせたいベクトルと「上」方向のベクトルを取得
2.上記2つのベクトルとの外積を取る(これが回転軸となる)
3.上記2つのベクトルの角度を、内積を使って取得
4.これら情報を元に、回転用のクォータニオンを生成
5.生成したクォータニオンをオブジェクトに適用

という順番で進めていきます。 [Three.js] クォータニオンを使って任意の方向にオブジェクトを向ける - Qiita

1. 向かせたいベクトルと「上」方向のベクトルを取得

向かせたい座標は[2,3,4]とします。「向かせたいベクトル」を取得するためには,向かせたい座標から回転させたい対象の座標を引く必要があります。これをすることで原点から見た向かせたい座標を見ることができるからではと考えています(数学わからん)。ここでは回転させたい物体の座標を[1,1,1]とします。なので

 \displaystyle \begin{pmatrix} 2, 3, 4\end{pmatrix} -  \begin{pmatrix} 1, 1, 1\end{pmatrix} =  \begin{pmatrix} 1, 2, 3\end{pmatrix}

と表され,[1,2,3]が向かせたいベクトルだとわかります。

「上」方向のベクトルについては[0,1,0]など環境にあった「上」方向を使用します。今回はBlenderのオブジェクトであるアーマチュア(ボーン)の回転を計算したいので,アーマチュアのデフォルトの方向である[0,0,1]を使用しますBlenderではライトのオブジェクトなどのデフォルト方向は[0,0,-1]なため使用するオブジェクトに応じてデフォルトの方向を変更する必要があります。また適宜,各環境のデフォルト方向を割り当ててください。

2. 2つのベクトルとの外積を取る(これが回転軸となる)

numpyを使用するときはnp.cross()で外積を取れます。以下のページを参考にプログラムを書きました。 外積とは何か。ベクトルの外積の定義・意味・大きさについて|アタリマエ!

以下の式がaとbのベクトルの外積を求める式です。a×bが外積を表します。外積は計算する順番が違うと結果が違うことがあるため,順番に気をつけてください。aをデフォルトの方向のベクトル,bを向かせたいベクトルだとすると,

 \displaystyle \boldsymbol{a}=[a_{1}, a_{2}, a_{3}]
 \displaystyle \boldsymbol{b}=[b_{1}, b_{2}, b_{3} ]
 \displaystyle \boldsymbol{a} \times \boldsymbol{b} = \begin{pmatrix} a_{2}b_{3}-a_{3}b_{2}\\ a_{3}b_{1}-a_{1}b_{3}\\a_{1}b_{2}-a_{2}b_{1} \end{pmatrix} =  \begin{pmatrix} \lambda_{x}\\ 
 \lambda_{y}\\ \lambda_{z}\end{pmatrix}

実際に計算してみると以下のようになります。

 \displaystyle \boldsymbol{a}=[0,0,1]
 \displaystyle \boldsymbol{b}=[1, 2, 3]
 \displaystyle \boldsymbol{a} \times \boldsymbol{b} = \begin{pmatrix} 0\times3 - 1\times2 \\ 1\times1 - 0\times3 \\0\times2 - 0\times1 \end{pmatrix} = \begin{pmatrix} -2\\ 1\\ 0 \end{pmatrix}

正規化の話をするため,クォータニオンの式を表します。

 \displaystyle \boldsymbol{q} =\begin{pmatrix} x\\ y\\ z\\ w\\ \end{pmatrix}= \begin{pmatrix} \lambda_{x}\sin\frac{\theta}{2}\\ \lambda_{y}\sin\frac{\theta}{2}\\ \lambda_{z}\sin\frac{\theta}{2}\\ \cos\frac{\theta}{2} \end{pmatrix}

外積をして求められる数値はクォータニオン式の中にある

 \displaystyle \lambda_{x}, \lambda_{y}, \lambda_{z}

に当てはまります。
この3つの数値は正規化しなければいけないという条件があります。 normalize(正規化)する条件は以下のとおりです。

 \displaystyle  \lambda_{x}^2+\lambda_{y}^2+\lambda_{z}^2=1

にならなくてはいけないというルールがあるので正規化します。正規化することによって各座標の2乗の総和を1にすることができます。

外積の結果を正規化する方法は以下の数式で表され

 \begin{pmatrix} \lambda_{x} 
 \lambda_{y} \lambda_{z} \end{pmatrix} /  \displaystyle \sqrt{\sum_{k=1}^{n}}k^2 = \begin{pmatrix} \lambda_{x}  \lambda_{y} \lambda_{z}\end{pmatrix} /  \displaystyle \sqrt{\lambda_{x}^2 + \lambda_{y}^2 + \lambda_{z}^2 }

実際に計算してみると以下のようになります。

 \displaystyle \begin{pmatrix} -2, 1 , 0 \end{pmatrix}  / \sqrt{-2^2 + 1^2 + 0^2} = \begin{pmatrix} -2, 1 , 0 \end{pmatrix}  /  2.23606797749979 \\= \begin{pmatrix} -0.89442719, 0.4472136, 0\end{pmatrix}

Pythonで書くと以下のようになります。

import numpy as np
o=np.array([1,1,1]) #回転させたい物体の座標
point_p = np.array([2,3,4]) #向かせたい座標
p_from_o = point_p - o #向かせたいベクトル
print(f"p_from_o {p_from_o}")
up_vector = np.array([0,0,1]) #blenderのアーマチュアのデフォルト
cross_product = np.array([])

def normalize(v):
 # numpyのnormを使用して計算
    norm = np.linalg.norm(v)
    print(f"norm {norm}")

    # numpyのnorm()を使わず計算
    norm = np.sqrt(sum(v**2))
    print(f"norm {norm}")

    if norm==0: #ゼロ除算を防ぐ
        return v

    return v / norm

# up_vectorが[0,0,-1]で,p_from_oが[1,2,3]
# numpyのnp.cross()を使わず外積計算
cross_product = np.append(cross_product,[up_vector[1]*p_from_o[2] - up_vector[2]*p_from_o[1], up_vector[2]*p_from_o[0] - up_vector[0]*p_from_o[2], up_vector[0]*p_from_o[1] - up_vector[1]*p_from_o[0]])
cross_product = normalize(cross_product)
print(f"cross_product {cross_product}")

# numpyで外積計算
cross_product = np.cross(up_vector, p_from_o)
cross_product = normalize(cross_product)
print(f"cross_product {cross_product}")

np.cross(up_vector, p_from_o)とnp.cross(p_from_o, up_vector)では結果が違うため注意が必要です。 このプログラムはBlender Pythonで方向ベクトルで表される方向をクォータニオンを使って実装する - Qiita を参考にしています。 プログラムを使用する場合はnormを使用する方か,使用しない方,どちらかを選んで使用してください

3. 2つのベクトルの角度を、内積を使って取得

以下のページを参考にプログラムを書きました。内積とは何なのか?ベクトルの内積の2つの求め方とその活用法|アタリマエ!

向かせたいベクトルがまだ正規化されていない場合内積は以下の式で計算できます。
 \vec{a}\cdot\vec{b}=\|a\|\|b\|\cos\theta\displaystyle

上の式を式変形することでcosθを以下の式で計算することができます。

 \displaystyle \cos\theta = \dfrac{\vec{a}\cdot\vec{b}}{\|a\|\|b\|}

cosθからθ(角度)を取得するためにarccosを使用します。

 \displaystyle \theta = \arccos \cos \theta

コードでは以下の式を使用してベクトルaとベクトルbの内積を計算します。

 \displaystyle \vec{a}\cdot\vec{b}=a_{1}b_{1} + a_{2}b_{2} + a_{3}b_{3}

計算してみます。ベクトルaをデフォルトの方向のベクトル,ベクトルbを正規化されていない向かせたいベクトルとします。radはラジアンの意味です。プログラムを実行するとラジアンが返されるため,ここでの計算結果もラジアン表記にしています。

 \displaystyle \vec{a} =[0,0,1 ]
 \displaystyle \vec{b} =[1,2,3 ]
 \displaystyle \vec{a}\cdot\vec{b}=0\times1+0\times2+1\times3 = 3

 \displaystyle 3 = \|a\|\|b\|\cos\theta\\ \quad= \sqrt{0^2+0^2+1^2} \times \sqrt{1^2+2^2+3^2} \times \cos\theta \\
\quad= 3.7416573867739413 \times \cos\theta

 \displaystyle \cos\theta = \dfrac{3
}{3.7416573867739413}

 \displaystyle \theta = \arccos(\dfrac{3
}{3.7416573867739413}) = \arccos(0.8017837257372732) \\= 0.6405223126794245rad


向かせたいベクトルが正規化されている場合内積は計算してみると以下のようになります。
 \displaystyle \theta = \arccos (\vec{a}\cdot\vec{b}) = \arccos(a_{1}b_{1} + a_{2}b_{2} + a_{3}b_{3})


ベクトルaを正規化された向かせたいベクトルとします。
ベクトルbをデフォルトの方向のベクトルとします。
radはラジアンの意味です。プログラムを実行するとラジアンが返されるため,ここでの計算結果もラジアン表記にしています。

 \displaystyle \vec{a} =[0, 0, 1 ]
 \displaystyle \vec{b} = [0.26726124, 0.53452248, 0.80178373 ]

 \displaystyle \theta = \arccos (\vec{a}\cdot\vec{b})\\
=\arccos(0\times0.26726124 + 0\times0.53452248 + 1\times0.80178373)\\ = \arccos(0.80178373) = 0.6405223055465182rad

向かせたい座標へのベクトルを正規化しても,正規化しなくても0.6405223まで一致しているので,好きな方を使うといいと思います。可読性を考えると正規化されたほうを選んだほうがいいと思います。

inner_product = np.array([])

# numpyのnp.dotやnormを使わず内積計算(正規化されている場合もされていない場合も使える)
inner_product=np.append(inner_product, [up_vector[0]*p_from_o[0] + up_vector[1]*p_from_o[1] + up_vector[2]*p_from_o[2]])
print(f"inner_product {inner_product}")
norm_up_vector_p = np.sqrt(sum(up_vector**2)) * np.sqrt(sum(p_from_o**2))
print(f"norm_up_vector_p {norm_up_vector_p}")
cos_theta = inner_product / norm_up_vector_p
print(f"cos_theta {cos_theta}")
theta = np.arccos(cos_theta) #thetaはラジアンで返ってくる
print(f"theta {theta}")

# numpyで内積計算(正規化されている場合もされていない場合も使える)
inner_product = np.dot(up_vector, p_from_o)
print(f"inner_product {inner_product}")
norm_up_vector_p = np.linalg.norm(up_vector) * np.linalg.norm(p_from_o)
print(f"norm_up_vector_p {norm_up_vector_p}")
cos_theta = inner_product / norm_up_vector_p
print(f"cos_theta {cos_theta}")
theta = np.arccos(cos_theta) #thetaはラジアンで返ってくる
print(f"theta {theta}")

#上2つをまとめて短く書いたもの(正規化されていないと使えない)
up_vector = normalize(up_vector)
p_from_o = normalize(p_from_o)
theta = np.arccos(np.dot(up_vector, p_from_o))
print(f"theta {theta}")

4. これら情報を元に、回転用のクォータニオンを生成

クォータニオンは以下の式で表します。

 \displaystyle \boldsymbol{q} =\begin{pmatrix} x\\ y\\ z\\ w\\ \end{pmatrix}= \begin{pmatrix} \lambda_{x}\sin\frac{\theta}{2}\\ \lambda_{y}\sin\frac{\theta}{2}\\ \lambda_{z}\sin\frac{\theta}{2}\\ \cos\frac{\theta}{2} \end{pmatrix}

 \displaystyle (\lambda_{x} \lambda_{y} \lambda_{z}) = (−0.89442719, 0.4472136, 0)

 \displaystyle \theta = 0.6405223055465182rad

 \displaystyle \boldsymbol{q} =\begin{pmatrix} x\\ y\\ z\\ w\\ \end{pmatrix}= \begin{pmatrix} −0.89442719\times\sin(\frac{0.6405223055465182rad}{2})\\ 0.4472136\times\sin(\frac{0.6405223055465182rad}{2})\\ 0\times\sin(\frac{0.6405223055465182rad}{2})\\ \cos\frac{0.6405223055465182rad}{2} \end{pmatrix}\\
= \begin{pmatrix}-0.2815785997243485\\ 0.1407893014362465\\ 0\\ 0.9491532357844017\end{pmatrix}

quaternion = np.array([])
rad_theta_divide2 = theta/2 #ラジアンで返ってくるnp.cosはラジアンを入れる
print(f"rad_theta_divide2 {rad_theta_divide2}")

np.set_printoptions(suppress=True) #指数表記を禁止
#w,x,y,zの順
quaternion = np.append(quaternion, [np.cos(rad_theta_divide2),
                                    cross_product[0]*np.sin(rad_theta_divide2),
                                    cross_product[1]*np.sin(rad_theta_divide2),
                                    cross_product[2]*np.sin(rad_theta_divide2)])
print(f"quaternion {quaternion}")

5. 生成したクォータニオンをオブジェクトに適用

ここは各自で回転させたいオブジェクトにクォータニオンに適用してください。(無慈悲)

プログラムの全体

import numpy as np

# 回転させたい物体の座標
o = np.array([1, 1, 1])
# 向かせたい座標
p = np.array([2, 3, 4])
p_from_o = p - o
print(f"p_from_o {p_from_o}")

up_vector = np.array([0, 0, 1])  # blenderのアーマチュアのデフォルト(デフォルト方向)

# 正規化,配列のリストを1を最大で正規化
def normalize(v):
    # norm = np.linalg.norm(v)
    # print(f"norm {norm}")
    # 同じ意味
    norm = np.sqrt(sum(v**2))
    print(f"normalize(norm) {norm}")
    if norm == 0:  # ゼロ除算を防ぐ
        return v

    return v / norm

cross_product = np.array([])  # 外積用のリスト

# numpyを使わず外積計算
# cross_product = np.append(cross_product, [up_vector[1]*p_from_o[2] - up_vector[2]*p_from_o[1], up_vector[2]
#                           * p_from_o[0] - up_vector[0]*p_from_o[2], up_vector[0]*p_from_o[1] - up_vector[1]*p_from_o[0]])
# print(f"cross_product {cross_product}")
# cross_product = normalize(cross_product)
# print(f"normalize(cross_product) {cross_product}")

# numpyで外積計算
cross_product = np.cross(up_vector, p_from_o)
cross_product = normalize(cross_product)
print(f"cross_product {cross_product}")


inner_product = np.array([])

# 内積から角度を出す

# # numpyのnp.dotやnormを使わず内積計算(正規化されている場合もされていない場合も使える)
# print("numpyを使わず内積計算")
# print(f"up_vector {up_vector}")
# print(f"p_from_o {p_from_o}")
# inner_product=np.append(inner_product, [up_vector[0]*p_from_o[0] + up_vector[1]*p_from_o[1] + up_vector[2]*p_from_o[2]])
# print(f"inner_product {inner_product}")
# norm_up_vector_p = np.sqrt(sum(up_vector**2)) * np.sqrt(sum(p_from_o**2))
# print(f"norm_up_vector_p {norm_up_vector_p}")
# cos_theta = inner_product / norm_up_vector_p
# print(f"cos_theta {cos_theta}")
# theta = np.arccos(cos_theta)
# print(f"theta {theta}")

# # numpyで内積計算(正規化されている場合もされていない場合も使える)
# print("numpyで内積計算")
# inner_product = np.dot(up_vector,p_from_o)
# print(f"inner_product {inner_product}")
# norm_up_vector_p = np.linalg.norm(up_vector) * np.linalg.norm(p_from_o)
# print(f"norm_up_vector_p {norm_up_vector_p}")
# cos_theta = inner_product / norm_up_vector_p
# print(f"cos_theta {cos_theta}")
# theta = np.arccos(cos_theta)
# print(f"theta {theta}")

# 上2つをまとめて短く書いたもの(正規化されていないと使えない)
up_vector = normalize(up_vector)
p_from_o = normalize(p_from_o)
print("上記をまとめて短く書いたもの")
theta = np.arccos(np.dot(up_vector, p_from_o))  # thetaはラジアンで返ってくる
print(f"theta {theta}")


# クォータニオンを求める
quaternion = np.array([])
rad_theta_divide2 = theta/2  # thetaはラジアンで返すためラジアンで変換をしない
print(f"rad_theta_divide2 {rad_theta_divide2}")
np.set_printoptions(suppress=True)  # 指数表記を禁止
quaternion = np.append(quaternion, [np.cos(rad_theta_divide2),
                                    cross_product[0]*np.sin(rad_theta_divide2),
                                    cross_product[1]*np.sin(rad_theta_divide2),
                                    cross_product[2]*np.sin(rad_theta_divide2)])
# w,x,y,z
print(f"quaternion {quaternion}")

まとめ

Pythonとnumpyをフル活用することでかんたんにクォータニオンを求めることが可能。クォータニオンは回転軸と角度を出すことで求められる。回転軸は外積で,角度は内積で出すことができる。クォータニオンを出してオブジェクトに適用して回転!回転!

参考

youtu.be

qiita.com

qiita.com

qiita.com