Podnikání Fakturace a výkazy práce Sklad a e-shop Klientský portál AI asistent Účetnictví Účetnictví firem Účetnictví OSVČ Neziskové organizace a SVJ Mzdy Integrace EET 2.0 a mobilní aplikace Integrace a IT partneři Nasazení a bezpečnost Převod účetních dat Produkt Funkce Ceník Provoz u nás Účetní kanceláře Dokumentace Živé demo Manuál a příručky Výuková videa Kompletní dokumentace API Portál podpory Koupit
Blog MyÚčta

Jak jsme z Teams školení vytvořili 11 výukových videí pomocí AI

Z tříhodinového školení vzniklo 2 hodiny a 39 minut výukových videí s českým hlasem, titulky a rychlými přechody. Jak jsme během zhruba pěti hodin a dvaceti minut zapojili Codex, ElevenLabs a automatizaci od scénáře až po přehrávání na webu.

Po školení pro jednu účetní firmu nám zůstal přibližně tříhodinový záznam z Microsoft Teams. Obsahoval praktické ukázky MyÚčta, otázky účastníků i vysvětlení souvislostí. Pro veřejnou videotéku ale potřeboval střih: odstranit přestávky, opakování, odbočky a pár osobních informací, které se při živém školení přirozeně objeví.

Vzali jsme záznam, přepis ve Wordu a manuál aplikace. S pomocí Codexu s modelem GPT 6.1 Sol, ElevenLabs a několika běžných vývojářských nástrojů jsme z nich připravili 11 výukových videí v celkové délce 2 hodiny, 39 minut a 6 sekund. Každé má český komentář, přepínatelné titulky, popis a přesné odkazy na jednotlivá témata. Celou sérii najdete v sekci Výuková videa.

Nejdřív scénář, potom nový hlas

Mluvený výklad potřebuje jinou úpravu než článek. Lektor se vrací k předchozí otázce, opraví se uprostřed věty nebo počká, až se někomu načte obrazovka. Přepis jsme proto prošli obsahově i jazykově. Zachovali jsme postupy, odstranili opakování a osobní vsuvky a spojili věty tak, aby jim rozuměl i člověk, který u školení nebyl.

Codex připravil členění do kapitol, návrhy textace a automatizační skripty. U mzdové části jsme výklad rozšířili podle manuálu, protože původní školení některé postupy jen naznačilo. Přibylo například podrobnější vysvětlení katalogu mzdových složek a jejich mapování na JMHZ. Text prošel také samostatnou revizí. Nové hlasy pro celou sérii se vyráběly až po kontrole scénáře.

Výsledná textace má přibližně 18 400 slov a 98 podkapitol. Lekce jsme členili podle pracovních témat, většinou přibližně na deset až patnáct minut; některé souvislé postupy jsou delší. Účetní si tak může pustit konkrétní úkon místo hledání v tříhodinovém záznamu.

Soukromí se kontroluje v textu i v obraze

Ze záznamu jsme ořízli účastníky schůzky, rozhraní Teams a okraje prohlížeče. Samostatně jsme kontrolovali obrazovky aplikace. Vynechat jméno firmy v komentáři nestačí, pokud je dál vidět ve spodní liště nebo v seznamu zaměstnanců. Úseky s údaji určenými jen pro konkrétního zákazníka jsme do veřejných videí nezařazovali.

Naopak čitelná demo data mají ve školení hodnotu. Plošné zakrytí tabulky by znemožnilo vysvětlit postup. Tam, kde původní obraz nestačil, jsme přes Playwright pořídili nové screenshoty v prohlížeči Microsoft Edge, v ukázkové firmě s demo údaji. Snímky jsme nejdřív prošli v galerii a schválili. Poměr stran zůstal zachovaný, takže formuláře nejsou roztažené a pravý okraj nepřetéká.

ElevenLabs dodal český hlas i časování

