[Design] ニールセンの10のヒューリスティックステスト

チェック項目を作成して、WFの段階できんちんと1枚ずつ確認していく

システム状態の視認性
L システムが今何をしているか、ユーザーに常にフィードバックを返すこと(例:アップロード中のプログレスバー)。
システムと実世界の一致
L 専門用語ではなく、ユーザーが使い慣れた言葉や概念を使うこと(例:削除ボタンにゴミ箱のアイコンを使う)。
ユーザーの制御権と自由
L 間違えて操作したときに、すぐにやり直したりキャンセルしたりできる「非常口」を用意すること。
一貫性と標準
L 同じ製品内や業界の標準で、言葉や操作の一貫性を保つこと(例:リンクは青色にする、など)。
エラーの防止
L エラーメッセージを出す前に、そもそもエラーが起きないような設計にすること(例:削除前に確認ダイアログを出す)。
想起(記憶)よりも再認
L ユーザーに何かを覚えさせなくても、見れば操作がわかるようにすること。
柔軟性と効率性
L 初心者には分かりやすく、上級者にはショートカットなどの効率的な手段を提供すること。
美学的で最小限のデザイン
L 不要な情報は、本当に必要な情報の邪魔をしないように削ぎ落とすこと。
ユーザーによるエラーの認識・診断・回復のサポート
L エラーが起きた際、何が問題でどう解決すればいいかを平易な言葉で伝えること。
ヘルプとドキュメント

[TTS] Mel-spectrogram出力 → vocoder変換 のサンプル

「波形への復元」には、数学的な近似アルゴリズムである Griffin-Lim法 を使う

import librosa
import numpy as np
import soundfile as sf

# 1. アップロードされたファイルの読み込み
# path は実行環境に合わせて調整してください(通常はカレントディレクトリ)
file_path = 'speech.mp3' 
y, sr = librosa.load(file_path, sr=None) # sr=None で元のサンプリングレートを維持

# 2. Mel-spectrogram への変換
S = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=128)
S_dB = librosa.power_to_db(S, ref=np.max)

# 3. 復元 (Griffin-Lim)
S_inv = librosa.db_to_power(S_dB)
y_inv = librosa.feature.inverse.mel_to_audio(S_inv, sr=sr)

# 4. 保存
sf.write('output_speech.wav', y_inv, sr)
print(f"'{file_path}' の処理が完了し、'output_speech.wav' として保存しました。")


output

Mel-spectrogramとは?: 音の強さを「時間」と「周波数」の2軸で表したものですが、周波数軸を人間の耳の特性に近いメル尺度に変換したものです。

Vocoder(ボコーダー)の役割: スペクトログラムから音声を復元する際、元の波形が持っていた「位相(Phase)」の情報が失われています。このサンプルで使った mel_to_audio(Griffin-Lim)は、その位相を推測して補完する簡易的なボコーダーの役割を果たしています。

より高品質にするには: 実用的なAI(TTSや声質変換)では、Griffin-Limの代わりに HiFi-GAN や BigVGAN といったディープラーニングベースのボコーダーを使って、より肉声に近い高品質な復元を行います。

位相推論に限界があるということですね。

instagram api

$ install instaloader

import instaloader

# インスタンスの作成
L = instaloader.Instaloader()

# 取得したいユーザーのIDを指定
target_profile = "instagram"  # 例としてInstagram公式アカウント

try:
    # プロフィール情報の読み込み
    profile = instaloader.Profile.from_username(L.context, target_profile)

    print(f"ユーザー名: {profile.username}")
    print(f"フォロワー数: {profile.followers}")
    print(f"自己紹介: {profile.biography}")

    # 最新の投稿を3件表示
    print("\n--- 最新の投稿 ---")
    for post in profile.get_posts():
        print(f"投稿日: {post.date}")
        print(f"キャプション: {post.caption[:30]}...") # 最初の30文字だけ
        print(f"URL: {post.url}")
        
        # 3件取得したらストップ
        if post.owner_username == target_profile:
            break 

except Exception as e:
    print(f"エラーが発生しました: {e}")

$ python3 app.py
ユーザー名: instagram
フォロワー数: 698490388
自己紹介: Discover what’s new on Instagram 🔎✨

