# Lang Lesson

> Одна команда /lang-lesson: из YouTube URL или папки с видео+субтитрами делает структурированный урок .md на русском (правила, нюансы, исключения, лайфхаки, ошибки, примеры) и Anki TSV на 4 поля (Вопрос, Ответ, Комментарий, Метки) плюс merge в master.de.tsv|master.en.tsv на уровень выше папки урока. DE nouns с артиклем; DE/EN verbs в Word с тремя формами. Скрины выключены по умолчанию. Trigger: /lang-lesson, языковой урок, конспект видео DE/EN, Anki из видео, master словарь.

- Skill: `alexey-shnaydmiller/lang-lesson` (Agent Skill, multi-file: 15 files)
- Install (CLI): `npx skillmds@latest add alexey-shnaydmiller/lang-lesson`
- Raw SKILL.md: https://api.skillmd.com/api/skills/alexey-shnaydmiller/lang-lesson/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: alexey-shnaydmiller (https://skillmd.com/u/alexey-shnaydmiller)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/alexey-shnaydmiller/lang-lesson

---


# Lang Lesson — конспект языкового видео

Превращает видеоуроки немецкого/английского (объяснения на русском) в **единый markdown-конспект** и **Anki TSV**.

## Запуск (одна команда)

Пользователь вызывает:

```text
/lang-lesson https://youtu.be/T_gnTfeDV28
/lang-lesson /path/to/folder-with-video-and-subs
```

Опционально в том же сообщении: уровень (A1–C1), курс, «положи в ту же папку» → `--inplace`, **«со скринами» / frames=on** → включить кадры.

По умолчанию: **только текст** (транскрипт, `lesson.md`, словарь, Anki). Скрины **не** делать.

## Жёсткие правила формата

1. Документ и пояснения — **на русском**.
2. Слова, примеры, цитаты из целевого языка — **на DE/EN** (как в уроке), рядом перевод на русский.
3. Имя файла урока: `lesson.md`. Anki: `anki.tsv`.
4. Структура секций **всегда** как в `templates/lesson.md` — не переименовывать и не пропускать заголовки (пустая секция = `—`).
5. Скрины — **только если пользователь явно попросил** (или `frames.enabled=true` / `--with-frames`). Иначе секции без картинок; не вызывать extract_frames.
6. Anki TSV — **4 колонки** под поля колоды: `Вопрос`, `Ответ`, `Комментарий`, `Метки`.
   - `Вопрос` ← слово (`Word`, с артиклем / формами глагола)
   - `Ответ` ← перевод (`Word_RU`)
   - `Комментарий` ← HTML: **POS** + пример + перевод примера (`POS`, `Sentence`, `Sentence_RU`)
   - `Метки` ← теги
   В `anki_cards.json` агент по-прежнему заполняет Word / Word_RU / POS / Sentence / Sentence_RU / Tags; `export_anki.py` собирает Комментарий.
7. После урока карточки **обязательно** мержатся в `master.de.tsv` / `master.en.tsv` **на уровень выше папки урока** (корень курса).
8. **DE nouns** — в `Word`, таблице словаря и Anki **всегда с артиклем**: `der Apfel`, `die Straße`, `das Haus`.
9. **Глаголы — три формы внутри `Word`** (для **всех** глаголов):

### DE verbs

Формат:

```text
lesen (liest · las · hat gelesen)
```