Hlas jsme vybírali na krátkých vzorcích. Pro celou sérii nakonec vyhrála Jana. ElevenLabs přes API vytvářel komentář po jednotlivých podkapitolách, což usnadnilo opravy: když se změnila jedna pasáž, stačilo znovu vytvořit jen ji. Použili jsme model Eleven Multilingual v2.

Praktický detail pro vlastní výrobu: API pro řeč s časováním vrací vedle audia i časové údaje jednotlivých znaků. Z nich jsme odvozovali titulky i přechody mezi obrazovkami. U zkratek jako DPH, JMHZ nebo MCP jsme oddělili výslovnost pro hlas od běžného zápisu v titulcích. Divák tak čte „JMHZ“, zatímco hlas vysloví jednotlivá písmena.

Nástroje, které spojily celý postup

  • Microsoft Teams a Word: původní školení a textový přepis jako obsahový základ.
  • Codex s GPT 6.1 Sol: úprava scénáře, rozdělení práce mezi agenty, skripty, kontroly a příprava stránky s přehrávači.
  • ElevenLabs API: český komentář hlasem Jany a časové údaje pro synchronizaci.
  • Python, Pillow a PyAV: práce s texty a metadaty, tvorba schémat a kontrolních galerií, kontrola mediálních souborů.
  • FFmpeg a Intel Quick Sync: ořez, skládání obrazu a zvuku, hardwarové kódování H.264 a sjednocení hlasitosti.
  • faster-whisper a RapidOCR: pomocné časové kotvy přepisu a hledání textů v obraze. Výsledky jsme doplňovali vizuální kontrolou.
  • Playwright a Microsoft Edge: nové snímky skutečné aplikace s demo daty.
  • PHP, JavaScript, SCSS a IIS: katalog lekcí, přehrávače, vzhled a obsluha videí na našem webu. Node.js a gulp sestavily webové soubory, jsdom posloužil k testům ovládání.

Vlastní skripty pracovaly se seznamem podkapitol, texty, audio soubory a obrazovými podklady. Přechody určovaly podle frází v namluveném komentáři. FFmpeg sestavil výsledné MP4 a pomocí filtru loudnorm sjednotil hlasitost. Hotové díly a hlasy se ukládaly do mezipaměti, takže oprava obrázku neznamenala nové placené generování celého komentáře.

Zhruba pět hodin a dvacet minut včetně revizí

První pracovní skripty vznikly 28. října v 16:08, dokončená série byla připravená v 21:27. Od prvních skriptů k hotové sérii tedy uplynulo zhruba pět hodin a dvacet minut. Tento čas zahrnuje výběr hlasu, revize textace, schvalování screenshotů, doplnění mzdových postupů, opravy obrazu, výrobu videí i přípravu jejich přehrávání na webu.

Nezávislé části běžely paralelně. Jeden agent připravoval obrazové podklady, další zpracovával jinou kapitolu nebo kontroloval hotový výstup. Společné soubory a finální zařazení hlídil řídící agent. Při pořizování nových screenshotů jsme převody naopak pozastavili, aby prohlížeč zůstal svižný. Paralelizace se vyplatí tam, kde si úlohy nepřepisují stejná data a nesoutěží o stejný výkon.

Spotřeba: 60 tisíc kreditů a desetina týdenního limitu

ElevenLabs podle přehledu našeho účtu spotřeboval přibližně 60 000 kreditů ze 130 000, tedy asi 46 % dostupného objemu. První měsíc předplatného nás stál 11 USD. Codex pro tento projekt spotřeboval přibližně 10 % týdenního limitu v našem předplatném ChatGPT Pro 500.

Jde o údaje z konkrétního účtu a projektu k 28. říjnu 2026. Částka 11 USD je cena prvního měsíce ElevenLabs; do celkové ekonomiky výroby patří také předplatné Codexu, práce člověka a provoz počítače. Spotřebu kreditů neodvozujeme z počtu znaků scénáře. Převzali jsme ji z účtu, protože záleží na použité službě, modelu a podmínkách tarifu.

Dokončení zahrnovalo titulky, popisky i samotný web