— 最新の投稿 —
投稿日: 2025-12-26 21:05:21
キャプション: the definition of “never let t…
URL: https://scontent-nrt1-2.cdninstagram.com/v/t51.2885-15/606469868_18689042716001321_9120174716535860606_n.jpg?stp=dst-jpg_e15_fr_p1080x1080_tt6&_nc_ht=scontent-nrt1-2.cdninstagram.com&_nc_cat=1&_nc_oc=Q6cZ2QFZnredhbdVl_SvagHdS1_L6FOS6xwQKfiSolX7tuMyxIYTOVN7Um-LzzQ_jBneDHI&_nc_ohc=VXPBA7g5rlQQ7kNvwFrzZcc&_nc_gid=s6qDPQ_v2Qy2aL1kVrz0Wg&edm=AOQ1c0wBAAAA&ccb=7-5&oh=00_AfmMpzoxHZbJe-l-Inrc-cUqHsm3Nfz13kckIgLq0ttU4A&oe=69584AA3&_nc_sid=8b3546

instaloader は、ブラウザでインスタを見る時と同じような仕組みで情報を読み取っているため、**「公開アカウント」かつ「数件の取得」**であれば、面倒なAPIキーの手続きなしでサクッと動く

「仕事で使いたい」「公式にアプリをリリースしたい」となった場合は、Meta社が提供する**「Instagram Graph API」**を使う必要がある

import instaloader

L = instaloader.Instaloader()

# 検索したいハッシュタグ(#は不要)
hashtag_name = "猫"

try:
    # ハッシュタグオブジェクトの作成
    hashtag = instaloader.Hashtag.from_name(L.context, hashtag_name)

    print(f"#{hashtag_name} の投稿を取得中...")

    # 最新の投稿を5件ループで回す
    for count, post in enumerate(hashtag.get_posts(), 1):
        print(f"\n[{count}件目]")
        print(f"投稿者: {post.owner_username}")
        print(f"いいね数: {post.likes}")
        print(f"キャプション: {post.caption[:50]}...") # 50文字まで
        print(f"URL: {post.url}")

        # 負荷軽減のため5件でストップ
        if count >= 5:
            break

except Exception as e:
    print(f"エラーが発生しました: {e}")

$ python3 cat.py
JSON Query to api/v1/tags/web_info/: 403 Forbidden – “fail” status, message “login_required” when accessing https://i.instagram.com/api/v1/tags/web_info/?__a=1&__d=dis&tag_name=%E7%8C%AB [retrying; skip with ^C]
JSON Query to api/v1/tags/web_info/: 403 Forbidden – “fail” status, message “login_required” when accessing https://i.instagram.com/api/v1/tags/web_info/?__a=1&__d=dis&tag_name=%E7%8C%AB [retrying; skip with ^C]
エラーが発生しました: JSON Query to api/v1/tags/web_info/: 403 Forbidden – “fail” status, message “login_required” when accessing https://i.instagram.com/api/v1/tags/web_info/?__a=1&__d=dis&tag_name=%E7%8C%AB

タグ検索の場合は、ログインが必要となる。
L.login(“自分のユーザー名”, “パスワード”)

本格的にやりたい場合はInstagram Graph API

その他

import instaloader

L = instaloader.Instaloader()

# --- 修正ポイント:パスワードを使わずブラウザのクッキーを使う ---
# Chromeがインストールされている場合、以下の1行でセッションを読み込めます
# 注意: 初回実行時にOSからブラウザデータへのアクセス許可を求められることがあります
USER = ""
try:
    L.interactive_login(USER) # または L.load_session_from_instaloader(USER)
    # 最も簡単な方法:
    # ブラウザのクッキーをインポートするヘルパー関数(instaloader公式推奨)
    # ※ pip install browser-cookie3 が必要な場合があります
    # 以下の1行でブラウザのログイン状態を引き継ぎます
    L.load_session_from_instaloader(USER) 
except:
    # ブラウザからセッションを取得するスクリプトを別途実行するか
    # 以下のコマンドをターミナルで実行してセッションファイルを作ってください
    # instaloader -l YOUR_USER_NAME
    print("セッションの読み込みに失敗しました。")

# 実行
hashtag_name = "猫"
hashtag = instaloader.Hashtag.from_name(L.context, hashtag_name)

for count, post in enumerate(hashtag.get_posts(), 1):
    print(f"[{count}] {post.owner_username}: {post.caption[:20]}...")
    if count >= 3: break

Open AI apiの TextToImage

import os
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()

# クライアント作成
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

# 2. 画像生成のリクエスト
response = client.images.generate(
    model="dall-e-3",
    prompt="サイバーパンクな都市を歩く柴犬",
    n=1,
    size="1024x1024"
)

# 3. 生成された画像のURLを表示
print(response.data[0].url)

geminiも同じようなことができる

import os
from google import genai
from google.genai import types
from PIL import Image
from io import BytesIO

# 1. クライアントの初期化(APIキーを入力)
# client = genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))