- 3-е лицо ед.ч. Präsens · Präteritum · Perfekt **со вспомогательным** (`hat` / `ist`).
- Источник форм (агент ходит в сеть): **сначала** [verbformen.de](https://www.verbformen.de), если неясно/нет данных — [duden.de](https://www.duden.de).
- Не выдумывать формы по памяти, если есть доступ к сайту.
- Рефлексивы: сохраняй `sich` в лемме и формах, как на verbformen (`sich waschen (wäscht sich · …)`).

### EN verbs

Формат (base · past · past participle):

```text
go (go · went · gone)
work (work · worked · worked)
```

- Для **всех** глаголов (правильных и неправильных).
- Источник: надёжный справочник (Wiktionary / словарь); не выдумывать irregulars.

В таблице «Словарь» в `lesson.md` для глаголов — тот же `Word` с формами в скобках.

## Pipeline (обязательный порядок)

Корень скилла: директория, где лежит этот `SKILL.md`.

### 1) Подготовка сырья (+ кадры только по запросу)

Локальная папка урока:

```bash
python3 scripts/lang_lesson.py "<INPUT_FOLDER>" --config config.json --inplace
```

Со скринами:

```bash
python3 scripts/lang_lesson.py "<INPUT_FOLDER>" --config config.json --inplace --with-frames
```

URL:

```bash
python3 scripts/lang_lesson.py "<INPUT>" --config config.json
```

Скрипт создаёт workdir с:

| Файл | Назначение |
|------|------------|
| `package.json` | метаданные |
| `transcript.txt` | сплошной текст |
| `transcript_timed.txt` | текст с таймкодами |
| `cues.json` | реплики start/end/text |
| `frames/` + `frames.json` | только если frames включены |
| `anki.tsv` | заголовок TSV |
| `run_summary.json` | пути для агента |

### 2) Анализ и заполнение `lesson.md`

Прочитай `transcript_timed.txt` (+ кадры, **если есть**). Заполни шаблон `templates/lesson.md`:

- **Главная идея** — 2–4 предложения
- **Правила** — нумерованный список; скрин — только если кадры включены и кадр информативный
- **Особенности / нюансы**
- **Исключения**
- **Лайфхаки**
- **Типичные ошибки**
- **Примеры с разбором**
- **Словарь** — DE nouns с артиклем; DE/EN verbs с тремя формами в Word
- **Таймкоды** — 5–15 ключевых моментов
- **Теги** — `#de`/`#en`, тема, уровень

Определи `target_lang` из `package.json` (de/en). Уровень угадай по уроку или спроси, если неясно — `не указан`.

#### Кадры (только если включены)

По умолчанию `frames.enabled=false` — **пропустить** весь блок кадров.

Если пользователь просил скрины:

1. Запусти extract / `--with-frames`.
2. Визуально проверь кадры; в `lesson.md` — только слайды/карточки с текстом.
3. Talking-head не вставлять.
4. Добор: `extract_frames.py … --only-timestamps --timestamp …`

### 3) Anki урока + master-словарь

Собери `anki_cards.json` (внутренний формат). Для глаголов — формы в `Word`. Экспорт сам упакует POS+примеры в HTML-`Комментарий`:

```json
{
  "cards": [
    {
      "Word": "der Apfel",
      "Word_RU": "яблоко",
      "POS": "noun",
      "Sentence": "Der Apfel ist rot.",
      "Sentence_RU": "Яблоко красное.",
      "Tags": "de alphabet A1"
    },
    {
      "Word": "lesen (liest · las · hat gelesen)",
      "Word_RU": "читать",
      "POS": "verb",
      "Sentence": "Ich lese ein Buch.",
      "Sentence_RU": "Я читаю книгу.",
      "Tags": "de alphabet A1"
    }
  ]
}
```

TSV после экспорта (пример строки Комментария):

```text
<b>verb</b><br>Ich lese ein Buch.<br><i>Я читаю книгу.</i>
```

В полях допускается HTML для форматирования.

POS: `noun` | `verb` | `adj` | `adv` | `prep` | `conj` | `pron` | `phrase` | `other`.

Правила карточек:

- На каждое важное слово/выражение — одна строка.
- **DE + `noun` → артикль в Word.**
- **`verb` → три формы в Word** (DE и EN).
- `Sentence` — естественный пример из урока или по правилу урока.
- Не дублируй одно и то же слово+POS в пределах урока.
- Теги: `<lang> <topic> <level>`.

```bash
python3 scripts/export_anki.py \
  --from-json <workdir>/anki_cards.json \
  --out <workdir>/anki.tsv \
  --tags "de grammar" \
  --lang de \
  --workdir <workdir> \
  --source "<workdir>/lesson.md" \
  --merge-report <workdir>/master_merge.json
```

Пример: урок `…/Грамматика 2.0/Урок 01/` → master `…/Грамматика 2.0/master.de.tsv`.

#### Логика master

Ключ: **Word + POS**; смысл = **Word_RU**.

| Ситуация | Действие |
|----------|----------|
| Нет Word+POS | **add** |
| Есть Word+POS+тот же Word_RU | **skip** |
| Есть Word+POS, но другой Word_RU | **update** |

### 4) Финал пользователю

- путь к `lesson.md`
- путь к `anki.tsv`
- путь к `master.{lang}.tsv`
- merge: added / updated / skipped
- были ли кадры (да/нет)
- импорт Anki: File → Import → `master.{lang}.tsv` → поля по порядку **Вопрос / Ответ / Комментарий / Метки** (Source/UpdatedAt в master можно игнорировать)

## Настройка скринов

`config.json` → `frames`:

| Поле | Смысл |
|------|--------|
| `enabled` | **по умолчанию `false`** |
| `mode` | `hybrid` \| `even` \| `keyword` |
| `prefer_slides` | скоринг UI/слайдов |
| остальные | см. config.json |

CLI: `--with-frames` включает; `--skip-frames` принудительно выключает.

## Входы

**URL:** yt-dlp. Для скринов — ffmpeg (только если frames on).

**Папка:** видео + `.vtt`/`.srt`.

## Зависимости

```bash
pip install -r requirements.txt
# ffmpeg только если нужны скрины; yt-dlp — для URL
```

```bash
./install.sh
```

## Performance Notes

- По умолчанию без кадров — быстро (только субтитры/пакет).
- Не скачивай видео повторно без нужды; для frames off видео локальной папки можно не трогать для скринов.
- Сначала `lang_lesson.py`, потом LLM-конспект.

## Troubleshooting

| Проблема | Что делать |
|----------|------------|
| Нет субтитров | Положить `.vtt`/`.srt` |
| Нет скринов | Это норма по умолчанию; просили скрины → `--with-frames` + ffmpeg |
| Формы глагола | Перепроверить verbformen.de → duden.de (DE) |
| Пустой Anki | `anki_cards.json` + `export_anki.py --lang …` |
| Master не там | `--workdir`: master в `parent(workdir)` |

## Examples

```text
/lang-lesson /path/to/Урок 01
положи в ту же папку
```

```text
/lang-lesson /path/to/Урок 01
со скринами
```

```text
/lang-lesson https://youtu.be/T_gnTfeDV28
уровень A2
```