Ke každé lekci vzniklo MP4, české titulky SRT a WebVTT, popis s časovými značkami a metadata podkapitol. SRT je připravené také pro případné nahrání na YouTube. Na našem webu má každá lekce vlastní nadpis, přehrávač, popis a seznam témat s přímým skokem na příslušný čas. Odkaz lze poslat kolegovi rovnou na konkrétní část výkladu.

Jedenáct videí se při otevření stránky nezačne stahovat. Nejdřív se zobrazí lehké náhledy s názvem a logem MyÚčta. Adresa videa i titulky se do přehrávače přidají až po kliknutí; při spuštění další lekce se předchozí média uvolní. To je přísnější řízení než samotný atribut preload="none". Server podporuje načítání částí souboru, takže přeskakování nevyžaduje stažení celého videa.

Jednotlivá videa prošla kontrolou úplným dekódováním. Následovalo 292 souhrnných kontrol souborů, metadat, titulků a kopií pro web a 11 testů ovládání stránky. Obraz jsme kontrolovali také na kontaktních listech a v jednotlivých snímcích. Automatická kontrola pomůže najít chybu v časování, člověk musí posoudit čitelnost obrazovky i správnost postupu.

Postup, který můžete zopakovat: technický návod pro IT

Následující postup je funkční základ pro jeden pilotní díl: jeden schválený screenshot, komentář a přepínatelné titulky. Příklady používají Windows, PowerShell 7, Python 3 a FFmpeg včetně ffprobe dostupné v PATH. Výrobu celé série pak rozšíříte o seznam podkapitol a střídání obrazů podle časových kotev.

1. Oddělte zdroje, texty, placené audio a výstupy

Založte pracovní adresář. Původní záznam a přepis ponechte jako zdroje; hotové soubory ukládejte zvlášť. První blok spusťte z nadřazeného adresáře; vytvoří složku video-kurz a přejde do ní. Všechny další příkazy pak spouštějte z této složky.

New-Item -ItemType Directory -Force -Path .\video-kurz | Out-Null
Set-Location .\video-kurz
'zdroj','texty','screens','audio','titulky','vystup','cache' |
    ForEach-Object { New-Item -ItemType Directory -Force -Path $_ | Out-Null }
python -m pip install python-docx

Do zdroj vložte skoleni.mp4 a prepis.docx. Ukázka převádí přepis tvořený odstavci, obsah tabulek nepřebírá. Pro převod odstavců z Wordu uložte následující soubor jako docx_text.py a spusťte python .\docx_text.py.

from pathlib import Path
from docx import Document

source = Document("zdroj/prepis.docx")
text = "\n\n".join(p.text for p in source.paragraphs if p.text.strip())
Path("texty/prepis.txt").write_text(text, encoding="utf-8")

2. Nechte AI připravit scénář s dohledatelnými zdroji

Codexu dejte přepis i manuál, pojmenujte soukromé pasáže a požadujte strojově čitelný výstup. Použít můžete například toto zadání:

Rozděl přepis do tematických lekcí a kratších podkapitol.
Pro každou vrať ID, název, stručný popis, finální český text,
zdrojovou pasáž a seznam potřebných obrazovek.
Odstraň přestávky, opakování a označené osobní informace.
Nové kroky dolož konkrétní částí manuálu.
Kde chybí obraz, napiš požadavek na screenshot; nic si nevymýšlej.
Zatím nevolej hlasové API a nepřeváděj videa.

Po revizi uložte jednu podkapitolu do texty/10-00.txt. Pilot může začínat například „Otevřete katalog mzdových složek.“ Identifikátor 10-00 propojí text, audio, titulky i obraz. Zkontrolujte také vyslovování zkratek; při fonetické úpravě textu pro hlas budete potřebovat převést časování zpět na běžný zápis titulků.

3. Připravte skutečný obraz a ověřte ořez

Získejte první kontrolní snímek ze záznamu. Čas v příkladu nahraďte vhodným místem svého školení. Prohlédněte účastníky, firemní lišty, otevřené dokumenty i údaje v tabulkách.