# 2. 画像生成のリクエスト(Imagen 3モデルを使用)
response = client.models.generate_images(
    model='imagen-4.0-generate-001', 
    prompt='サイバーパンクな都市を歩く柴犬',
    config=types.GenerateImagesConfig(
        number_of_images=1,
    )
)

# 3. 生成された画像を表示・保存
for generated_image in response.generated_images:
    # バイトデータから画像を開く
    image = Image.open(BytesIO(generated_image.image.image_bytes))
    image.show() # 標準のフォトビューアーで開く
    # image.save("result.png") # ファイルとして保存する場合

[App] Rorkでアプリを作成する

### プロンプト
シンプルな「日英翻訳アプリ」を作成してください。
このアプリは、外部の翻訳APIは使用せず、内部に持たせた簡単な辞書データで翻訳処理を代替します。

### 1. 辞書データ(必須)
以下のデータを持ったオブジェクトまたは配列をコンポーネント内に定義してください。

* **日本語:** ‘こんにちは’ → **英語:** ‘Hello’
* **日本語:** ‘ありがとう’ → **英語:** ‘Thank you’
* **日本語:** ‘さようなら’ → **英語:** ‘Goodbye’
* **日本語:** ‘はい’ → **英語:** ‘Yes’
* **日本語:** ‘いいえ’ → **英語:** ‘No’

### 2. UI/機能要件(必須)
1つの画面(App.jsのみで完結)に以下の要素を配置してください。

* **入力エリア:** ユーザーが日本語の単語を入力できる `` コンポーネント。
* **翻訳ボタン:** 「翻訳する」というテキストのボタン。
* **結果表示:** 翻訳結果(英語)を表示する `` コンポーネント。初期値は「翻訳結果がここに表示されます」としてください。

### 3. 処理ロジック
1. ユーザーが入力エリアに日本語を入力し、「翻訳する」ボタンを押します。
2. 入力された日本語が、辞書データ内に存在するかチェックします。
3. 存在する場合、対応する英語を結果表示エリアに表示します。
4. 辞書データに存在しない単語が入力された場合、「辞書に単語がありません」というメッセージを表示してください。

ここまで来たか… oh my goodness

Three.jsで3Dアバターの表示

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Three.js glTF アバターデモ (最終サイズ調整版)</title>
    <style>
        body { margin: 0; overflow: hidden; background-color: #f0f0f0; }
        canvas { display: block; }
    </style>
    
    <script src="https://unpkg.com/three@0.137.0/build/three.min.js"></script>
    <script src="https://unpkg.com/three@0.137.0/examples/js/loaders/GLTFLoader.js"></script>
    <script src="https://unpkg.com/three@0.137.0/examples/js/controls/OrbitControls.js"></script>
</head>
<body>
    <script>
        // ==========================================================
        // 1. シーン、カメラ、レンダラーのセットアップ
        // ==========================================================
        const scene = new THREE.Scene();
        // カメラのクリッピング範囲を広げる (near=0.001, far=10000)
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.001, 10000); 
        const renderer = new THREE.WebGLRenderer({ antialias: true });
        
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.outputEncoding = THREE.sRGBEncoding; 
        renderer.toneMapping = THREE.ACESFilmicToneMapping;
        renderer.setClearColor(0xcccccc, 1); 
        document.body.appendChild(renderer.domElement);

        // ==========================================================
        // 2. ライトのセットアップ
        // ==========================================================
        const ambientLight = new THREE.AmbientLight(0xffffff, 2.0); 
        scene.add(ambientLight);

        const directionalLight = new THREE.DirectionalLight(0xffffff, 1.0);
        directionalLight.position.set(5, 10, 5);
        scene.add(directionalLight);

        const pointLight = new THREE.PointLight(0xffffff, 3.0);
        pointLight.position.set(0, 3, 0); 
        scene.add(pointLight);

        // ==========================================================
        // 3. GLTFLoaderとアニメーションミキサーのセットアップ
        // ==========================================================
        const loader = new THREE.GLTFLoader(); 
        let mixer; 
        const clock = new THREE.Clock(); 

        // ==========================================================
        // 4. モデルの読み込み
        // ==========================================================
        const MODEL_PATH = './ellen_joe_oncampus/scene.gltf';

        loader.load(
            MODEL_PATH,
            function (gltf) {
                const model = gltf.scene;
                scene.add(model);

                // 【最終修正点】モデルを 50倍に拡大し、適切なサイズで表示
                model.scale.set(50, 50, 50); 
                
                // モデルの位置を強制的に原点 (0, 0, 0) に設定
                model.position.set(0, 0, 0); 
                
                // アニメーションデータの処理
                if (gltf.animations && gltf.animations.length > 0) {
                    mixer = new THREE.AnimationMixer(model);
                    const action = mixer.clipAction(gltf.animations[0]);
                    action.play();
                } else {
                    console.log('モデルにアニメーションデータが見つかりませんでした。静止画として表示します。');
                }
            },
            function (xhr) {
                console.log('モデル読み込み中: ' + (xhr.loaded / xhr.total * 100).toFixed(2) + '%');
            },
            function (error) {
                console.error('モデルの読み込み中にエラーが発生しました。', error);
            }
        );

        // ==========================================================
        // 5. カメラとコントロールの設定
        // ==========================================================
        // 【最終修正点】50倍スケールに合わせてカメラを遠ざけ、全体が見えるように調整
        camera.position.set(0, 5, 10); 

        const controls = new THREE.OrbitControls(camera, renderer.domElement); 
        // 【最終修正点】注視点をモデルの中心 (Y=5m) に設定
        controls.target.set(0, 5, 0); 
        controls.update();

        // ==========================================================
        // 6. アニメーションループ (毎フレームの更新処理)
        // ==========================================================
        function animate() {
            requestAnimationFrame(animate);

            const delta = clock.getDelta();

            if (mixer) {
                mixer.update(delta);
            }

            controls.update();
            renderer.render(scene, camera);
        }

        animate();

        // 画面サイズ変更時の対応
        window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        });

    </script>
