cdの'.cda'をMP3としてPCに取り込む

 CDのCDAファイル(インデックスファイル[.cda」/.cdda])をMP3としてPCに取り込む

■fre:ac (Free Audio Converter)の利用





■ファイル名を一括で変更(Windows、PowerShellを使用)

(1) フォルダを指定してPowerShellを開く。
(2) 対象ファイルがあるフォルダで Shift + 右クリック を押し、「PowerShell ウィンドウをここで開く」を選択。
(3) 以下のコマンドを入力。
$i = 1; Get-ChildItem -Filter "*.mp3" | Sort-Object Name | ForEach-Object {
    Rename-Item $_ -NewName ("Track" + $i.ToString("00") + ".mp3"); $i++
}

[コマンドの説明]
・Get-ChildItem -Filter "*.mp3": フォルダ内の .mp3 ファイルを取得。
・Sort-Object Name: 名前順にソート。
・Rename-Item: ファイルを Track01.mp3, Track02.mp3 ,...のようにリネームされる。

Windows PowerShell/PowerShell 7.4.6

●下記の記述は自分用の覚書です。
PowerShellを利用する場合は、'PowerShell'がよくわかる人に確認するようにしましょう。

(1) windows10で、任意のフォルダーの中から、'Windows PowerShell' を開く

・エクスプローラーで任意のフォルダーを開く。
・そのフォルダー内の空白部分をShiftキーを押しながら右クリック。
・表示されるメニューから「PowerShell ウィンドウをここで開く」を選択。
私の環境では'Windows PowerShell' が開きます。

PS > $PSVersionTable.PSVersion   <- PowerShellのバージョンを表示する

Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      19041  5247

PS > pwsh       <-PowerShell 7.xを起動[PowerShell-7.4.6-win-x64.msiをinstall)
PowerShell 7.4.6
PS >

現在の PowerShell 7 セッションを終了(exitコマンド)すると、
元の'Windows PowerShell' に戻ります。

PowerShell 7.4.6
PS > exit

PS > $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      19041  5247

(2) コマンドプロンプトを立ち上げた後、 'pwsh'コマンドでPowerShell 7.xを立ち上げる

Microsoft Windows [Version 10.0.19045.5247]
(c) Microsoft Corporation. All rights reserved.

>pwsh
PowerShell 7.4.6
PS >

現在の PowerShell 7 セッションを終了すると、
元の'コマンドプロンプト'に戻ります。

>pwsh
PowerShell 7.4.6
PS > exit

>

■注意:
(1)の「私の環境では'Windows PowerShell' が開きます。」に関連して
ここでの操作でPowerShell 7.4.6を直接開くような方法もあると思いますが、PowerShell に不慣れな私には無理でした。
PowerShell に不慣れな場合は深入りしないのが安全です。

PDFファイルのページサイズを調べる/横長のページを左右に分割し、それぞれ別のPDFに保存(python)

■PDFファイルのページサイズを調べる(python)

#get-pdf-page-sizes.py
import fitz  # PyMuPDFをインポート

def get_pdf_page_sizes(pdf_path):
    doc = fitz.open(pdf_path)  # PDFを開く
    for page_number, page in enumerate(doc, start=1):
        rect = page.rect  # ページの矩形サイズ
        print(f"ページ {page_number}: 幅={rect.width} ポイント, 高さ={rect.height} ポイント")

# 使用例
get_pdf_page_sizes("sample.pdf")

>python pdf_page_sizes.py
ページ 1: 幅=842.0 ポイント, 高さ=595.0 ポイント

842/72*2.54 = 29.7cm
595/72*2.54 = 21.1cm

・Adobe Acrobat /メニュー/文書のプロパティ/ページサイズ
からも知ることができる。297×210mm

・A4サイズの場合:
幅 ≈ 595.276 ポイント(約 8.27インチ)
高さ ≈ 841.890 ポイント(約 11.69インチ)

■以下のコードは、横長のページを左右に分割し、それぞれ別のPDFに保存します。

#split-pdf-vertically.py
import fitz  # PyMuPDFをインポート

def split_pdf_vertically(input_pdf, output_pdf_left, output_pdf_right):
    # 元のPDFを開く
    doc = fitz.open(input_pdf)
    # 左右分割用の新しいPDFを作成
    left_pages = fitz.open()
    right_pages = fitz.open()

    for page in doc:
        rect = page.rect  # ページ全体のサイズ
        width = rect.width  # 幅
        height = rect.height  # 高さ

        # 左半分の矩形領域
        left_rect = fitz.Rect(rect.x0, rect.y0, rect.x0 + width / 2, rect.y1)
        # 右半分の矩形領域
        right_rect = fitz.Rect(rect.x0 + width / 2, rect.y0, rect.x1, rect.y1)

        # 左半分を新しいページに追加
        left_page = left_pages.new_page(width=left_rect.width, height=left_rect.height)
        left_page.show_pdf_page(
            fitz.Rect(0, 0, left_rect.width, left_rect.height),
            doc,
            page.number - 1,
            clip=left_rect
        )

        # 右半分を新しいページに追加
        right_page = right_pages.new_page(width=right_rect.width, height=right_rect.height)
        right_page.show_pdf_page(
            fitz.Rect(0, 0, right_rect.width, right_rect.height),
            doc,
            page.number - 1,
            clip=right_rect
        )

    # 分割したPDFを保存
    left_pages.save(output_pdf_left)
    right_pages.save(output_pdf_right)

    print(f"分割完了!\n左半分PDF: {output_pdf_left}\n右半分PDF: {output_pdf_right}")

# 使用例
split_pdf_vertically("sample.pdf", "left_half.pdf", "right_half.pdf")

■ポイント
1 ページの矩形領域に基づいた分割:
幅が842ポイント、ページ全体を左右2分割(421ポイントずつ)しています。
左半分: fitz.Rect(0, 0, 421, 595)
右半分: fitz.Rect(421, 0, 842, 595)

2 正しい領域の切り取り:
clipパラメータを使用し、ページから指定した領域だけをクロップします。

