ミノムシの日記

気まぐれでブログ投稿してます。アニメ見たり音楽聞くのが好きです

for文との格闘

タイトルの箇所
戻る(一つ前の曲を再生する)


えー、僕は最近自作音楽プレイヤーを作ってます

音楽プレイヤーと言ってもとても単純なやつです

コマンドライン引数からファイルパス取得

(①で取得したパスがファイルだった場合)

②そのまま再生

(①で取得したパスがディレクトリだった場合)

②glob.glob()でその中身を取得

③②の戻り値をfor文で回して順に再生


……というようなプログラムです

しかし、これだけではホントに単純過ぎるのでせめて「曲をスキップ・戻る、ランダム再生」くらいの機能は付けようと思いました

曲をスキップ

これは簡単にできました

#coding: utf-8
import pygame
import os
from mutagen.mp3 import MP3
from timeout_decorator import timeout, TimeoutError

def main(argv):
    if os.path.isfile(argv[1]):
        play(argv[1])
    else:
        play(glob.glob(os.path.join(*[argv[1], '*'])))

def play(path):
    for f in path:
        pygame.mixer.init()
        pygame.mixer.music.load(f)
        length = MP3(f).info.length
        pygame.mixer.music.play()
        result settings(length)
        if result == None:
            pygame.mixer.music.stop()
            continue

def settings(sec):
    @timeout(sec)
    def option():
        while True:
            opt = sys.stdin.read(1)
            if opt == 'n':
                return
    try:
        return option()
    except TimeoutError:
        return

if __name__ == '__main__':
    main(sys.argv[1])

音声を再生したあと、setting関数を呼び出します。
そしてoption関数のタイムアウト時間を音源の長さと同じに設定して、option関数を呼び出します

nが入力されたら現在の曲をスキップして次の曲を流します

音源が再生し終わった(つまりoption関数がタイムアウトした)らまた次の音声を再生します。

戻る(一つ前の曲を再生する)

これにつまずきました

だってfor文中に要素の取り出しを一個前に戻すなんてコード知りませんし調べても出てこないんですもん

諦めそうになった

かれこれ30分この問題と格闘した結果……

#coding: utf-8
import pygame
import os
from mutagen.mp3 import MP3
from timeout_decorator import timeout, TimeoutError


def main(argv):
    if os.path.isfile(argv[1]):
        play(argv[1])
    else:
        play(glob.glob(os.path.join(*[argv[1], '*'])))

def play(path, num):
    for n, f in enumerate(path):
        if n<num:
            continue
        pygame.mixer.init()
        pygame.mixer.music.load(f)
        length = MP3(f).info.length
        pygame.mixer.music.play()
        result = settings(length)
        if result == None:
            pygame.mixer.music.stop()
        elif result == 'back':
            pygame.mixer.music.stop()
            play(path, n-1)

def settings(sec):
    @timeout(sec)
    def option():
        opt = sys.stdin.read(1)
        if opt == 'n':
            return
        elif opt == 'b':
            return 'back'
    try:
        return option()
    except TimeoutError:
        return
if __name__ == '__main__':
    main(sys.argv[1], 0)

play関数の引数を一つ増やしました

こうすることでインデックスがnum未満のやつはスキップさせることができました(最初はnumの値が0なので何もスキップしない)

これを早く思いつかなかった自分を殴りたい

ランダム再生

#coding: utf-8
import pygame
import os
import random
from mutagen.mp3 import MP3
from timeout_decorator import timeout, TimeoutError

def main(argv):
    if os.path.isfile(argv[1]):
        play(argv[1])
    else:
        play(random.shuffle(glob.glob(os.path.join(*[argv[1], '*']))))

def play(path, num):
    for n, f in enumerate(path):
        if n<num:
            continue
        pygame.mixer.init()
        pygame.mixer.music.load(f)
        length = MP3(f).info.length
        pygame.mixer.music.play()
        result = settings(length)
        if result == None:
            pygame.mixer.music.stop()
        elif result == 'back':
            pygame.mixer.music.stop()
            play(path, n-1)