</body>
</html>

[iOS] Image + Circle + frame

struct ChatMessage: Identifiable {
    let id = UUID()
    let text: String
    let isMe: Bool
    let avatar: String  // 画像名(URLの場合もOK)
}

struct ChatRow: View {
    let message: ChatMessage

    var body: some View {
        HStack(alignment: .bottom, spacing: 10) {

            // 左側に相手のアバター
            if !message.isMe {
                avatarView
            }

            // メッセージバブル
            Text(message.text)
                .padding()
                .background(message.isMe ? Color.blue : Color.gray.opacity(0.2))
                .foregroundColor(message.isMe ? .white : .black)
                .cornerRadius(12)

            // 右側に自分のアバター
            if message.isMe {
                avatarView
            }
        }
        .padding(.horizontal)
    }

    // アバター
    private var avatarView: some View {
        Image(message.avatar)
            .resizable()
            .scaledToFill()
            .frame(width: 40, height: 40)
            .clipShape(Circle())
    }
}
struct ChatView: View {
    let messages = [
        ChatMessage(text: "こんにちは!", isMe: false, avatar: "avatar1"),
        ChatMessage(text: "こんにちは〜!", isMe: true, avatar: "myAvatar"),
        ChatMessage(text: "調子どう?", isMe: false, avatar: "avatar1")
    ]

    var body: some View {
        ScrollView {
            VStack(spacing: 12) {
                ForEach(messages) { msg in
                    ChatRow(message: msg)
                }
            }
        }
    }
}

[design] Smashing Magazine

Smashing Magazine は Web デザイン/フロントエンド関連で最も歴史があり影響力のある専門オンラインメディアの1つ です。
UI/UX、HTML/CSS、アクセシビリティ、デザインシステム、フロントエンド実装までカバーした“実務者向け”の知識が揃います。

UX Collective が「読みやすいUXマガジン」なら
Smashing Magazine は “本格的・プロ志向” のデザイン/実装メディア です。

🔷 Smashing Magazine とは?

創刊:2006年

Webデザイナー、UIデザイナー、フロントエンド開発者向け

デザイン × 技術 の交差点を深く掘り下げる

世界中の専門家が寄稿

実務レベルのナレッジが大量にある

🔶 どんな記事が多い?

他のメディアより 技術的・専門的 です。

▼ 主なカテゴリ
UI/UX デザイン
アクセシビリティ(WCAG)
レスポンシブデザイン
デザインシステム
CSS レイアウト(Grid, Flexbox)
フロントエンド(React, Next.js など)
UX リサーチ
モーションデザイン
パフォーマンス最適化

▼ 教科書級の人気記事例
Responsive Web Design Patterns
Color Contrast Best Practices
UI Components: Design + Code Examples
Creating Accessible Interfaces
Design System Essentials
UX Collective より文章量が多く、より体系的・プロフェッショナル寄り。

🔶 デザインを学ぶ上で Smashing Magazine は重要?

結論:実務レベルで UI/UX をやるなら非常に重要(特にフロント寄り)。