3 実行後の期待結果
left_half.pdf: 元PDFの左半分(0~421ポイント)。
right_half.pdf: 元PDFの右半分(421~842ポイント)。

■横長のpdfファイルを分割することでA4用紙に印刷できました。




Pythonコードで、/ で区切られた複数行の文章を1行に結合し出力する

 Pythonコードで、/ で区切られた複数行の文章を1行に結合し出力する。

■ Pythonコード1
・入力ファイル(.txt)
I am happy.
You are happy.
She is happy.
/
I am cold.
We are cold.
It is cold today.

・出力ファイル(.txt)
I am happy.You are happy.She is happy.
I am cold.We are cold.It is cold today.

・コード:
def merge_text_lines(file_path, output_path):
    with open(file_path, 'r', encoding='utf-8') as file:
        # テキストファイルを読み込む
        lines = file.read().splitlines()

    merged_lines = []
    current_sentence = []

    for line in lines:
        # '/'で区切られている場合
        if line == '/':
            # current_sentenceを結合して1行の文章にし、リストに追加
            if current_sentence:
                merged_lines.append(''.join(current_sentence))
                current_sentence = []
        else:
            # '/'でない行はcurrent_sentenceに追加
            current_sentence.append(line)

    # 最後の文がある場合は追加
    if current_sentence:
        merged_lines.append(''.join(current_sentence))

    # 各文章を改行で結合してファイルに書き込む
    with open(output_path, 'w', encoding='utf-8') as output_file:
        output_file.write('\n'.join(merged_lines))

# 入力ファイルと出力ファイルのパスを指定して実行
merge_text_lines('path_to_your_file.txt', 'output_file.txt')

■ Pythonコード2
・入力ファイル(.txt)
I am happy.
You are happy.
She is happy.
/
I am cold.
We are cold.
It is cold today.

・出力ファイル(.txt)[コンマ区切り]
I am happy.,You are happy.,She is happy.
I am cold.,We are cold.,It is cold today.

・コード2:
def merge_text_lines_with_commas(file_path, output_path):
    with open(file_path, 'r', encoding='utf-8') as file:
        # テキストファイルを読み込む
        lines = file.read().splitlines()

    merged_lines = []
    current_sentence = []

    for line in lines:
        # '/'で区切られている場合
        if line == '/':
            # current_sentenceをカンマ区切りで1行の文章にし、リストに追加
            if current_sentence:
                merged_lines.append(','.join(current_sentence))
                current_sentence = []
        else:
            # '/'でない行はcurrent_sentenceに追加
            current_sentence.append(line)

    # 最後の文がある場合は追加
    if current_sentence:
        merged_lines.append(','.join(current_sentence))

    # 各文章を改行で結合してファイルに書き込む
    with open(output_path, 'w', encoding='utf-8') as output_file:
        output_file.write('\n'.join(merged_lines))

# 入力ファイルと出力ファイルのパスを指定して実行
merge_text_lines_with_commas('path_to_your_file.txt', 'output_file_with_commas.txt')

■ Pythonコード3
入力ファイル(.txt)[最後の行に/がある]
I am happy.
You are happy.
She is happy.
/
I am cold.
We are cold.
It is cold today.
/

・出力ファイル(.txt)[コンマ区切り]
I am happy.,You are happy.,She is happy.
I am cold.,We are cold.,It is cold today.

・コード3
def merge_text_lines_with_commas(file_path, output_path):
    with open(file_path, 'r', encoding='utf-8') as file:
        # テキストファイルを読み込む
        lines = file.read().splitlines()

    merged_lines = []
    current_sentence = []

    for line in lines:
        # '/'で区切られている場合
        if line == '/':
            # current_sentenceに文がある場合のみカンマ区切りで1行に結合し、リストに追加
            if current_sentence:
                merged_lines.append(','.join(current_sentence))
                current_sentence = []  # 次の文のためにリストをリセット
        else:
            # '/'でない行はcurrent_sentenceに追加
            current_sentence.append(line)

    # 最後の'/'でcurrent_sentenceがリセットされているので、追加処理は不要

    # 各文章を改行で結合してファイルに書き込む
    with open(output_path, 'w', encoding='utf-8') as output_file:
        output_file.write('\n'.join(merged_lines))

# 入力ファイルと出力ファイルのパスを指定して実行
merge_text_lines_with_commas('path_to_your_file.txt', 'output_file_with_commas.txt')



Pythonから外部のコマンドラインツールを使う(.aacをmp3に変換する)

■必要な環境
ffmpegがインストールされていることを確認。subprocessで呼び出しています。
pydubとその依存関係(ffmpeg)が必要。

まだインストールしていない場合は、以下でインストールできます。
[ffmpegのインストール]
・MacOSやLinuxではbrew install ffmpegまたはsudo apt install ffmpegでインストールできます。
・Windowsの場合では、ffmpeg公式サイトからインストールしてください。

[pydubのインストール]
・pip install pydub

これで、ffmpegを使って.aacファイルを.wavに変換し、その後pydubで.mp3に変換する一貫したプロセスが実行できます。

----
import subprocess
from pydub import AudioSegment
import os

# 入力と出力のファイルパスを設定
input_file = "sample.aac"  # 変換したいAACファイルのパス
wav_file = "sample.wav"  # 一時的なWAVファイルのパス
output_file = "sample.mp3"  # 変換後のMP3ファイルのパス

# 1. ffmpegでAACからWAVに変換
subprocess.run(['ffmpeg', '-i', input_file, wav_file])

# 2. WAVファイルをMP3に変換
audio = AudioSegment.from_file(wav_file, format="wav")
audio.export(output_file, format="mp3")

print("変換が完了しました:", output_file)

# 一時的なWAVファイルを削除
os.remove(wav_file)
----

[学習のまとめ]
subprocess.run()を使うことで、Pythonから外部のコマンドラインツール(例えば、ffmpegやlsコマンドなど)を実行することができます。これにより、Pythonコード内でシステムのコマンドを直接呼び出すことができます。

[ffmpegの活用例]
1)ffmpeg -i input.aac output.wav
2)ffmpeg -i input.aac output.mp3