def settings(sec):
    @timeout(sec)
    def option():
        opt = sys.stdin.read(1)
        if opt == 'n':
            return
        elif opt == 'b':
            return 'back'
    try:
        return option()
    except TimeoutError:
        return
if __name__ == '__main__':
    main(sys.argv[1], 0)

play関数に渡すリストをシャッフルしてみました

最初はrandom.randintでインデックス番号生成しようかなぁなんて考えてたのですが、調べてる途中random.shuffle関数様と出会いました

このお方のおかげでランダム再生の実装が簡単に終わった

おまけ

「いちいちn押してEnter押すの面倒くさいなー」と思ってEnter押さなくても勝手に標準入力受け取ってくれる魔法のモジュールを探していました

そしたら見つかりました、「termios」というものを!!

#coding: utf-8
import pygame
import os
import random
import termios
from mutagen.mp3 import MP3
from timeout_decorator import timeout, TimeoutError

def main(argv):
    if os.path.isfile(argv[1]):
        play(argv[1])
    else:
        play(random.shuffle(glob.glob(os.path.join(*[argv[1], '*']))))

def play(path, num):
    for n, f in enumerate(path):
        if n<num:
            continue
        pygame.mixer.init()
        pygame.mixer.music.load(f)
        length = MP3(f).info.length
        pygame.mixer.music.play()
        result = settings(length)
        if result == None:
            pygame.mixer.music.stop()
        elif result == 'back':
            pygame.mixer.music.stop()
            play(path, n-1)

def settings(sec):
    @timeout(sec)
    def option():
        fd = sys.stdin.fileno()
        old = termios.tcgetattr(fd)
        new = termios.tcgetattr(fd)
        new[3] &= ~termios.ICANON
        new[3] &= ~termios.ECHO
        try:
            termios.tcsetattr(fd, termios.TCSANOW, new)
            opt = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSANOW, old)
        if opt == 'n':
            return
        elif opt == 'b':
            return 'back'
    try:
        return option()
    except TimeoutError:
        return
if __name__ == '__main__':
    main(sys.argv[1], 0)

どうやらtermiosを使って設定を弄るようです
入力も出力されないっぽい
これはいいねぇ

参考:
https://qiita.com/tortuepin/items/9ede6ca603ddc74f91ba

あと追加したい機能

  • プレイリスト表示(簡単そう)
  • ループ再生
  • 一時停止

ただソースコード置くだけみたいな記事になってしまってすみません

エイプリルフールについて調べてみた

この記事の執筆日は4月1日、エイプリルフールです。
TwitterのTLを見ても嘘で溢れかえってました。
そんな中「エイプリルフールで嘘をついていいのは午前中まで」というツイートを見かけました。これは初耳、知らなかったと思い他にも知らなかったことがあるんじゃないかと今回エイプリルフールについて色々と調べてみました。

エイプリルフールの語源

エイプリルフールの語源については、諸説あるようです。
  • かつて、フランスでは3月25日に新年を迎え、4月1日まで新年のお祭りをしていたが、16世紀にシャルル9世が1月1日を新年とするグレゴリオ暦を採用すると、これに反発した人々が4月1日を「嘘の新年」として馬鹿騒ぎをした。この騒ぎに怒ったシャルル9世が人々を処刑したため、抗議と追悼の意を込めて、4月1日に「嘘の新年」を盛大に行うようになった。
  • キリストの命日にあたるため、ユダの裏切りを忘れないために設けられた。
  • インドの仏教徒春分の日から3月末まで修行を行う。せっかく修業をしても、4月1日になると修行が嘘だったかのように俗人に戻ってしまうことから、4月1日を「揶揄節」(やゆせつ)としてからかった。