▼ なぜ重要か?
UIの見た目だけではなく「実装可能な設計」を学べる
→ デザインとコーディングのギャップを埋める記事が多い。
アクセシビリティやレスポンシブの正しい方法を学べる
→ 開発現場で求められる“本物のUI設計”の知識。
デザインシステム(Figma + コード)の総合的知識が得られる
→ フロント実装+UI構造+Figma運用を連携して解説。
NN/g(ニールセンノーマン)より技術寄りで実践的
→ Webプロダクトの実装との相性がよい。

🔶 UX Collective と Smashing Magazine の違い
項目 UX Collective Smashing Magazine
難易度 初級〜中級 中級〜上級
傾向 UX・UIの読み物 デザイン+実装+システム
スタイル 読みやすくライト 専門的で体系的
学べる範囲 体験デザインやUI改善 レスポンシブ、実装、デザインシステム
向いている人 まずUXを理解したい人 UIをコードとつなぐ実務者

あなたのように
開発現場でFigmaを扱いつつ、UI/UX を本格的に学びたいエンジニア寄りの方
には Smashing Magazine はかなり相性がよいです。

🔷 どう使うべき?
もし今後こういうレベルを目指すなら確実に役立ちます:
デザインシステムを構築したい
フロントとFigmaの連携をよくしたい
アクセシビリティに強くなりたい
UIの「正しい構造」「正しい余白」「レスポンシブ基礎」を知りたい
コンポーネントをコード側でどう実装するかを理解したい

🔶 学習の進め方(超シンプル版)

Smashing の記事は長いので、次の順序で読むと効率的:

① Layout(グリッド・レスポンシブ)
② Color & Accessibility(コントラスト)
③ UI Components(ボタン・カード・フォーム)
④ Design Systems(構造化)
⑤ Motion / Micro-interactions(動き)

この順番で読むと、デザインの全体像がつながります。

Smashing Magazine
https://www.smashingmagazine.com/

VAE Autoencoder

VAE(Variational Autoencoder)や Autoencoder も、Text-to-Image / Text-to-Video における“補助的な技術”として重要な役割を担っています。
ただし、**役割は GAN とは異なり、画像を「圧縮・展開するための土台」**として使われることが多いです。

⭐ VAE / Autoencoder は「画像を扱いやすくするための変換装置」
最新の Text-to-Image(Stable Diffusion など)では、

**画像をいきなりピクセルで扱わず、
一度「潜在空間(latent space)」に圧縮してから処理します。**
ここで使われるのが VAE や Autoencoder。

⭐ 1. Stable Diffusion を例にすると、VAE は「圧縮と復元」を担当
Stable Diffusion の大まかな流れ:

1️⃣ VAE Encoder:
画像 → 低次元の潜在表現(latent)

2️⃣ Diffusion (U-Net):
潜在空間でノイズ除去 / 生成処理
(ここが Text-to-Image のメイン)

3️⃣ VAE Decoder:
潜在 → 最終画像(512×512 など高解像度)
つまり VAE は、
Diffusion が扱う“潜在空間”を作るための重要モジュール。

⭐ 2. なぜ Autoencoder が必要なのか?

理由は3つ。

✔ 理由①:計算量を激減させる(高速化)
画像を直接生成すると 512×512×3 = 786,432 ピクセル
これは非常に重い。
潜在空間は 1/8〜1/16のサイズなので
Diffusion の計算が一気に軽くなる。

✔ 理由②:高解像度の構造を少ない次元で表現できる
Autoencoder は


質感

などの情報を「圧縮しても失われにくい形」に変換できる。
GAN や Diffusion だけではこの圧縮が難しいので Autoencoder が必要。

✔ 理由③:潜在空間はノイズ処理と相性が良い
Diffusion の“ノイズ除去プロセス”は、
潜在空間の方がやりやすい。

⭐ 3. Text-to-Video でも Autoencoder が使われる
動画の場合は、
“空間だけでなく時間方向にも圧縮”が必要。

そこで登場するのが:
Video Autoencoder
Temporal VAE
3D VAE(空間+時間)

これらは
動画 → 潜在動画
に変換してから Diffusion で生成します。

Sora など最新モデルでは
専用の Video Autoencoder が重要な基盤技術として使われています。

⭐ 4. まとめ:VAE / Autoencoder は「補助」だけど“めちゃ重要な基盤”
技術 主な役割
Diffusion 画像・動画そのものを生成する“エンジン”
GAN 仕上げの高解像化・質感改善・時間的一貫性補正
Autoencoder / VAE 画像や動画を扱いやすい潜在空間に変換

要するに、

🔹 Diffusion(生成の本体)

🔹 Autoencoder(圧縮/展開の基盤)

🔹 GAN(質感や解像度を補強)

という構成が最新モデルの一般形です。