3)ffmpeg -i input.aac -map 0 output.wav -map 0 output.mp3
1),2)を1行で行う。

4)ffmpeg -i input.aac -map 0 output.wav -map 0 output.mp3 && rm output.wav
1),2)を1行で行い、output.wavを削除する。




ディレクトリ内のファイルを取得してテキストファイルに保存(python Windows10)

 
ディレクトリ /sound-part/ 内にあるすべてのファイル名を取得し、
それらを all_file_list.txtに保存する。
'dirctory-get_files_names.py'(20241107 作成)

[pythonコード(Windows10)]
----
import os

# 対象ディレクトリと出力ファイル
directory_path = "sound-part"# 読み取り対象のディレクトリ
output_file = "all_file_list.txt"  # 出力するテキストファイル

# ディレクトリ内のファイルを取得してテキストファイルに保存
with open(output_file, "w",encoding="utf-8") as file:
    for filename in os.listdir(directory_path):
        # ファイルパスを取得
        file_path = os.path.join(directory_path, filename)
        
        # ファイルのみを対象(ディレクトリは除外)
        if os.path.isfile(file_path):
            file.write(filename + "\n")  # ファイル名を1行ごとに保存

print(f"ファイルリストが {output_file} に保存されました(BOMなしのUTF-8形式)")
----

■with open(output_file, "w",encoding="utf-8") as fileに関連して
macOSのデフォルトエンコーディングは utf-8 であるため、
encoding="utf-8"がなくても'BOMなしのUTF-8形式'で保存されるようです。

with open(output_file, "w") as file:


■各OSでの動作
・Windows 10:
デフォルトエンコーディングは cp1252(Shift-JISやANSIと呼ばれることもあるWindowsのローカルエンコーディング)になります。
cp1252 はUTF-8とは異なるため、文字エンコーディングに互換性のない文字が含まれていると、文字化けが発生することがあります。

・macOS:
macOSのデフォルトエンコーディングは utf-8 であるため、BOMなしのUTF-8形式で保存されます。

■推奨事項
エンコーディングの違いを避け、常に同じ形式でファイルを扱うために、 encoding="utf-8" を明示的に指定するのがおすすめです。これにより、OSに関係なく、BOMなしのUTF-8形式でファイルが保存されます。

python
コードをコピーする
# BOMなしのUTF-8を明示的に指定
with open("example.txt", "w", encoding="utf-8") as file:
    file.write("これはテストの文章です。")
これで、WindowsとmacOSのどちらでも一貫してBOMなしのUTF-8形式で保存できます。

example.txtの中身:
これはテストの文章です。


複数の空ファイルの作成とそのファイル名の一部を一括変更する(python,wondows10)

利用する場合は、テスト用のディレクトリを作成しその中で作業して下さい。
ファイルの消去には注意してください。

■空のファイルを作成する
空のファイルを作成するには、Pythonでファイルを開いてすぐ閉じることで可能です。
以下のコードでは、指定されたファイル名のリストを使って空ファイルを作成。

[pythonコード例1]
空ファイルを作成する。拡張子が同じファイルの例
 F:\英語の学習-実習1>python empty_files.py
---
import os

# 作成したい空ファイルの名前リスト
file_names = [
    'sample_track-001.mp3',
    'sample_track-002.mp3',
    'sample_track-003.mp3',
    'sample-001.mp3'
]

# ファイルを保存するディレクトリ
directory = 'eigo'  # 必要に応じてディレクトリ名を変更してください

# ディレクトリが存在しない場合は作成
os.makedirs(directory, exist_ok=True)

# 空ファイルを作成
for file_name in file_names:
    file_path = os.path.join(directory, file_name)
    with open(file_path, 'w') as f:
        pass  # 'w' モードで開いてすぐ閉じることで空ファイルが作成される

print("空ファイルの作成が完了しました。")


●コードの説明
os.makedirs(directory, exist_ok=True) は、eigo ディレクトリが存在しない場合に作成します(既に存在する場合は何もしない)。
with open(file_path, 'w') as f: pass で空ファイルを作成します。ファイルが既に存在する場合、上書きされて空になる。

●実行結果
上記のコードを実行すると、指定した eigo ディレクトリに以下の空ファイルが作成される。

eigo/
├── sample_track-001.mp3
├── sample_track-002.mp3
├── sample_track-003.mp3
└── sample-001.mp3
これで、.mp3、.txt などの空ファイルが作成されます。

[pythonコード例2]
空ファイルを作成する。拡張子が同じファイルの例
 F:\英語の学習-実習1>python n-empty_files.py
---
import os
import time

# 作成したい空の .mp3 ファイルの名前リスト
file_names = [
    'sample_track-001.mp3',
    'sample_track-002.mp3',
    'sample_track-003.mp3',
    'sample-001.mp3'
]

# ファイルを保存するディレクトリ
directory = 'eigo'

# 既存のファイルをすべて削除してから再作成する
if os.path.exists(directory):
    for f in os.listdir(directory):
        os.remove(os.path.join(directory, f))
else:
    os.makedirs(directory)

# 指定順にファイルを作成し、間隔を開けて保存順を明確にする
for file_name in file_names:
    file_path = os.path.join(directory, file_name)
    with open(file_path, 'w') as f:
        pass  # 'w' モードで開いてすぐ閉じることで空ファイルが作成される
    time.sleep(0.1)  # 作成時間に間隔を設けて順序が保持されるようにする

print("空ファイルの作成が完了しました。")

# ディレクトリ内のファイルを指定順で表示
print("\nディレクトリ内のファイル一覧:")
for file_name in file_names:
    print(file_name)


■ファイル名の一部を一括変更する
 F:\英語の学習-実習1>pyton rename-files-name.py
----
import os
import shutil

# 元ディレクトリと新規保存ディレクトリのパス
source_dir = 'eigo'
target_dir = os.path.join(source_dir, 'rename_eigo')

# 変更する条件
target_extension = '.mp3'  # 変更するファイルの拡張子
old_text = 'sample_track'  # 置換前の文字列
new_text = 'eiken3'        # 置換後の文字列