(引用元 https://allabout.co.jp/gm/gc/220781/)

↑この引用元のサイトを見て知ったのですが、エイプリルフールって直訳すると「4月馬鹿」なんですね〜。


「嘘は午前中だけ」ルール

調べてみたところこれはイギリスのオークアップルデーが元になったものらしいです。
オークアップルデーとは、騎士たちがオークの実を纏って王様に忠誠を誓う儀式なのですが、「午後は付けなくていい」というルールがあり、それがエイプリルフールに影響を及ぼしたのだそうで
そして午後にネタバラシをするそうです。

エイプリルフールのルール

ちなみに「嘘をついていいのは午前中だけ」以外に、エイプリルフールのルールとしてはこんなのがあるらしい
  • 他人を傷付ける嘘はつかない
  • 嘘をつかれても笑って許す

当たり前のことですね

ついた嘘は叶わない

更に調べたところ、何と「エイプリルフールについた嘘は叶わない」ということだそうです。
しかし、これにも「その嘘をついた年1年は叶わない」というのと、「一生叶わない」という説があるそうです。

あれ、彼氏(彼女)出来たってツイートしてた人が居たような…………

知らないことが結構あった

エイプリルフールについて調べてみたら、結構面白かったです。特に「ついた嘘は叶わない」というのは驚きでした。
次からエイプリルフールに嘘を付くときは気をつけます

おまけ

エイプリルフールに嘘をついてはいけない(又はそもそも行ってない)国を紹介します。

中国

エイプリルフールに嘘つくのは禁止らしい

フィリピン

そもそもあまり浸透してない

インドネシア

こちらも中国と同様に嘘をついてはいけないらしい

参考

https://ameno-ato.com/3660.html
https://allabout.co.jp/gm/gc/220781/

pythonで音楽プレイヤーもどきを作った話

ある日ふと「自作の音楽プレイヤー作れないかなぁ」と思い、音楽プレイヤーもどきを作ることにしました。
今回こちらの機能を実装したいと思います。 

  • 音源を再生する
  • 再生途中で再生を止める(一時停止なども含め)
  • 連続再生

そして理想の完成形
1. キーボード入力からディレクトリのパスを取得
        ↓
2. 1で取得したディレクトリの中身を表示し、再生する曲を選択し再生
        ↓
3.その後はオプションなどなど……

音源を再生する

pythonで音源を再生するモジュールを探したところ色々出てきたのですが、今回はpygameというモジュールを使っていきます。
pygameはpipコマンドでインストールできます


python -m pip install pygame

pygameの機能は以下の通り(今回使うであろうもの)

  • pygame.mixer.init() pygameを初期化
  • pygame.music.load() 音源読み込み
  • pygame.mixer.music.play 再生開始
  • pygame.mixer.music.stop() 再生停止
  • pygame.mixer.music.fadeout() 徐々に音量を小さくして再生を止める。引数には何秒かけて止めるかをミリ単位で指定する
  • pygame.mixer.music.pause() 一時停止
  • pygame.mixer.music.unpause() 再生再開
そしてプログラムがこちら


import pygame
dirpass = input()
dir = os.path.listdir(dirpass)
for (n, i) in enumerate(dir):
n+=1
print(n, i)
mun = input("再生する曲の番号を入力してください。")
num = int(num)+1
file = dir[num]
pygame.mixer.init()
pygame.mixer.load(file)
pygame.mixer.music.play(1)
input()

pygame.mixer.music.play()で音源を再生した後、にも無いとすぐ再生が止まっちゃうので、input()で処理を止めておきます。
enumerate関数は、リストの中身だけでなく、リストの位置も取得できるので便利です。

好きなところで再生を止める

まずはs、またはstopと入力したら再生を止める機能を追加



import pygame
mode = "p"
dirpass = input()
dir = os.path.listdir(dirpass)
for (n, i) in enumerate(dir):
n+=1
print(n, i)
mun = input("再生する曲の番号を入力してください。")
num = int(num)+1
file = dir[num]
pygame.mixer.init()
pygame.mixer.load(file)
pygame.mixer.music.play(1)
while mode != "s" or mode != "stop":
mode = input()
pygame.mixer.music.fadeout(0.5)

NameError回避のため最初にmodeに適当な値を入れます。
sかstopが入力されると再生を停止します(0.5ってありますがここは好みです)

連続再生

連続再生機能はさっきのコードに追記するだけ………とはなりません。
さっきまでのコードだとinput()のところで処理が止まってしまい、処理が進まないからです。
そこで「python タイムアウト機能を付ける方法」とggったところ、自作関数にはタイムアウト機能を付けることができるということが分かりました。
なのでコードを改良したものがこちら



from timeout_decorator import timeout, TimeoutError
from mutagen.mp3 import MP3
import pygame
import time
import sys
def dirread():
dirpass = input()
dir = os.path.listdir(dirpass)
for (n, i) in enumerate(dir):
n+=1
print(n, i)
mun = input("再生する曲の番号を入力してください。")
num = int(num)+1
return (num, dir)
def play():
file = dir[num]
pygame.mixer.init()
pygame.mixer.load(file)
sec = MP3(file).info.length
pygame.mixer.music.play()
return setting(sec)
def setting(timeout_sec):
@timeout(timeout_sec)
def wate():
while True:
mode = input()
if mode == "s" or mode == "stop":
break
return mode
try:
return wate()
except TimeoutError:
return None
if __name__ == "__main__":
num, dir = dirread()
while True:
if play() == "s" or "stop":
pygame.mixer.music.fadeout(0.5):
sys.exit()
else:
time.sleep(0.25)
pygame.mixer.music.stop()
num+=1

timeout_decoratorとmutagenもpipコマンドでインストールできます


python -m pip install mutagen timeout_decorator

mutagenはID3タグを読み込むモジュールです。
mutagenで音源の長さを取得し、その長さ分キーボード入力を待つことで、連続再生ができるようになりました。

完成形



from timeout_decorator import timeout, TimeoutError
from mutagen.mp3 import MP3
import pygame
import time
import sys
def dirread():
dirpass = input()
dir = os.path.listdir(dirpass)
for (n, i) in enumerate(dir):
n+=1
print(n, i)
mun = input("再生する曲の番号を入力してください。")
num = int(num)+1
file = dir[num]
return (num, file)
def play():
pygame.mixer.init()
pygame.mixer.load(file)
sec = MP3(file).info.length
pygame.mixer.music.play()
return setting(sec)
def setting(timeout_sec):
@timeout(timeout_sec)
def wate():
while True:
mode = input()
if mode == "s" or mode == "stop":
break
return mode
elif mode == "pause":
pygame.mixer.music.pause()
print("一時停止しました"+"\n"+"再開する場合はxキーを押してください")
for event in pygame.event.get()
if event.type == KEYDOWN:
if event.key == K_x:
pygame.mixer.music.unpause()
break
try:
return wate()
except TimeoutError:
return None
if __name__ == "__main__":
num, file = dirread()
while True:
if play() == "s" or "stop":
pygame.mixer.music.fadeout(0.5):
sys.exit()
else:
time.sleep(0.25)
num+=1

結局はこんな感じになりました。
まだまだ機能は追加できると思うのですが、音楽プレイヤーもどきには十分だと思います。

YouTubeが鯖落ちした話

2020/12/14の20:30、その時は突然訪れました。

 

YouTubeが見れなくなる

 

まあ正確に言うとGoogle関連のサービスがほぼすべて使えなくなりました。

 

そしてYouTubeが見れなくなった影響からか何故かニコニコ動画まで鯖落ちする始末……

 

Twitter上では、YouTubeが見れなくなったためニコニコ動画に人が流れたのではないという考えのツイートが多数ありました。

 

これはボジティブに考えてみれば大勢の人が第一はYouTube、その次はニコニコ動画と考えている人が多いのではないでしょうか?

 

現に22:00現在(執筆日時)ニコニコというワードがトレンド5位にランクインしています。

 

最も、ニコニコ動画鯖落ちした原因はサーバーの強度が脆いからだとは思います……

 

ドワンゴ、頑張れ!(いつも見てまーす)

腰を痛めた話

今、めちゃくちゃ腰が痛いんです……。

月曜日(祝日)に縄跳び跳んだあとから痛くなりました。これって縄跳びしたのが悪いんですかね……?
お陰様で今週はずっと部活を休んできました。痛すぎて部活どころではない()。

さらに今丁度体育の授業で柔道をやっているのですが、もちろん出来る訳がない。当然見学(柔道着は着た)

裸足で見学したので足が冷たかった。
もはや床が僕を殺しにかかっているもんだと思ってました。

痛みが発症した月曜日の夜は腰にサロンパスを貼って寝ました。

しかし一向に治らない。

なのでGoogle先生に「腰の痛み 治し方」と質問しました。するとストレッチがいいとかツボ押しがいいという記事がヒット、それを試してみました。

最近少し良くなってきた感じがします。

サロンパスに感謝感謝

ニワトリが進化!?(マイクラ)

↑はい、こんな風にニワトリがエンドラに変身しちゃいました!
……正確にはコマンドで変身したように見せてるだけですけどね……

今回はこの方法を説明します

・作成

手順1 名札に名前を付ける
まず金床で名札に「エンドラ」と付けて下さい。

手順2 コマンドブロックの設定
コマンドブロックを縦に3つ繋げて並べます。(矢印の向きは全て上向きにする)

f:id:mino3855:20201019183653j:plain

1番のコマンドブロックは「反復/無条件/リピート」と設定して下さい。残りの2.3番のコマンドブロックは「チェーン/条件付き/リピート」と設定して下さい。 

1番のコマンドブロックには、「execute @e[name="エンドラ"] ^^^ summon ender_doragon ^^^」と入力して下さい。

2番のコマンドブロックには、「tp @e[name="エンドラ"] ^^-100^」

3番のコマンドブロックには、「kill @e[name="エンドラ"]」と入力して下さい。

これで完了です。

あとは「エンドラ」と付けた名札をニワトリに付けるだけです。(一応どのモブでも反応する)


・応用編

このように少し改良すればどのモブにでも変身させることができます。

作り方は、「作成」のところの赤文字の部分を指定のモブの名前に変更するだけです。

ドット絵をまとめた

僕が過去に作ったドット絵を少しまとめてみました

f:id:mino3855:20200927113458j:plain
↑ソードカービィ
作ってみたら色が全体的に渋くなった……

f:id:mino3855:20200927113546j:plain
ピカチュウ
カワイイ

f:id:mino3855:20200927113607j:plain
メタナイト
作るの大変でした

f:id:mino3855:20200927113631j:plain
↑アイスカービィ
クオリティが高くなったって言われた

f:id:mino3855:20200927113656j:plain
クリボー
クリボーは栗じゃなくてしいたけらしいです

f:id:mino3855:20200927113716j:plain
↑クリーパー(パーカーver)
アイコンにしたかったから作った

f:id:mino3855:20200927113747j:plain
↑トトロ
あのジブリのやつです

f:id:mino3855:20200927113816j:plain
↑サンズ
うわァァァァァァァァァ!(トラウマ)

f:id:mino3855:20200927114732j:plain
ボム兵
フォロワーさんからのリクエス

f:id:mino3855:20200927125509j:plain
↑トリエル
バタースコッチパイ食べたい()

f:id:mino3855:20200927125628j:plain
↑しずえさん
カワイイ(二度目)

f:id:mino3855:20200927125758j:plain
ミミッキュ
ピカチュウのパクr…(((((

f:id:mino3855:20200927125831j:plain
アルフィー
オタクオタクオタク

f:id:mino3855:20200927125845j:plain
↑スパイダーカービィ
スパイダーマン(?)

f:id:mino3855:20200927125919j:plain
↑ニンジャカービィ
カッコいい

f:id:mino3855:20200927125950j:plain
イーブイ
犬(((((