ffmpeg -hide_banner -y -ss 00:05:00 -i .\zdroj\skoleni.mp4 `
    -frames:v 1 .\screens\kontrola.png
if ($LASTEXITCODE -ne 0) { throw 'Extrakce snímku selhala.' }

Pokud záznam potřebuje ořez, filtr má tvar crop=šířka:výška:x:y. Například crop=1424:976:120:104 odpovídá jednomu konkrétnímu rozložení našeho zdroje. Souřadnice si změřte na svém snímku a před hromadným zpracováním ořez ověřte. Citlivou obrazovku nahraďte schválenou ukázkou s demo daty.

Při snímání nové obrazovky přes Playwright nejdřív otevřete správnou firmu, vyčkejte na dokončené načtení a až potom pořiďte screenshot. Následující řádek patří do již připojené a přihlášené browser session:

await page.screenshot({ path: 'screens/10-00.png', fullPage: false });

Pro další kroky použijte schválený obrázek screens/10-00.png. Jeho obsah musí odpovídat mluvenému textu.

4. Vygenerujte jednu podkapitolu přes ElevenLabs API

Do prostředí procesu nastavte ELEVENLABS_API_KEY a ELEVENLABS_VOICE_ID. ID vybraného hlasu vezměte ze svého účtu. Klíč zůstává mimo skript. Následující volání je placená operace: spusťte ho až pro schválený text, nikoli při každém renderu.

if (-not $env:ELEVENLABS_API_KEY -or -not $env:ELEVENLABS_VOICE_ID) {
    throw 'Chybí API klíč nebo ID hlasu v prostředí.'
}
if (Test-Path -LiteralPath .\audio\10-00.mp3) {
    throw 'Audio už existuje. Nové generování musí být záměrné.'
}
$text = Get-Content -LiteralPath .\texty\10-00.txt -Raw -Encoding utf8
$body = @{
    text = $text.Trim()
    model_id = 'eleven_multilingual_v2'
    voice_settings = @{
        stability = 0.65
        similarity_boost = 0.75
        style = 0
        use_speaker_boost = $true
        speed = 1.0
    }
} | ConvertTo-Json -Depth 5
$result = Invoke-RestMethod -Method Post `
    -Uri "https://api.elevenlabs.io/v1/text-to-speech/$($env:ELEVENLABS_VOICE_ID)/with-timestamps" `
    -Headers @{ 'xi-api-key' = $env:ELEVENLABS_API_KEY } `
    -ErrorAction Stop -ContentType 'application/json; charset=utf-8' `
    -Body ([Text.Encoding]::UTF8.GetBytes($body))
[IO.File]::WriteAllBytes(
    (Join-Path $PWD 'audio\10-00.mp3'),
    [Convert]::FromBase64String($result.audio_base64)
)
$result | Select-Object alignment,normalized_alignment |
    ConvertTo-Json -Depth 100 |
    Set-Content -LiteralPath .\audio\10-00.json -Encoding utf8

MP3 a JSON uchovejte spolu. Pro větší sérii počítejte SHA-256 z textu, modelu, hlasu a jeho nastavení. Shodný otisk znamená, že můžete použít existující audio; změněný screenshot jeho regeneraci nevyžaduje. API zde neposíláme žádný záznam schůzky, jen schválený text komentáře.

5. Z časování vytvořte SRT a WebVTT

Soubor make_subtitles.py níže rozdělí řeč po slovech do nejvýše dvou řádků a přibližně pětisekundových úseků. Používá časování vrácené ke stejnému komentáři, takže nepotřebujete další placený přepis nového audia. Spusťte python .\make_subtitles.py.

import json
import re
import textwrap
from pathlib import Path

a = json.loads(Path("audio/10-00.json").read_text(encoding="utf-8-sig"))["alignment"]
text = "".join(a["characters"])
starts = a["character_start_times_seconds"]
ends = a["character_end_times_seconds"]
assert len(text) == len(starts) == len(ends) and text.strip()
words = list(re.finditer(r"\S+", text))

def lines(group):
    return textwrap.wrap(" ".join(w.group() for w in group), width=42,
                         break_long_words=False, break_on_hyphens=False)

def stamp(seconds):
    ms = round(max(0, seconds) * 1000)
    hours, ms = divmod(ms, 3600000)
    minutes, ms = divmod(ms, 60000)
    seconds, ms = divmod(ms, 1000)
    return f"{hours:02}:{minutes:02}:{seconds:02},{ms:03}"

groups, group = [], []
for word in words:
    candidate = group + [word]
    if group and (len(lines(candidate)) > 2 or
                  ends[word.end()-1] - starts[group[0].start()] > 5):
        groups.append(group)
        group = []
    group.append(word)
if group:
    groups.append(group)

blocks = []
for index, group in enumerate(groups, 1):
    begin = starts[group[0].start()]
    end = ends[group[-1].end()-1]
    blocks.append(f"{index}\n{stamp(begin)} --> {stamp(end)}\n" + "\n".join(lines(group)))
srt = "\n\n".join(blocks) + "\n"
Path("titulky/10-00.srt").write_text(srt, encoding="utf-8")
vtt = "WEBVTT\n\n" + re.sub(r"(\d{2}:\d{2}:\d{2}),(\d{3})", r"\1.\2", srt)
Path("titulky/10-00.cs.vtt").write_text(vtt, encoding="utf-8")

6. Sestavte pilotní MP4 s přepínatelnými titulky

Nejdřív zjistěte délku komentáře. Potom FFmpeg opakuje obrázek přesně po tuto dobu, zachová poměr stran a přidá nové audio i textovou stopu. Příklad používá softwarový enkodér libx264, aby nevyžadoval konkrétní grafický čip. V naší výrobě kódování urychloval Intel Quick Sync.

$audioSeconds = & ffprobe -v error -show_entries format=duration `
    -of default=noprint_wrappers=1:nokey=1 .\audio\10-00.mp3