# 保存ディレクトリを作成(存在しない場合のみ作成)
os.makedirs(target_dir, exist_ok=True)

# 元ディレクトリのファイルを順に処理
for filename in os.listdir(source_dir):
    source_file = os.path.join(source_dir, filename)
    
    # ファイルがディレクトリでないことを確認
    if os.path.isfile(source_file):
        # ファイル名と拡張子を分割
        name, ext = os.path.splitext(filename)
        
        # 拡張子が指定されたものであれば、名前の一部を置換
        if ext == target_extension and old_text in name:
            new_name = name.replace(old_text, new_text) + ext
        else:
            # 他のファイルは名前をそのまま保持
            new_name = filename
        
        # 変更後のファイルを新しいディレクトリにコピー
        target_file = os.path.join(target_dir, new_name)
        shutil.copy2(source_file, target_file)

print("ファイルの変更が完了しました。")





リスニング/スピーキングの独習アプリ(2024/10/17 by Takahashi)

●リスニング/スピーキングの独習アプリ(2024/10/17 by Takahashi)
(audio_player_20241101.py)

●audio_player.pyの実行ファイル(.exe)の作成
使用するときには実行ファイルを活用する。
>pyinstaller --onefile audio_player.py
これで作成されるディレクトリ[dist]内のaudio_player.exeをダブルクリックで立ち上げる。

●使用上の約束
・audio_player.exeと同じ場所にディレクトリ[sound]を作成して、そこにmp3を置く。
ディレクトリ[sound]はmp3ファイルを置くためのデフォルトディレクトリとしている。
ディレクトリ[sound]が無い場合には音声を入れたディレクトリ名を指定する。
・以後、起動後に表示されるメニューに従って利用します。
・再生中に
[p]を押すと再生の停止/再開
[m]を押すとメニューに戻る
[q]を押すとプログラム終了

●実行ファイルの提供について
未定

[立ち上げ時とメニュー表示]





















[pythonコード 参考]
-----------------

-----------------
■便利ツール(上記のメニュー画像の調整に下記の2,3を活用)
1) AIで画像を拡大|waifu2x.org
https://waifu2x.org/ja/

2) AIアップスケーラーで画像を大きく、美しく
https://imgupscaler.com/ja