if ($LASTEXITCODE -ne 0) { throw 'Délku audia se nepodařilo načíst.' }

ffmpeg -hide_banner -y -loop 1 -framerate 25 -i .\screens\10-00.png `
    -i .\audio\10-00.mp3 -i .\titulky\10-00.srt `
    -map 0:v:0 -map 1:a:0 -map 2:0 `
    -vf 'scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:color=0x291e50,setsar=1' `
    -c:v libx264 -preset veryfast -crf 21 -pix_fmt yuv420p `
    -c:a aac -b:a 160k -ar 48000 -c:s mov_text `
    -metadata:s:a:0 language=ces -metadata:s:s:0 language=ces `
    -t ($audioSeconds.Trim()) -movflags +faststart .\vystup\10-00.mp4
if ($LASTEXITCODE -ne 0) { throw 'Výroba pilotního videa selhala.' }

Pro více obrazovek si uložte seznam přechodů a jejich fráze. V časování vyhledejte začátek fráze, přečtěte její čas a převeďte ho na snímek: round(čas × 25). Délka záběru je rozdíl začátků dvou sousedních záběrů. Poslední obraz končí s komentářem. Záznam níže je příklad vstupu pro vlastní řídící skript; FFmpeg takový JSON sám nenačítá.

{
  "id": "10-00",
  "audio": "audio/10-00.mp3",
  "visuals": [
    {"path": "screens/katalog.png", "offset": 0},
    {"path": "screens/mapovani.png", "phrase": "Pro mapování otevřete"}
  ]
}

Při sestavování původního pohyblivého záběru mapujte jen jeho video a nové hlasové audio. Původní zvuk schůzky se do výstupu nemá přimíchat. Po sestavení více podkapitol přičtěte jejich skutečné délky k titulkům a časům podkapitol; zahrňte také úvodní kartu a případné pauzy.

7. Zkontrolujte soubor a připravte web

ffmpeg -hide_banner -v error -threads 2 -i .\vystup\10-00.mp4 `
    -map 0:v:0 -map 0:a:0 -f null NUL
if ($LASTEXITCODE -ne 0) { throw 'Kontrola dekódování selhala.' }
ffprobe -v error -show_streams -show_format .\vystup\10-00.mp4
Get-FileHash -LiteralPath .\vystup\10-00.mp4 -Algorithm SHA256

Prohlédněte také začátky a konce všech záběrů, vyzkoušejte titulky a porovnejte jejich text se scénářem. Záznam kontroly spojte s SHA-256 hotového MP4, abyste věděli, kterou verzi jste skutečně ověřili.

Na web nahrajte 10-00.mp4 a 10-00.cs.vtt do media/videa. Následující minimální přehrávač stáhne média až po kliknutí a umí start podle odkazu #cas=20. Soubor stránky musí mít kódování UTF-8.

<button id="start" type="button">Přehrát lekci</button>
<video id="lesson" controls preload="none" playsinline hidden
       style="width:100%;max-width:1080px"></video>
<script>
const start = document.getElementById('start');
const video = document.getElementById('lesson');
start.addEventListener('click', () => {
    start.hidden = true;
    video.hidden = false;
    const requested = Number(new URLSearchParams(location.hash.slice(1)).get('cas') || 0);
    video.addEventListener('loadedmetadata', () => {
        video.currentTime = Number.isFinite(requested)
            ? Math.max(0, Math.min(requested, video.duration)) : 0;
        video.play().catch(error => console.warn('Spusťte přehrávání ovládáním videa.', error));
    }, { once: true });
    const track = document.createElement('track');
    track.kind = 'subtitles';
    track.srclang = 'cs';
    track.label = 'Česky';
    track.src = '/media/videa/10-00.cs.vtt';
    track.default = true;
    video.append(track);
    video.src = '/media/videa/10-00.mp4';
    video.load();
}, { once: true });
</script>

Na IIS nastavte pro .vtt MIME typ text/vtt a pro .mp4 typ video/mp4. Ověřte částečné stahování souboru:

$r = Invoke-WebRequest `
    -Uri 'https://vas-web.example/media/videa/10-00.mp4' `
    -Headers @{ Range = 'bytes=0-1023' }
$r.StatusCode
$r.Headers['Content-Range']

Očekáváte stav 206 a odpovídající Content-Range. Pro celou videotéku doplňte katalog JSON s názvy, popisy a skutečnými časy. Při spuštění jiné lekce původní video pozastavte, odeberte jeho src i stopy a zavolejte load(). Odkaz s časem může nejdřív pouze vybrat náhled; načtení nechte na kliknutí uživatele.

8. Teprve potom rozšiřte výrobu na celou sérii

Každé podkapitole ponechte samostatné ID, soubory a kontrolní otisk. Placené generování hlasu, render a publikaci spouštějte odděleně. Paralelně zpracovávejte různé kapitoly ve vlastních pracovních adresářích; společný katalog nechte zapisovat jen jednomu procesu. Při změně obrázku znovu sestavte obrazový díl a výsledné MP4, při změně textu obnovte také příslušné audio a jeho časování. Tak zůstane další aktualizace výuky rychlá a dohledatelná.

Pro účetní kancelář to znamená možnost vrátit se ke konkrétnímu postupu i několik týdnů po školení. Nový kolega dostane stejný výklad a zkušenější účetní přeskočí přímo na část, kterou potřebuje. Otevřete si hotovou videotéku MyÚčta a vyzkoušejte třeba přímý skok na katalog mzdových složek a mapování na JMHZ.

Chcete si postup projít na konkrétní firmě?V živém demo jsou připravená data pro pohled účetní i klienta.
Otevřít živé demo

Další články z blogu

30. září 2026Zeptejte se své firmy: s MyÚčtem si majitel povídá, klidně z mobilu cestou v autěČíst článek
25. září 2026Rolls-Royce mezi online systémy pro firmy: od faktury po kontrolní hlášení bez účetníhoČíst článek
21. srpna 2026Přímé podání přes EPO: s osobním certifikátem odešlete přiznání jedním kliknutímČíst článek