3) デスクトップ版waifu2x-caffeの使い方
デスクトップ版「waifu2x-caffe」は、Windowsで動作するスタンドアロンのアプリケーションで、インターネットに接続せずに高画質化が行えます。
[waifu2x-caffeのダウンロードとインストール]
「waifu2x-caffe」のGitHubページ(https://github.com/lltcggie/waifu2x-caffe)から最新のリリースをダウンロードします。
ダウンロードしたZIPファイルを解凍し、「waifu2x-caffe.exe」をダブルクリックして起動。

テキストファイルから各センテンスを読み込み、無音を挿入した統合音声ファイルと個別センテンスの音声ファイルを作成

[F:\英語の学習-実習\20241102\1-each_sentence_basename.py](作業場所メモ)

Pythonを使って、テキストファイル(.txt)から各センテンスを読み込み、無音を挿入した音声ファイル(統合ファイル)と個別センテンスの音声ファイルを作成する。

[手順]
(1) テキスト読み込み
sentences.txtファイルから各センテンスを読み込む。
(2) 音声合成 (Text-to-Speech)
音声合成ライブラリ(例えば gTTS (Google Text-to-Speech))を使用して、各センテンスを音声データに変換。
(3) 音声ファイルの保存

Hello, how are you?
I am learning Python.
This is a test sentence.
Let's go fishing after school.
What do you do every saturday.

[pythonコード]
from gtts import gTTS
from pydub import AudioSegment

# 一括でファイル名を定義
txt_file = "sentences.txt"
out_mp3 = "sentences_with_silence.mp3"

# 各センテンスの音声ファイル名の頭部
each_sentence_basename = "lesson"

# 無音の長さを秒単位で設定(センテンスとセンテンスの間に無音を設定する)
silence_duration = 3  # 3秒間の無音

# テキストファイルの読み込み
with open(txt_file, "r", encoding="utf-8") as file:
    sentences = file.readlines()

# 初期の空の音声データ(全体の音声ファイル)
combined_audio = AudioSegment.silent(duration=0)

# 各センテンスを音声に変換し、無音を追加
for i, sentence in enumerate(sentences, start=1):
    sentence = sentence.strip()
    if sentence:
        # テキストを音声に変換
        tts = gTTS(sentence, lang='en')
        
        # 各センテンスのファイル名を作成(例: lesson001.mp3)
        sentence_filename = f"{each_sentence_basename}-{i:03}.mp3"
        tts.save(sentence_filename)
        
        # 個別の音声ファイルを読み込む
        sentence_audio = AudioSegment.from_mp3(sentence_filename)
        
        # 全体の音声にセンテンスと無音を追加
        combined_audio += sentence_audio
        combined_audio += AudioSegment.silent(duration=silence_duration * 1000)  # ミリ秒に変換

# 最終的な音声ファイルを保存
combined_audio.export(out_mp3, format="mp3")

print("無音を挿入した音声ファイルと個別のセンテンス音声ファイルが生成されました。")

音声(mp3)のセンテンスのテキスト出力及び各センテンスのmp3出力(python,windows10)

[F:\英語の学習-実習\mp3-2-text\t1-mp3-to-sentense-mp3.py](作業場所)

■音声(mp3)のセンテンスのテキスト出力及び各センテンスのmp3出力の試み
上手くいかない場合があります。
改善が必要ですが覚書として記録したものです。


import speech_recognition as sr
from pydub import AudioSegment
from pydub.silence import split_on_silence
import os

# 一括でファイル名を定義
mp3_file = "practice.mp3"
wav_file = "converted.wav"

# ディレクトリ部分とファイル名部分に分ける
basename, ext = os.path.splitext(mp3_file)
#print(basename)     # "practice"
#print(ext)          # ".mp3"

dir_name, file_name = os.path.split(mp3_file)
#print(dir_name)     # 空文字列 ""
#print(file_name)    # "practice.mp3"

# ファイル名から拡張子を除去
tmp2 = os.path.splitext(file_name)[0]  #"practice"

txt_file = tmp2 + "/" + tmp2 + ".txt" #"practice/practice.txt"で保存

directory = os.path.dirname(txt_file) #"practice"

# ディレクトリが存在しない場合は作成
if not os.path.exists(directory):
    os.makedirs(directory)

# 無音の長さ(秒単位)を設定(チャンク同士の間隔)
#silence_duration = 2  # 1 デフォルトの無音時間(秒)
silence_duration = 1  #1 英文のチャンク間の無音時間

# MP3ファイルをWAVに変換する
sound = AudioSegment.from_mp3(mp3_file)
sound.export(wav_file, format="wav")

# 音声タイプを選択 ('e-only' for 英文だけ, 'j-only' for 和訳だけ)
audio_type = 'e-only'  # 'e-only' または 'j-only' に設定

# 無音を作成する関数
def generate_silence(duration_sec):
    return AudioSegment.silent(duration=duration_sec * 1000)  # ミリ秒に変換

# 音声ファイルを分割する(無音部分で区切る)
def split_audio(file_path):
    sound = AudioSegment.from_wav(file_path)
    chunks = split_on_silence(
        sound,
        min_silence_len=1200,  # 500->1200無音とみなす最小の長さ(ミリ秒)[この値を適宜変更]
        silence_thresh=sound.dBFS - 14,  # 無音とみなす音の閾値
        keep_silence=500  # 各チャンクの先頭と末尾に無音を残す(ミリ秒)
    )
    return chunks

# 文章の末尾に句点やピリオドを追加し、英文をキャピタライズする関数
def format_sentence(sentence, is_english=False):
    sentence = sentence.strip()  # 余分なスペースを削除
    if is_english:
        sentence = sentence.capitalize()  # 英文の先頭を大文字に変換
        if sentence and sentence[-1] not in ['.', '?', '!', '。', '?', '!']:
            sentence += '.'  # 英文の文末にピリオドを追加
    else:
        if sentence and sentence[-1] not in ['。', '?', '!']:
            sentence += '。'  # 和訳の文末に句読点を追加
    return sentence

# 音声認識の準備
recognizer = sr.Recognizer()

# WAVファイルをチャンクごとに分割
audio_chunks = split_audio(wav_file)

# 変換したテキストを保存するリスト
recognized_sentences = []

# 各チャンクをテキストに変換
chunk_files = []  # 生成されたチャンクファイルのリスト

for i, chunk in enumerate(audio_chunks):
    chunk_filename = f"chunk{i}.wav"
    # 各チャンクを保存
    chunk.export(chunk_filename, format="wav")
    chunk_files.append(chunk_filename)  # 作成されたチャンクファイルをリストに追加
    
    with sr.AudioFile(chunk_filename) as source:
        audio = recognizer.record(source)
    
    # 音声をテキストに変換
    try:
        # 音声の種類に応じて処理を変更
        if audio_type == 'e-only':
            # 英文の場合
            text = recognizer.recognize_google(audio, language="en-US")
            formatted_sentence = format_sentence(text, is_english=True)
        elif audio_type == 'j-only':
            # 和訳の場合
            text = recognizer.recognize_google(audio, language="ja-JP")
            formatted_sentence = format_sentence(text, is_english=False)
        
        # 認識結果をリストに追加
        recognized_sentences.append(formatted_sentence)
    except sr.UnknownValueError:
        print(f"チャンク{i} は認識できませんでした。")
    except sr.RequestError as e:
        print(f"Googleサービスへのリクエストに失敗しました; {e}")

# TXTファイルに書き込む処理
with open(txt_file, mode='w', encoding='utf-8') as txtfile:

    for sentence in recognized_sentences:
        txtfile.write(sentence + '\n')

print(f"出力が完了しました。結果は {txt_file} に保存されました。")

# 生成された各チャンクファイルをMP3に変換する
# ファイル名はmp3_fileのbasenameに"-"と3桁の連番を付ける。例 practice-001.mp3

output_dir=directory

# ディレクトリが存在しない場合は作成
if not os.path.exists(output_dir):
    os.makedirs(output_dir)

# 各チャンクファイルをMP3に変換して保存
for i, chunk in enumerate(audio_chunks):
    mp3_filename = f"{basename}-{i+1:03d}.mp3"  
    output_path = os.path.join(output_dir, mp3_filename)  # ディレクトリに保存
    
    # チャンクをMP3として保存
    chunk.export(output_path, format="mp3")
    print(f"{output_path} に保存されました。")

# 生成されたWAVファイルを削除
if os.path.exists(wav_file):
    os.remove(wav_file)
    print(f"{wav_file} を削除しました。")

# 生成されたチャンクファイルを削除
for chunk_file in chunk_files:
    if os.path.exists(chunk_file):
        os.remove(chunk_file)
        print(f"{chunk_file} を削除しました。")

ファイルからテキストを読み込み、文字数を数える関数(python)


# ファイルからテキストを読み込み、文字数を数える関数
def count_characters_in_file(file_path, language="mixed"):
    with open(file_path, 'r', encoding='utf-8') as file:
        text = file.read()
    
    if language == "english":
        # 英語専用:アルファベットのみをカウント
        english_text = ''.join([char for char in text if char.isalpha()])
        return len(english_text)
    elif language == "japanese":
        # 日本語専用:ひらがな、カタカナ、漢字をカウント
        japanese_text = ''.join([char for char in text if '\u3040' <= char <= '\u30FF' or '\u4E00' <= char <= '\u9FFF'])
        return len(japanese_text)
    else:
        # 混在:全ての文字(空白や記号も含む)をカウント
        return len(text)

# ファイルパスと言語モードを指定して実行
file_path = 'example.txt'
language_mode = 'english'  # 'english', 'japanese', または 'mixed' を指定
character_count = count_characters_in_file(file_path, language_mode)
print(f"文字数: {character_count}")

複数のMP3ファイルを結合するpythonコード例

 複数のMP3ファイルを結合するpythonコード例
・各ファイル間に無音時間を設定できる
・ディレクトリ内のすべてのMP3ファイルを結合
・ファイル名(concatenate_mp3_files.py)
----
import os
from pydub import AudioSegment

# 複数のMP3ファイルを結合する関数
def concatenate_mp3_files(directory, output_file, silence_duration=1):
    # 無音時間の設定(ミリ秒単位)
    silence = AudioSegment.silent(duration=silence_duration * 1000)  # 秒単位をミリ秒に変換

    # ディレクトリ内のすべてのMP3ファイルを取得
    mp3_files = [f for f in os.listdir(directory) if f.endswith('.mp3')]

    # MP3ファイルをロードして結合
    combined = AudioSegment.empty()
    for mp3_file in mp3_files:
        mp3_path = os.path.join(directory, mp3_file)
        audio = AudioSegment.from_mp3(mp3_path)
        combined += audio + silence  # 音声ファイルに無音時間を追加して結合

    # 最後に追加された無音時間を削除
    combined = combined[:-silence.duration_seconds * 1000]

    # 出力ファイルとして保存
    combined.export(output_file, format="mp3")
    print(f"MP3ファイルが結合されました。出力ファイル: {output_file}")

# 使用例
directory = "lesson"  # MP3ファイルが置かれているディレクトリ
output_file = "combined_lessonn.mp3"  # 結合後の出力ファイル名
silence_duration = 1  # 無音時間の設定(秒単位)ファイル間の無音時間(この場合は1秒)

concatenate_mp3_files(directory, output_file, silence_duration)
----

画像のテキスト化

画像のテキスト化のpythonコード例

from PIL import Image
import pytesseract

# Tesseractのインストールパスを指定(例: Windowsの場合)
# pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'

def extract_text_from_image(image_path):
    # 画像を開く
    img = Image.open(image_path)

    # 画像からテキストを抽出
    text = pytesseract.image_to_string(img, lang='eng')  # lang='jpn+eng'日本語と英語の両方を使用

    # 全角を半角に変換
    #text = text.replace('’', "'")  # 全角アポストロフィ → 半角アポストロフィ
    text = text.replace('’', "'").replace('“', '"').replace('”', '"')  # 必要に応じて追加

    return text

# 使用例
image_path = 'sample.jpg'
text = extract_text_from_image(image_path)
print(text)

PDFのテキスト化

■PDFのテキスト化のpythonコード例1

import fitz  # PyMuPDF
import pytesseract
from PIL import Image
import io

# Tesseractのインストールパスを指定(例: Windowsの場合)
# pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'

def pdf_to_text(pdf_path, language='eng'):
    # PDFを開く
    pdf_document = fitz.open(pdf_path)
    text = ""
    #text = pdf_to_text(pdf_path, language='eng')

    # 各ページごとに画像に変換し、OCRでテキストを抽出
    for page_num in range(pdf_document.page_count):
        page = pdf_document[page_num]
        
        # PDFページを画像にレンダリング
        pix = page.get_pixmap(dpi=300)
        img = Image.open(io.BytesIO(pix.tobytes()))
        
        # 画像からテキストを抽出
        page_text = pytesseract.image_to_string(img, lang=language)
        text += page_text + "\n\n"  # ページごとに改行を追加

    pdf_document.close()

    # 全角を半角に変換
    #text = text.replace('’', "'")  # 全角アポストロフィ → 半角アポストロフィ
    text = text.replace('’', "'").replace('“', '"').replace('”', '"')  # 必要に応じて追加

    return text

# 使用例
pdf_path = 'sample.pdf' 
# 'eng'は英語, 'jpn'は日本語, 'eng+jpn'は英語と日本語の両方
#text = pdf_to_text(pdf_path, language='eng+jpn')
text = pdf_to_text(pdf_path, language='eng')

print(text) #テキストの表示。必要な場合はファイル出力に

=======
■PDFのテキスト化のpythonコード例2

import fitz  # PyMuPDF
import pytesseract
from PIL import Image
import io

# Tesseractのインストールパスを指定(例: Windowsの場合)
# pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'

def pdf_to_text(pdf_path, language='eng'):
    # PDFを開く
    pdf_document = fitz.open(pdf_path)
    text = ""

    # 各ページごとに画像に変換し、OCRでテキストを抽出
    for page_num in range(pdf_document.page_count):
        page = pdf_document[page_num]
        
        # PDFページを画像にレンダリング
        pix = page.get_pixmap(dpi=300)
        img = Image.open(io.BytesIO(pix.tobytes()))
        
        # 画像からテキストを抽出
        page_text = pytesseract.image_to_string(img, lang=language)
        text += page_text + "\n\n"  # ページごとに改行を追加

    pdf_document.close()
    
    # 全角を半角に変換
    # text = text.replace('’', "'").replace('“', '"').replace('”', '"')  # 必要に応じて追加

    return text

# 全角の句読点や記号を半角に変換する関数
def convert_fullwidth_to_halfwidth(text):
    text = text.replace(',', ',')  # 全角コンマ → 半角カンマ
    text = text.replace('。', '.')  # 全角ピリオド → 半角ピリオド
    text = text.replace(':', ':')  # 全角コロン → 半角コロン
    text = text.replace(';', ';')  # 全角セミコロン → 半角セミコロン
    text = text.replace('!', '!')  # 全角感嘆符 → 半角感嘆符
    text = text.replace('?', '?')  # 全角疑問符 → 半角疑問符
    text = text.replace('’', "'")  # 全角アポストロフィ → 半角アポストロフィ
    text = text.replace('“', '"')  # 全角二重引用符始 → 半角二重引用符始
    text = text.replace('”', '"')  # 全角二重引用符終 → 半角二重引用符終
    text = text.replace('(', '(')  # 全角括弧開 → 半角括弧開
    text = text.replace(')', ')')  # 全角括弧閉 → 半角括弧閉
    text = text.replace('[', '[')  # 全角角括弧開 → 半角角括弧開
    text = text.replace(']', ']')  # 全角角括弧閉 → 半角角括弧閉
    text = text.replace('{', '{')  # 全角波括弧開 → 半角波括弧開
    text = text.replace('}', '}')  # 全角波括弧閉 → 半角波括弧閉
    text = text.replace('・', '・')  # 全角中黒 → 半角中黒
    text = text.replace('~', '~')  # 全角チルダ → 半角チルダ
    text = text.replace(' ', ' ')  # 全角スペース → 半角スペース
    return text

# 使用例
# PDFからテキストを抽出し、全角を半角に変換
pdf_path = 'sample.pdf'
text = pdf_to_text(pdf_path, language='eng+jpn')
text = convert_fullwidth_to_halfwidth(text)
print(text)

get-contrast-text-color

背景色の選択は手動(#808080,#808080FFなど)とcolorPicker(Enter HEXA Color Code部)で行います。
スライダーは背景色の透明度(Alpha)を調整します。
colorPickerで選択した場合はAlpha=255(1.000)となります。
テキスト(Hello, World!)の色はカラーピッカーBで変えることができます。
背景色とテキストの色を調整してテキストの認識度を確認してみよう


colorPicker-hexa-rgba-cmyka

色の選択は手動(#808080,#808080FFなど)とcolorPickerで行います。
スライダーは色の透明度(Alpha)を調整します。
colorPickerで選択した場合はAlpha=255(1.000)となります。


svgnames-colors

svgnames-colors

pccs-tone-colors

・PCCSトーン

色相/彩度 /明度の調整

色相(Hue)、彩度(Saturation/chroma)、明度(Brightness/Value)の調整。

・調整に使用した値は.cvsで保存できる。
例:test.csvで保存するときは、ファイル名はtestとし、拡張子は省略して下さい。 ・ボックスの値を変える:小さい5つのカラーボックはクリックで色の選択ができます。
・スラーダーで値を変える:

Munsell Color Wheel

Virtual Munsell Color Wheel
https://www.andrewwerth.com/color/munsell1.html
https://www.andrewwerth.com/color/munsell2.html


png-base64-webdisp


html-code-escape

1行の'''から10行までの「HTMLコード」をエスケープしてファイルに書き出す。

'escaped_output.txt'の中身は以下となります。 &lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;title&gt;HTMLの'&lt;'と'&gt;'をエスケープ&lt;/title&gt; &lt;/head&gt; &lt;body&gt; &lt;h1&gt;ともに&lt;/h1&gt; &lt;p&gt;能登半島&lt;/p&gt; &lt;/body&gt; &lt;/html&gt;

png-base64-html



.txtファイルのBOMを削除する


.pngをbase64形式でBOMなしで出力する。


.png(複数対応)をbase64形式でBOMなしで出力する。

png2base64

注意:
15行:with open('output_base64.txt, 'wb')を修正してください(修正済20240324)
with open('sample2_base64.txt', 'wb')
学習用.png写真(width="100px",heigt="84"): ジャーマンアイリスの花
'image.png'の画像データをbase64形式で'output_base64.txt'に出力する(python)
ディレクトリ'flowers'の画像データ(複数可能)をbase64形式でディレクトリ'png-out1'に出力する(python)
例えば、[image.pngはimage.txt]となります。
課題:
出力ファイルに"BOM"が「含まれる」か「含まれてない」かを知ることが大切。 次の記事に、このことに関連した記事を予定しています。

画像(jpgなど)のサイズを一括変更(2)

画像(jpg)のサイズを一括変更するスクリプトです。
上のスクリプトはExif情報が消去され、下のスクリプトはExif情報を保持します。
#はコメントアウトを示す。



参照
https://ctakaha77.blogspot.com/2024/03/resize-pillow.html

CSSではみ出したテキストを省略するテストです。

縦長の動画(mp4)の上半分残す(下半分をカット[削除])方法

ディレクトリに保存した複数のmp4ファイルを一括クロップするスクリプト
(縦長の動画(mp4)の上半分を残す)

>python mp4-crop-sample.txt

mp4ファイルを"F:/video/tmp"に保存した場合
F:/video/tmp>python mp4-crop-sample.txt

一つの動画をクロップする(コマンドプロンプトで)
・動画の上半分を残して、下半分をカットする方法
>ffmpeg -i input_video.mp4 -filter:v "crop=in_w:in_h*0.5:0:0" output_video.mp4
・動画の下半分を残して、上半分をカットする方法
>ffmpeg -i input_video.mp4 -filter:v "crop=in_w:in_h*0.5:0:in_h*0.5" output_video.mp4
■FFmpegのインストール

exiftoolの活用

■exiftoolを使った、画像メタデータ情報の削除(利用には、情報を確認して自己責任でお願いします)

ExifToolは、Windows、macOS、Linuxなどのさまざまなプラットフォームで利用できる。

以下は、ExifToolを使用して写真や動画のプロパティを一括削除する手順です。

・ExifToolをインストールとコマンドラインでexiftoolの実行
インストール手順については、ExifToolの公式ウェブサイトを参照。
https://exiftool.org/index.html
Windows Executable: exiftool-12.78.zip (8.4 MB)をDL
・exiftool.exeへのpathを設定(exiftool.exeのあるディレクトリを設定)

・コマンドラインを開き、写真や動画の保存されているディレクトリ(F:\baseball2403\tmp-out)に移動。

F:\baseball2403\tmp-outに5個の画像があるとすると、
F:\baseball2403\tmp-out>exiftool -all= *.jpg

    5 image files updated

これで、写真や動画のメタデータが削除されます。

・一つのsample.jpgのメタ情報を削除
exiftool -all= sample.jpg

・現在のディレクトリにあるすべての.jpgや.mp4ファイルのメタ情報を一括削除する。
exiftool -all= *.jpg *.mp4

・詳しくは以下を参照
exiftool Application Documentation
https://exiftool.org/exiftool_pod.html

■コマンドプロンプトで、外付けHDD(f:)の画像保存ディレクトリに移動する場合のコマンドプロンプト

C:\Windows\system32>cd /d f:\baseball2403\tmp-out

画像(jpgなど)のサイズを一括変更(1)



画像(jpgなど)のサイズを一括変更する場合に使用するスクリプトです(Exif情報が削除されます)

■スクリプト中の(\\と/)について

・バックスラッシュをエスケープ文字として扱うために、\\とする必要があります

input_directory = "baseball2403\\tmp-in"
output_directory = "baseball2403\\tmp-out"

・スラッシュを使う。
input_directory = "baseball2403/tmp-in"
output_directory = "baseball2403/tmp-out"

どちらを使用してもよい。

■pythonとpillowの入手はサイトを参照しました。
■ChatGPT3.5と何回もやりとりして完成したものです。

KeTCindy installation guide revised version

 Updateできないときの対応

[Update]をクリックすると黒い画面(コマンドプロンプト)が点滅し終了しない場合は、
Updateできていないので手動で更新する。

更新されない箇所は以下の2つのファイルの中身である。
[C:\kettex\texlive\texmf-dist\scripts\ketcindy]と
[C:\kettex\texlive\texmf-dist\tex\latex\ketcindy]

  


■手動更新

手順1
1) [C:\kettex\texlive\texmf-dist\scripts\ketcindy]の中身を
2) [C:\ketcindy4.4.61\scripts]の中身と同じにする。
具体的には1)の中身をすべて削除して、2)の中身をコピーして、1)にペーストする。

手順2
1) [C:\kettex\texlive\texmf-dist\tex\latex\ketcindy]の中身を
2) [C:\ketcindy4.4.61\style]の中身と同じにする。
具体的には1)の中身をすべて削除して、2)の中身をコピーして、1)にペーストする。

手順3
コマンドプロンプトを管理者として立ち上げ、mktexlsrを実行する。
mktexlsrは
[C:/kettex/texlive/bin/win32/mktexlsr]にある。
コマンドプロンプトでの操作は以下のようとなります。

Microsoft Windows [Version 10.0.19045.3930]
(c) Microsoft Corporation. All rights reserved.
C:\Windows\system32>cd \
C:\>C:/kettex/texlive/bin/win32/mktexlsr
mktexlsr: Updating C:/kettex/texlive/texmf-local/ls-R...
mktexlsr: Updated C:/kettex/texlive/texmf-local/ls-R.
mktexlsr: Updating C:/kettex/texlive/texmf-config/ls-R...
mktexlsr: Updated C:/kettex/texlive/texmf-config/ls-R.
mktexlsr: Updating C:/kettex/texlive/texmf-var/ls-R...
mktexlsr: Updated C:/kettex/texlive/texmf-var/ls-R.
mktexlsr: Updating C:/kettex/texlive/texmf-dist/ls-R...
mktexlsr: Updated C:/kettex/texlive/texmf-dist/ls-R.
mktexlsr: Done.
C:\>

直ぐに終了しました。

■WORKボタンのクリック

作業ディレクトリー[ketcindy2024Jan16]がユーザディレクトリー(ユーザーホーム)に作成される。

C:\Users\taka\ketcindy2024Jan16


■[ketcindyjs]の生成
[C:\Users\taka\ketcindy2024Jan16\templates]にある[ketcindyjs]の生成

最初にKetjsoffボタンを押したタイミングで生成される。
[ketcindyjs]がないと×××offL.htmlが表示されない。

上記の作業ディレクトリー[ketcindy2024Jan16]を例えばD:\に移動してしまうと、Ketjsoffボタンを押しても[ketcindyjs]は生成されないようです。

そこで、C:\Users\takaの作業ティレクーで[ketcindyjs]を生成してからD:\等に移動することになるようです。
作業ティレクーは任意の場所に移動できるが、[ketcindyjs]が必要な場合は[ketcindyjs]の生成のタイミングに注意が必要である。


KeTCindy installation guide

KeTCindyの更新手順(Windows10)
KeTCindyのインストール」による
[https://s-takato.github.io/ketcindyorg/installketcindy.html]

■ketcindy4.4.61をダウンロードして、C:直下に置く











■ketcindysettings.cdyを実行して各種設定
[C:\ketcindy4.4.61\doc\ketcindysettings.cdy]にある




Kettex→MkinitUpdate→Workの順に実行
[Update]をクリックすると黒い画面(コマンドプロンプト)が点滅し終了しない。
Ctrl+Cで強制終了する。

コマンド画面には、以下のメッセージが連続して表示される。
^Cwhoami: extra operand `/groups' 
Try `whoami --help' for more inform ation.
find: `Mandatory': No such file or directory
バッチ ジョブを終了しますか (Y/N)?
Y 




動画の様子


■まとめ
設定後、KeTCindyは問題なく実行できている。



■動画作成に利用したソフトと参考サイト
  • 【AviUtl】ぼかし系エフェクト(ぼかし・境界ぼかし・モザイク)の使い方
    https://aviutl.info/bokasi-efekuto/
  • Aviutlを使う方法をご紹介
    https://filmora.wondershare.jp/aviutl/how-to-use-free-software-aviutl.html

AviUtlの編集


Cycloidの仲間たち


下図をクリックしてください(別タブに表示)。
図のA点を上下して曲線の変化を見てみましょう。



  • 円は半径1
  • A点は自由点で、ドラッグして上下に動かすことができる
  • 範囲はSlider("A",[0,-4],[0,4]);で設定している
Ketinit();
Setketcindyjs(["Label=[A]","Color=white"]);

Putpoint("A",[0,0],[0,A.y]);
Putpoint("C",[0,1]);
Slider("A",[0,-4],[0,4]);
Setpt(2);
Circledata("0",[C,C+[1,0]]);
Pointdata("0",[A],["Color=red"]);

nn=4*36;
forall(1..nn,
    t=4*pi/nn*#;
    Rotatedata("p","pt0",-t,[C,"nodisp"]);
    Translatedata("p"+text(#),"rtp",[t,0],["Color=red"]);
    Rotatedata("c","cr0",-t,[C,"nodisp"]);
    Translatedata(text(#),"rtc",[t,0],["dr,0.3"]);
);

Windispg();