Zobrazují se příspěvky se štítkemskript. Zobrazit všechny příspěvky
Zobrazují se příspěvky se štítkemskript. Zobrazit všechny příspěvky

sobota 31. ledna 2026

Python script: Změna časů chainů a markerů mlt souboru pro zdrojové video 2x zrychlené

 

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
fix_times_one_script_fixed.py
Opravená verze — škáluje jen to, co se smí (bez double-scalingu a bez škálování length média)
"""

from xml.etree import ElementTree as ET
from pathlib import Path
from decimal import Decimal, getcontext, ROUND_HALF_UP
import re, shutil, sys

# ======= NASTAVENÍ =======
INPUT_FILE  = Path("./Jede vlak.mlt")
OUTPUT_FILE = Path("./Jede vlak_fixed.mlt")
SCALE = Decimal("0.5")                          # 0.5 = polovina času
RESOURCE_FROM = "/1/"                           # nebo None
RESOURCE_TO   = "/2/"
# ==================================================

getcontext().prec = 28
getcontext().rounding = ROUND_HALF_UP

TIME_RE = re.compile(r'^(?P<h>\d{2}):(?P<m>\d{2}):(?P<s>\d{2})(?:\.(?P<frac>\d+))?$')

def parse_time_to_decimal(text):
    if text is None:
        return None, 0
    t = text.strip()
    m = TIME_RE.match(t)
    if not m:
        return None, 0
    h = int(m.group('h'))
    mm = int(m.group('m'))
    ss = int(m.group('s'))
    frac = m.group('frac') or ""
    frac_len = len(frac)
    frac_dec = Decimal("0." + frac) if frac_len > 0 else Decimal(0)
    total = Decimal(h)*3600 + Decimal(mm)*60 + Decimal(ss) + frac_dec
    return total, frac_len

def format_decimal_seconds(total_seconds: Decimal, frac_len: int = 3):
    if total_seconds < 0:
        total_seconds = Decimal(0)
    hours = int(total_seconds // 3600)
    rem = total_seconds - Decimal(hours)*3600
    minutes = int(rem // 60)
    sec_dec = rem - Decimal(minutes)*60
    if frac_len > 0:
        q = Decimal(1).scaleb(-frac_len)
        sec_q = sec_dec.quantize(q, rounding=ROUND_HALF_UP)
        if sec_q >= 60:
            sec_q -= 60
            minutes += 1
            if minutes >= 60:
                minutes -= 60
                hours += 1
        frac_part = f"{sec_q - int(sec_q):.{frac_len}f}"[1:]
        sec_str = f"{int(sec_q):02d}{frac_part}"
    else:
        sec_str = f"{int(sec_dec):02d}"
    return f"{hours:02d}:{minutes:02d}:{sec_str}"

def scale_time_text(txt, scale):
    total, frac_len = parse_time_to_decimal(txt)
    if total is None:
        return None
    new_total = total * scale
    target_frac = frac_len if frac_len > 0 else 3
    return format_decimal_seconds(new_total, target_frac)

def backup_file(p: Path):
    bak = p.with_suffix(p.suffix + ".bak")
    if not bak.exists():
        shutil.copy2(p, bak)
    return bak

def main():
    if not INPUT_FILE.exists():
        print("Chyba: vstupní soubor nenalezen:", INPUT_FILE)
        sys.exit(1)
    xml = INPUT_FILE.read_text(encoding="utf-8")
    root = ET.fromstring(xml)

    counts = {"tractor":0, "chain_out":0, "playlist_entry":0, "markers":0, "resource_repl":0}
    samples = []

    # 1. playlist entry in/out
    for playlist in root.findall(".//playlist"):
        for entry in playlist.findall("entry"):
            for a in ("in", "out"):
                v = entry.get(a)
                new = scale_time_text(v, SCALE) if v else None
                if new:
                    entry.set(a, new)
                    counts["playlist_entry"] += 1
                    samples.append(("playlist_entry", entry.get("producer"), a, v, new))

    # 2. tractor in/out
    for tractor in root.findall(".//tractor"):
        for a in ("in", "out"):
            v = tractor.get(a)
            new = scale_time_text(v, SCALE) if v else None
            if new:
                tractor.set(a, new)
                counts["tractor"] += 1
                samples.append(("tractor", tractor.get("id"), a, v, new))

    # 3. chains: ŠKÁLUJEME POUZE out atribut (NE length property!)
    for chain in root.findall(".//chain"):
        for a in ("in", "out"):   # in obvykle není, ale pro jistotu
            v = chain.get(a)
            new = scale_time_text(v, SCALE) if v else None
            if new:
                chain.set(a, new)
                counts["chain_out"] += 1
                samples.append(("chain_out", chain.get("id"), a, v, new))
        # ŽÁDNÉ škálování <property name="length"> !!!

        # resource replacement (pokud chceš)
        if RESOURCE_FROM:
            for prop in chain.findall("property[@name='resource']"):
                if prop.text:
                    old = prop.text
                    newres = old.replace(RESOURCE_FROM, RESOURCE_TO)
                    if newres != old:
                        prop.text = newres
                        counts["resource_repl"] += 1
                        samples.append(("resource", chain.get("id"), old, newres))

    # 4. markery – jen jednou!
    for props in root.findall(".//properties[@name='shotcut:markers']"):
        for marker in props.findall("properties"):
            for prop_name in ("start", "end"):
                prop = marker.find(f"property[@name='{prop_name}']")
                if prop is not None and prop.text:
                    new = scale_time_text(prop.text, SCALE)
                    if new:
                        prop.text = new
                        counts["markers"] += 1
                        samples.append((f"marker_{prop_name}", marker.get("name"), prop.text, new))

    # ZÁLOHA + ZÁPIS
    bak = backup_file(INPUT_FILE)
    print("Záloha:", bak)
    OUTPUT_FILE.write_text(ET.tostring(root, encoding="utf-8", method="xml").decode("utf-8"), encoding="utf-8")
    print("Uloženo:", OUTPUT_FILE)

    # Souhrn
    print("\nZměny:")
    for k, v in counts.items():
        print(f" - {k}: {v}")
    print("\nUkázka (prvních 30):")
    for s in samples[:30]:
        print(s)

if __name__ == "__main__":
    main()

sobota 13. prosince 2025

Přesměrování audia do virtuálního sinku a vytvoření sinku

 

pactl load-module module-null-sink sink_name=MySink sink_properties=device.description=MySink

Tím vznikne MySink + zdroj MySink.monitor (ten použiješ jako záznamový zdroj v Audacity).

 

 

$ pactl load-module module-null-sink sink_name=MySink sink_properties=device.description=MySink
536870913
user@Toshi:~$ pactl list short sinks
pactl list short sources
64786    alsa_output.pci-0000_00_1b.0.pro-output-0    PipeWire    s32le 2 ch 48000 Hz    SUSPENDED
64787    alsa_output.pci-0000_00_1b.0.pro-output-3    PipeWire    s32le 8 ch 48000 Hz    SUSPENDED
65030    MySink    PipeWire    float32le 2 ch 48000 Hz    SUSPENDED
64786    alsa_output.pci-0000_00_1b.0.pro-output-0.monitor    PipeWire    s32le 2 ch 48000 Hz    SUSPENDED
64787    alsa_output.pci-0000_00_1b.0.pro-output-3.monitor    PipeWire    s32le 8 ch 48000 Hz    SUSPENDED
64788    alsa_input.pci-0000_00_1b.0.pro-input-0    PipeWire    s32le 2 ch 48000 Hz    RUNNING
65030    MySink.monitor    PipeWire    float32le 2 ch 48000 Hz    SUSPENDED
user@Toshi:~$
 

Aktivní sink inputs:

pactl list short sink-inputs

713    64786    712    PipeWire    s16le 1 ch 44100 Hz
 

ZRUŠENÍ ZAVEDENÉHO SINKU

pactl unload-module module-null-sink
pactl unload-module module-loopback

ZKUSÍM ZAVÉST VIRTUÁLNÍ ZDROJ

pactl load-module module-virtual-source source_name=MixSource source_properties=device.description=MixSource

$ pactl list short sources
66660    alsa_output.pci-0000_00_1b.0.pro-output-0.monitor    PipeWire    s32le 2 ch 48000 Hz    SUSPENDED
66661    alsa_output.pci-0000_00_1b.0.pro-output-3.monitor    PipeWire    s32le 8 ch 48000 Hz    SUSPENDED
66662    alsa_input.pci-0000_00_1b.0.pro-input-0    PipeWire    s32le 2 ch 48000 Hz    RUNNING
67689    output.MixSource    PipeWire    float32le 2 ch 48000 Hz    SUSPENDED
 


BASH SKRIPT PRO ZAVEDENÍ SINKU - K NIČEMU, AUDACITY NEPRACUJE S VIRTUÁLNÍM SINKEM ALE SOURCEM

 

#!/usr/bin/env bash
# Komfortní skript pro vytvoření "MySink" (null sink) + loopbacku
# Pro Linux Mint 21.3 (PulseAudio on PipeWire kompatibilita přes pactl)
# - start  : vytvoří null sink a loopback (idempotentní)
# - stop   : odstraní moduly načtené tímto skriptem
# - status : zobrazí stav (pactl list short ...)
# - install-autostart / remove-autostart : vytvoří/odstraní .desktop pro spouštění při přihlášení
#
# Poznámky:
# - Skript pracuje v uživatelském sezení (NESPUSŤTE SUDO!).
# - Výchozí fyzický sink je nastaven podle dat, které jsi poslal:
#   alsa_output.pci-0000_00_1b.0.pro-output-0
#   Pokud máš jiný, nastav proměnnou PHYSICAL_SINK před spuštěním nebo uprav v souboru.
# - Moduly načtené skriptem ukládá do ~/.config/mysink/modules.ids
#
set -euo pipefail

CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/mysink"
MODULES_FILE="$CONFIG_DIR/modules.ids"
SCRIPT_PATH="$(realpath "$0")"

NULL_SINK_NAME="MySink"
PHYSICAL_SINK="${PHYSICAL_SINK:-alsa_output.pci-0000_00_1b.0.pro-output-0}"
LATENCY_MS="50"
AUTOSTART_DESKTOP="$HOME/.config/autostart/mysink-start.desktop"

mkdir -p "$CONFIG_DIR"

function ensure_pactl() {
  if ! command -v pactl >/dev/null 2>&1; then
    echo "Chyba: pactl nenalezen. Nainstaluj Pulse/pipewire-pulse nebo zkontroluj PATH." >&2
    exit 1
  fi
}

function save_module_id() {
  local key="$1" id="$2"
  mkdir -p "$(dirname "$MODULES_FILE")"
  # replace key if exists
  if grep -q "^${key}=" "$MODULES_FILE" 2>/dev/null; then
    sed -i "s/^${key}=.*/${key}=${id}/" "$MODULES_FILE"
  else
    echo "${key}=${id}" >> "$MODULES_FILE"
  fi
}

function get_saved_module_id() {
  local key="$1"
  if [ -f "$MODULES_FILE" ]; then
    awk -F= -v k="$key" '$1==k{print $2}' "$MODULES_FILE" || true
  fi
}

function start() {
  ensure_pactl

  # 1) vytvořit null sink pokud neexistuje
  if pactl list short sinks | awk '{print $2}' | grep -xq "$NULL_SINK_NAME"; then
    echo "Null sink '$NULL_SINK_NAME' již existuje."
  else
    echo "Vytvářím null sink '$NULL_SINK_NAME'..."
    module_id=$(pactl load-module module-null-sink sink_name="$NULL_SINK_NAME" sink_properties=device.description="$NULL_SINK_NAME")
    echo "Načten modul module-null-sink id=$module_id"
    save_module_id NULL "$module_id"
  fi

  # 2) vytvořit loopback (MySink.monitor -> PHYSICAL_SINK) pokud neexistuje
  # zkusíme najít existující loopback s odpovídajícími parametry
  existing_loopback_id=$(pactl list short modules | awk '$2=="module-loopback"{print $1" "$0}' | grep "source=${NULL_SINK_NAME}.monitor" | grep "sink=${PHYSICAL_SINK}" | awk '{print $1}' || true)
  if [ -n "$existing_loopback_id" ]; then
    echo "Loopback již existuje (module id=$existing_loopback_id)."
    save_module_id LOOPBACK "$existing_loopback_id"
  else
    echo "Vytvářím loopback z ${NULL_SINK_NAME}.monitor do ${PHYSICAL_SINK}..."
    loop_id=$(pactl load-module module-loopback source=${NULL_SINK_NAME}.monitor sink=${PHYSICAL_SINK} latency_msec=${LATENCY_MS})
    echo "Načten modul module-loopback id=$loop_id"
    save_module_id LOOPBACK "$loop_id"
  fi

  echo
  echo "Hotovo. Stav (krátký přehled):"
  pactl list short sinks
  pactl list short sources
  pactl list short sink-inputs
  pactl list short modules | grep -E "module-null-sink|module-loopback" || true
  echo
  echo "Pokud chceš nahrávat v Audacity, vyber jako záznamový zdroj: Monitor of ${NULL_SINK_NAME}."
}

function stop() {
  ensure_pactl
  local loop_id saved_null saved_loop
  saved_loop=$(get_saved_module_id LOOPBACK || true)
  saved_null=$(get_saved_module_id NULL || true)

  if [ -n "$saved_loop" ]; then
    echo "Odstraňuji loopback (module id=$saved_loop)..."
    pactl unload-module "$saved_loop" || echo "Nepodařilo se unload-module $saved_loop" >&2
    sed -i "/^LOOPBACK=/d" "$MODULES_FILE" 2>/dev/null || true
  else
    echo "Loopback nebyl nalezen v uložených modulech. Hledám v běžících modulech..."
    # pokusit se najít a unload
    found=$(pactl list short modules | awk '$2=="module-loopback"{print $1" "$0}' | grep "source=${NULL_SINK_NAME}.monitor" | grep "sink=${PHYSICAL_SINK}" | awk '{print $1}' || true)
    if [ -n "$found" ]; then
      echo "Odstraňuji loopback module id=$found"
      pactl unload-module "$found" || true
    else
      echo "Loopback nenalezen."
    fi
  fi

  if [ -n "$saved_null" ]; then
    echo "Odstraňuji null sink (module id=$saved_null)..."
    pactl unload-module "$saved_null" || echo "Nepodařilo se unload-module $saved_null" >&2
    sed -i "/^NULL=/d" "$MODULES_FILE" 2>/dev/null || true
  else
    echo "Null sink nebyl nalezen v uložených modulech. Hledám v běžících modulech..."
    found_null=$(pactl list short modules | awk '$2=="module-null-sink"{print $1" "$0}' | grep "sink_name=${NULL_SINK_NAME}" | awk '{print $1}' || true)
    if [ -n "$found_null" ]; then
      echo "Odstraňuji module id=$found_null"
      pactl unload-module "$found_null" || true
    else
      echo "Null sink nenalezen."
    fi
  fi

  echo "Hotovo."
}

function status() {
  ensure_pactl
  echo "=== pactl info ==="
  pactl info
  echo
  echo "=== sinks ==="
  pactl list short sinks
  echo
  echo "=== sources ==="
  pactl list short sources
  echo
  echo "=== sink-inputs ==="
  pactl list short sink-inputs
  echo
  echo "=== modules (null-sink / loopback) ==="
  pactl list short modules | grep -E "module-null-sink|module-loopback" || true
  echo
  echo "Uložené module ids (pokud existují):"
  [ -f "$MODULES_FILE" ] && cat "$MODULES_FILE" || echo "(žádné)"
}

function install_autostart() {
  mkdir -p "$(dirname "$AUTOSTART_DESKTOP")"
  cat > "$AUTOSTART_DESKTOP" <<EOF
[Desktop Entry]
Type=Application
Name=MySink autostart
Exec=${SCRIPT_PATH} start
X-GNOME-Autostart-enabled=true
NoDisplay=false
Comment=Vytvori MySink a loopback pri prihlaseni
Terminal=false
EOF
  echo "Vytvořen: $AUTOSTART_DESKTOP"
}

function remove_autostart() {
  if [ -f "$AUTOSTART_DESKTOP" ]; then
    rm -f "$AUTOSTART_DESKTOP"
    echo "Odstraněn: $AUTOSTART_DESKTOP"
  else
    echo "Autostart soubor neexistuje: $AUTOSTART_DESKTOP"
  fi
}

function help() {
  cat <<EOF
Pouziti: $0 {start|stop|status|install-autostart|remove-autostart|help}

Př.: $0 start            # vytvoří MySink + loopback
     $0 stop             # odstraní moduly vytvořené tímto skriptem
     $0 status           # zobrazí stav pactl
     $0 install-autostart # spustí při přihlášení
     $0 remove-autostart  # smaže autostart

Proměnné prostředí:
  PHYSICAL_SINK     - jméno fyzického sinku (default: $PHYSICAL_SINK)
  NULL_SINK_NAME    - název virtuálního sinku (default: $NULL_SINK_NAME)
  LATENCY_MS        - latence pro loopback (ms)

Poznámka: Spouštěj bez sudo (v uživatelském sezení). Pokud používáš jiný fyzický sink,
        nastav PHYSICAL_SINK před spuštěním nebo uprav řetězec v souboru.
EOF
}

# main
if [ $# -lt 1 ]; then
  help
  exit 0
fi

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  status)
    status
    ;;
  install-autostart)
    install_autostart
    ;;
  remove-autostart)
    remove_autostart
    ;;
  help|--help|-h)
    help
    ;;
  *)
    echo "Neznama volba: $1" >&2
    help
    exit 2
    ;;
esac
 

 

pátek 13. září 2024

curl: Simulace komunikace se serverem

Pokračuji v předchozím článku o curl a hlavíčkách (stahování souborů a hlavičky).

Pro simulaci celé komunikace, jak je popsána v minulém díle o hlavičkách, můžeme použít curl v Bashi s nastavenými hlavičkami pro oba požadavky – první požadavek na HTML soubor ze serveru zp....cz a druhý požadavek na JavaScript soubor ze serveru freeprivacypolicy.com. Ukážeme, jak přesně nasimulovat odesílání hlaviček a zpracování odpovědí. Níže je ukázka:

1. První požadavek: Stažení HTML souboru z zp....cz

curl -X GET "https://zp....cz/" \
-H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8" \
-H "Accept-Encoding: gzip, deflate, br, zstd" \
-H "Accept-Language: cs,sk;q=0.8,en-US;q=0.5,en;q=0.3" \
-H "Connection: keep-alive" \
-H "DNT: 1" \
-H "Host: zp....cz" \
-H "Priority: u=0, i" \
-H "Sec-Fetch-Dest: document" \
-H "Sec-Fetch-Mode: navigate" \
-H "Sec-Fetch-Site: none" \
-H "Sec-Fetch-User: ?1" \
-H "Sec-GPC: 1" \
-H "Upgrade-Insecure-Requests: 1" \
-H "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0" \
--compressed --verbose

Parametr -X v příkazu curl specifikuje HTTP metodu, kterou chceš použít pro daný požadavek. Ve tvém případě:

  • -X GET říká curl, aby použil metodu GET, což je nejběžnější metoda pro získání dat z URL (např. stažení webové stránky nebo souboru). Ve většině případů curl implicitně používá metodu GET, takže tento parametr není nutný, pokud neplánuješ použít jinou metodu (např. POST, PUT, DELETE).

2. Druhý požadavek: Stažení JavaScript souboru z freeprivacypolicy.com

curl -X GET "https://www.freeprivacypolicy.com/public/cookie-consent/4.0.0/cookie-consent.js" \
  -H "Accept: */*" \
  -H "Accept-Encoding: gzip, deflate, br, zstd" \
  -H "Accept-Language: cs,sk;q=0.8,en-US;q=0.5,en;q=0.3" \
  -H "Connection: keep-alive" \
  -H "DNT: 1" \
  -H "Host: www.freeprivacypolicy.com" \
  -H "Priority: u=2" \
  -H "Referer: https://zp....cz/" \
  -H "Sec-Fetch-Dest: script" \
  -H "Sec-Fetch-Mode: no-cors" \
  -H "Sec-Fetch-Site: cross-site" \
  -H "Sec-GPC: 1" \
  -H "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0" \
  --compressed --verbose


Vysvětlení parametrů:

  • -H – nastavuje hlavičky požadavku.
  • --compressed – povoluje podporu kompresí jako gzip, br, deflate.
  • --verbose – zobrazí detaily komunikace, včetně přijatých a odeslaných hlaviček, což simuluje sledování celé komunikace.

Tímto způsobem bude curl odesílat požadavky s příslušnými hlavičkami a zpracovávat odpovědi, jak jsou uvedeny v komunikaci.

Uložení cookies

Hlavičky odpovědi, zejména cookies, jsou velmi důležité pro následné požadavky na stejný server. Když server v odpovědi nastaví cookies (například Set-Cookie), klient (v tomto případě tvůj Bash skript s curl) by měl tyto cookies uložit a použít je při dalších požadavcích. Tyto cookies mohou sloužit k udržení stavu session (např. pomocí PHPSESSID) nebo k identifikaci uživatele (např. pomocí kdojeto).

Jak správně zpracovat hlavičky odpovědi a cookies pomocí curl:

  1. Ukládání cookies: Když server nastaví cookies, je potřeba je uložit do souboru, abys je mohl při dalších požadavcích použít.
  2. Zasílání cookies zpět: Při dalších požadavcích je nutné tyto uložené cookies posílat zpět na server, aby mohl server pokračovat v komunikaci na základě session nebo jiných informací.

Simulace v Bash pomocí curl:

Zde je skript, který provede:

  • Stažení HTML stránky a uložení cookies do souboru.
  • Stažení JS souboru s použitím těchto cookies a simulací hlaviček.

#!/bin/bash

# URL serveru
BASE_URL="https://zp...cz"
JS_URL="https://www.freeprivacypolicy.com/public/cookie-consent/4.0.0/cookie-consent.js"

# Soubor, do kterého se uloží cookies
COOKIE_FILE="cookies.txt"

# První požadavek - stáhnutí HTML
curl -s -c "$COOKIE_FILE" \
  -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8" \
  -H "Accept-Encoding: gzip, deflate, br, zstd" \
  -H "Accept-Language: cs,sk;q=0.8,en-US;q=0.5,en;q=0.3" \
  -H "Connection: keep-alive" \
  -H "DNT: 1" \
  -H "Host: zp....cz" \
  -H "Sec-Fetch-Dest: document" \
  -H "Sec-Fetch-Mode: navigate" \
  -H "Sec-Fetch-Site: none" \
  -H "Sec-Fetch-User: ?1" \
  -H "Upgrade-Insecure-Requests: 1" \
  -H "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0" \
  "$BASE_URL/"

# Druhý požadavek - stažení JS souboru s použitím uložených cookies
curl -s -b "$COOKIE_FILE" \
  -H "Accept: */*" \
  -H "Accept-Encoding: gzip, deflate, br, zstd" \
  -H "Accept-Language: cs,sk;q=0.8,en-US;q=0.5,en;q=0.3" \
  -H "Connection: keep-alive" \
  -H "DNT: 1" \
  -H "Host: www.freeprivacypolicy.com" \
  -H "Referer: $BASE_URL/" \
  -H "Sec-Fetch-Dest: script" \
  -H "Sec-Fetch-Mode: no-cors" \
  -H "Sec-Fetch-Site: cross-site" \
  -H "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0" \
  "$JS_URL"

Vysvětlení:

  1. První curl příkaz stáhne HTML stránku a uloží cookies do souboru cookies.txt. Používáme různé hlavičky, jako například Accept-Encoding a User-Agent, aby komunikace vypadala jako běžný prohlížeč.

  2. Druhý curl příkaz stáhne JS soubor, ale tentokrát použije uložené cookies (-b "$COOKIE_FILE"). Zasíláme také hlavičku Referer, která ukazuje, odkud byl požadavek odeslán (v tomto případě z zp....cz).

Proč jsou důležité odpovědi serveru?

  • Cookies: Slouží pro udržení session nebo autentizaci uživatele. Například PHPSESSID udržuje stav session mezi požadavky.
  • Cache-Control: Ovládá cacheování. Hlavička no-cache znamená, že by obsah neměl být uložen do cache.
  • Content-Encoding: Uvádí, jak je odpověď komprimována (např. gzip, br), což je důležité, pokud chceš odpověď správně rozbalit a zpracovat.
  • X-Powered-By: Informuje, na jaké technologii server běží (zde PHP a ASP.NET).

Uložení hlaviček a kontrola

Chcete-li uložit hlavičky odpovědi do souborů a následně kontrolovat, zda soubor již existuje na disku a nestahovat jej znovu, můžete v Bashi použít curl spolu s dalšími nástroji jako grep nebo head.

1. Uložení hlaviček odpovědi do souboru

Pomocí curl můžete uložit hlavičky odpovědi do samostatného souboru a tělo odpovědi (např. JS soubor) do jiného:

# Stáhne hlavičky a uloží je do souboru headers.txt, tělo uloží do file.js
curl -D headers.txt -o file.js "https://www.freeprivacypolicy.com/public/cookie-consent/4.0.0/cookie-consent.js"

2. Kontrola, zda je soubor již stažen

Před každým stahováním můžete zkontrolovat, zda soubor již existuje na disku:

# Zkontroluje, zda soubor file.js existuje
if [ -f "file.js" ]; then
    echo "Soubor již existuje, nestahovat."
else
    echo "Soubor neexistuje, stáhne se nyní."
    curl -D headers.txt -o file.js "https://www.freeprivacypolicy.com/public/cookie-consent/4.0.0/cookie-consent.js"
fi


3. Kontrola hlavičky 303 See Other

Hlavička 303 indikuje, že klient by měl použít jiný zdroj (URL) pro požadavek. Můžete tuto hlavičku kontrolovat takto:

# Stáhne jen hlavičky a kontroluje stavový kód
status_code=$(curl -I -s -o headers.txt -w "%{http_code}" "https://www.freeprivacypolicy.com/public/cookie-consent/4.0.0/cookie-consent.js")

# Kontrola, zda je status code 303
if [ "$status_code" -eq 303 ]; then
    echo "Hlavička 303 - soubor by měl být přesměrován."
else
    echo "Status code je $status_code, není potřeba přesměrování."
fi

 

4. Ukládání cookies pro další požadavky

Pro práci s cookies a jejich uchování mezi požadavky můžete použít curl s volbami -c a -b:

 # Uloží cookies do souboru cookies.txt
curl -c cookies.txt -D headers.txt -o index.html "https://zp....cz/"

# Při dalším požadavku načte cookies ze souboru cookies.txt
curl -b cookies.txt -D headers2.txt -o další_soubor.js "https://zp....cz/něco"

Vše v jednom skriptu

#!/bin/bash

# URL serveru
DOMAIN_1="zp..cz"

DOMAIN_2="www.freeprivacypolicy.com"

BASE_URL="https://$DOMAIN_1"
JS_URL="https://
$DOMAIN_2/public/cookie-consent/4.0.0/cookie-consent.js"

# Soubor, do kterého se uloží cookies
COOKIE_FILE="cookies.txt"
# Soubor, do kterého se uloží hlavičky
HEADERS_FILE_1="headers_1.txt"
HEADERS_FILE_2="headers_2.txt"
HEADERS_FILE_3="headers_3.txt"
# Soubor pro JS
JS_FILE="file.js"

# První požadavek - stáhnutí HTML a uložení hlaviček
curl -s -c "$COOKIE_FILE" -D "$HEADERS_FILE_1" \
  -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8" \
  -H "Accept-Encoding: gzip, deflate, br, zstd" \
  -H "Accept-Language: cs,sk;q=0.8,en-US;q=0.5,en;q=0.3" \
  -H "Connection: keep-alive" \
  -H "DNT: 1" \
  -H "Host: 
$DOMAIN_1" \
  -H "Sec-Fetch-Dest: document" \
  -H "Sec-Fetch-Mode: navigate" \
  -H "Sec-Fetch-Site: none" \
  -H "Sec-Fetch-User: ?1" \
  -H "Upgrade-Insecure-Requests: 1" \
  -H "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0" \
  "$BASE_URL/"

# Kontrola, zda soubor JS již existuje
if [ -f "$JS_FILE" ]; then
    echo "Soubor $JS_FILE již existuje, nestahuje se znovu."
else
    echo "Soubor $JS_FILE neexistuje, stahuje se nyní."

    # Získání hlavičky a status kódu pro kontrolu 303
    status_code=$(curl -I -s -b "$COOKIE_FILE" -o "$HEADERS_FILE_2" -w "%{http_code}" \
      -H "Accept: */*" \
      -H "Accept-Encoding: gzip, deflate, br, zstd" \
      -H "Accept-Language: cs,sk;q=0.8,en-US;q=0.5,en;q=0.3" \
      -H "Connection: keep-alive" \
      -H "DNT: 1" \
      -H "Host: 
$DOMAIN_2" \
      -H "Referer: $BASE_URL/" \
      -H "Sec-Fetch-Dest: script" \
      -H "Sec-Fetch-Mode: no-cors" \
      -H "Sec-Fetch-Site: cross-site" \
      -H "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0" \
      "$JS_URL")

    # Kontrola status kódu
    if [ "$status_code" -eq 303 ]; then
        echo "Přesměrování 303 - kontrolujte novou lokaci."
        # Případně můžete extrahovat hlavičku Location pro přesměrování
        new_location=$(grep -i "Location:" "$HEADERS_FILE_3" | awk '{print $2}')
        echo "Nová lokace je: $new_location"
        # Stáhnutí JS z nové lokace
        curl -s -b "$COOKIE_FILE" -o "$JS_FILE" "$new_location"
    else
        # Stáhnutí JS souboru, pokud není přesměrování
        curl -s -b "$COOKIE_FILE" -o "$JS_FILE" "$JS_URL"
        echo "JS soubor stažen do $JS_FILE"
    fi
fi

Parametr -s v příkazu curl znamená "silent mode" (tichý režim). Tento režim způsobí, že curl nebude zobrazovat žádné informace o průběhu stahování, jako je například ukazatel postupu, chyby nebo informace o připojení. Tento režim je užitečný, když chcete minimalizovat výstup příkazu curl, například když pracujete se skripty a potřebujete pouze data, nikoli průběžné informace.

V kontextu tvého kódu:

  • curl -s -c "$COOKIE_FILE" znamená, že curl stáhne data (v tichém režimu) a uloží cookies do souboru "$COOKIE_FILE".
  • curl -s -b "$COOKIE_FILE" znamená, že curl stáhne data (v tichém režimu) a při tom odešle cookies uložené v souboru "$COOKIE_FILE" na server.

Pokud chceš z curl dostat více informací pro ladění, můžeš vynechat parametr -s nebo použít -v (verbose) pro více podrobný výstup.

Parametr -I v příkazu curl znamená HEAD request. Tímto příkazem nepožaduješ kompletní obsah stránky nebo souboru, ale pouze hlavičky HTTP odpovědi.

V tomto kontextu:

  • curl -I pošle požadavek na server pouze pro získání hlaviček a ne stáhne celé tělo odpovědi.
  • -s je volba pro tichý režim, aby se nezobrazovaly průběžné zprávy nebo chyby.
  • -b "$COOKIE_FILE" znamená, že curl při odesílání požadavku pošle uložené cookies z tohoto souboru.
  • -o "$HEADERS_FILE" uloží hlavičky odpovědi do souboru.
  • -w "%{http_code}" vypíše status kód HTTP odpovědi (například 200, 303, atd.).

Tímto způsobem můžeš získat pouze hlavičky, včetně status kódu, který lze zkontrolovat pro případy jako je přesměrování (status kód 303).

 


pondělí 26. srpna 2024

Python: Skript na export segmentů videa a jejich zpomalení

Předchozí skript obsahoval vážnou chybu. Zvuk byl příliš opožděn za obrazem asi o 35% a ve výsledku se tam vešla jen 1/2 z původního segmentu. 

Nový skript vypadá dobře. Testováno jen pro zpomalení 8x.

# TENTO SKRIPT S librosou vypadá opravdu správně
# ALE TESTOVAL JSEM TO ZATÍM JEN NA 8X ZPOMALENÍ

# REQUIRES: moviepy, librosa, soundfile
import os
from moviepy.editor import VideoFileClip, concatenate_videoclips, vfx, AudioFileClip
import librosa
import soundfile as sf
import time

# Cesty ke složkám
home_dir = os.path.expanduser("~")
default_path = "/TUTORIALS"
input_dir = os.path.join("/media/toshiba/home/user/Videa", default_path)

file = 'TUTORIAL DRŽENÍ ZÁPĚSTÍ A PRSTY PRAVÉ RUKY -5 cosas que NO debes hacer tocando la guitarra.mp4'
input_path = os.path.join(input_dir, file)

ramdisk_disable = True  # Deaktivuje vytvoření RAM disku

user_choice = input("Chcete použít aktuální složku (.) nebo přednastavenou složku? Zadejte '.' pro aktuální složku nebo 'default' pro přednastavenou složku: ")
if user_choice == '.':
    input_dir = os.path.abspath('.')
    input_path = os.path.join(input_dir, file)

# Faktory zpomalení
# slowdowns = [2, 4, 6, 8, 10, 15, 20, 25]
slowdowns = [8]

# Vytvoření výstupních složek dynamicky na základě faktorů zpomalení
output_dirs = [os.path.join(input_dir, f"Output/{factor}") for factor in slowdowns]
for dir in output_dirs:
    os.makedirs(dir, exist_ok=True)

# Vytvoření RAM disku (bez skutečného připojení, pokud je ramdisk_disable = True)
ramdisk_path = os.path.join(input_dir, "ramdisk")
log_file = os.path.join(input_dir, "ramdisk.log")
if not os.path.exists(ramdisk_path):
    os.makedirs(ramdisk_path)

if not ramdisk_disable:
    with open(log_file, "w") as log:
        os.system(f'sudo mount -t tmpfs -o size={ramdisk_size}M tmpfs "{ramdisk_path}"')
        os.system(f'df "{ramdisk_path}" > "{log_file}"')

    with open(log_file, "r") as log:
        log_content = log.read()

    if ramdisk_path in log_content:
        print(f"RAM disk is correctly mounted.")
    else:
        print(f"RAM disk is not found")

# Funkce pro změnu pitchu pomocí ffmpeg
def audio_pitchup_ffmpeg(input_audio_path, output_audio_path, factor):
    command = f'ffmpeg -i "{input_audio_path}" -filter_complex "rubberband=pitch={factor}" "{output_audio_path}"'
    os.system(command)

# Funkce pro změnu rychlosti zvuku pomocí librosa
def change_audio_speed(input_audio_path, output_audio_path, speed_factor, target_duration):
    # Načtěte původní zvukový soubor
    y, sr = librosa.load(input_audio_path, sr=None)
    
    # Získejte a vytiskněte délku původního zvuku
    original_duration = librosa.get_duration(y=y, sr=sr)
    print(f"Audio duration before stretching: {original_duration} seconds")
    
    # Zrychlete/zpomalte zvuk tak, aby odpovídal nové délce videa
    y_stretched = librosa.effects.time_stretch(y, rate=original_duration / target_duration)
    
    # Získejte a vytiskněte délku zvuku po zpracování
    stretched_duration = librosa.get_duration(y=y_stretched, sr=sr)
    print(f"Audio duration after stretching: {stretched_duration} seconds")
    time.sleep(2)
    
    # Uložte zpracovaný zvuk do nového souboru
    sf.write(output_audio_path, y_stretched, sr)

# Převod času na sekundy
def convert_to_seconds(time_str):
    parts = time_str.split(':')
    minutes = int(parts[0])
    seconds = float(parts[1])
    return minutes * 60 + seconds

# Definice časových rozsahů k vyexportování
time_ranges = [
    ("0:0.0", "0:03.20")  # krátká ukázka základní techniky fingerpickingu když zpomalila
]

# Zpracování jednoho videa file
video_path = input_path
if os.path.isfile(video_path) and video_path.endswith(".mp4"):  # Upravte podle formátu vašich videí
    video_clip = VideoFileClip(video_path)
    
    # Exportování specifikovaných časových úseků jako dočasné soubory
    temp_clips = []
    for start_time, end_time in time_ranges:
        start_seconds = convert_to_seconds(start_time)
        end_seconds = convert_to_seconds(end_time)
        temp_clip = video_clip.subclip(start_seconds, end_seconds)
        temp_clips.append(temp_clip)
    
    # Sloučení úseků do jednoho videa
    temp_joined_path = os.path.join(input_dir, "temp_joined.avi")
    joined_clip = concatenate_videoclips(temp_clips)
    joined_clip.write_videofile(temp_joined_path, codec="libx264", audio_codec="aac")
    
    # Uzavření všech klipů
    for clip in temp_clips:
        clip.close()
    video_clip.close()
    joined_clip.close()
    
    # Zpomalení videí a korekce pitch v audio stopách
    for i, factor in enumerate(slowdowns):
        output_path = os.path.join(output_dirs[i], file)
        edited_clip = VideoFileClip(temp_joined_path)

        # Extrakce a úprava audio stopy
        temp_audio_path = os.path.join(ramdisk_path, "temp_audio.wav")
        edited_clip.audio.write_audiofile(temp_audio_path, codec='pcm_s16le')

        # Změna pitchu zvuku
        new_audio_path = os.path.join(ramdisk_path, "new_temp_audio.wav")
        audio_pitchup_ffmpeg(temp_audio_path, new_audio_path, factor)
        
        # Změna rychlosti upravené audio stopy tak, aby odpovídala nové délce videa
        final_audio_path = os.path.join(ramdisk_path, "final_audio.wav")
        change_audio_speed(new_audio_path, final_audio_path, factor, edited_clip.duration)
        
        new_audio_clip = AudioFileClip(final_audio_path)

        # Vytvoření nového video klipu s upravenou audio stopou
        edited_clip = edited_clip.set_audio(new_audio_clip)
        temp_video_name = os.path.join(ramdisk_path, "temp-final-video.m4a")
        edited_clip.write_videofile(
            temp_video_name,
            codec="libx264",
            audio_codec="aac",
            temp_audiofile=os.path.join(ramdisk_path, 'temp-audio-1.m4a'),
            remove_temp=True,
            threads=4,
            preset='ultrafast'
        )

        # Uzavření dočasných klipů
        edited_clip.close()
        new_audio_clip.close()

        # Znovu otevření video klipu pro zpomalení
        edited_clip = VideoFileClip(temp_video_name)
        edited_clip = edited_clip.fx(vfx.speedx, 1.0 / factor)
        edited_clip.set_duration(edited_clip.duration)

        print(f"Processing {file} with slowdown factor {factor}. Saving to {output_path}")
        edited_clip.write_videofile(
            output_path,
            codec="libx264",
            audio_codec="aac",
            temp_audiofile=os.path.join(ramdisk_path,'temp-audio-2.m4a'),
            remove_temp=True,
            threads=4,
            preset='ultrafast'
        )

        # Uzavření všech klipů
        edited_clip.close()

        # Odstranění dočasných souborů
        if os.path.exists(temp_audio_path):
            os.remove(temp_audio_path)
        if os.path.exists(new_audio_path):
            os.remove(new_audio_path)
        if os.path.exists(final_audio_path):
            os.remove(final_audio_path)
        if os.path.exists(temp_video_name):
            os.remove(temp_video_name)

    # Odstranění dočasného sloučeného videa
    if os.path.exists(temp_joined_path):
        os.remove(temp_joined_path)

print("Job done.")
if not ramdisk_disable:
    os.system(f'sudo umount "{ramdisk_path}"')
 

pátek 9. srpna 2024

Python: skript na změření času a redukci záznamů ve výpisu souborů

root-ext-files-unmounted-all-times.log

Mám soubory s množstvím řádků ve formátu (první údaj je čas na prvním řádku):

22:23:14 - /opt/palemoon/updater.ini

a chci to převést na formát a redukovat na výpis jen po jedné vteřině (1 soubor na vteřinu, první řádek je logicky čas 0s):

0:00:00 - /opt/palemoon/updater.ini

import os
import datetime

# Vytvoření složek pro výstupy
os.makedirs("log-times", exist_ok=True)
os.makedirs("directories", exist_ok=True)

# Funkce pro výpočet rozdílu času
def time_diff(start, end):
    FMT = "%H:%M:%S"
    tdelta = datetime.datetime.strptime(end, FMT) - datetime.datetime.strptime(start, FMT)
    return str(tdelta)

# Funkce pro zpracování logů
def process_logs(input_dir):
    for log_file in os.listdir(input_dir):
        if log_file.endswith(".log"):
            with open(os.path.join(input_dir, log_file), 'r') as f:
                lines = f.readlines()

            # První čas a inicializace proměnných
            if lines:
                start_time = lines[0].split(" - ")[0]
            else:
                print(f"Soubor {log_file} je prázdný.")
                continue

            last_logged_second = None

            # Vytvoření souborů pro výstup
            output_log_path = os.path.join("log-times", log_file)
            reduced_log_path = os.path.join("directories", log_file)

            with open(output_log_path, 'w') as log_out, open(reduced_log_path, 'w') as dir_out:
                for line in lines:
                    try:
                        current_time, path = line.strip().split(" - ", 1)
                        elapsed_time = time_diff(start_time, current_time)

                        # Zapisování do logu s rozdílem času
                        log_out.write(f"{elapsed_time} - {path}\n")

                        # Zapisování pouze jednoho záznamu na vteřinu
                        current_second = current_time.split(":")[-1]
                        if current_second != last_logged_second:
                            dir_out.write(f"{elapsed_time} - {path}\n")
                            last_logged_second = current_second
                    except ValueError as e:
                        print(f"Chyba při zpracování řádku: '{line.strip()}'. Detail: {e}")

# Spuštění zpracování logů z aktuálního adresáře
process_logs(".")

print("Logy byly úspěšně zpracovány a uloženy do složek 'log-times' a 'directories'.")

 

 

automad je dobrý cms na vytváření flat-file blokových prezentací

 automad je dobrý cms na vytváření flat-file blokových prezentací

Štítky

.profile adm administrace Adobe Aho-Corasick AI akcelerace alfa transparence analýza AND any aplikace apt ar archiv asociativní pole atomicity audacity audio audio redirect autentifikace automad automatizace awk balíčkovací systém bash beacon beacon_hint benchmark Bézierovy křivky bezpečnost biblehub BJT blogger boolean Braessův paradox brainstorming BRE buffer buffering bufferované čtení Cache-Conrol Cloudflare cms code Collector Cut-off ColorManager colorpicker common compare config cookies CPU CPU pipe crop css CSS3 curl current code cut čas data loss data lost data transfer reliability datasheet datetime.strptime deb deb-systemd-helper debian debián depricated development dict dioda diody disonance doprava dpkg dpkg -S dpkg-deb drivers EBO editace efekt Emitter Cut-off Current eps ETag evtest exclude exec Expires extrakce jediného extrakce názvu balíčku souboru extrakce obrázků extrakce souboru .deb fflock fflush ffmpeg FIFO file read file write file_get_contents file_get_contents/file_put_contents file_put_contents filter find first_install.sh flat-file flock Fly-back dioda font-face fonty fóra formant-preserving morphing fotorezistor fread functions funkce FuzzyWuzzy fwrite gate gate drive GDVfs gedit gedit-common geolokace getdata Ghostscript GIO glib gnome gnome settings GNU Privacy Guard gnupg gpg gradient-background grafika grep grep -v groupadd grub grub update gs gsettings gtk gtk.css gtk+ hebrejština history hlavičky HS html html 5 https hudba hunspell charakterizace chatGPT chroot chyba ICES IGBT Image img sizes img srcset impedance implementace imshow inference inkscape inrush current install IQ jalový výkon javascript javescript jednocení seznamů js jsonData kapacita součástek klávesnice koeficient zesílení komponenty xFce komunikace se serverem koncept konfigurace kontejner korekce barev Krita KSF kvantifikátor kytara Last-Modified lazy caching led LEFT JOIN librosa ligatury light-locker lightdm linux list log m3u maják manuál map mapování maskování maskování hlasu maskování služby masky matplotlib Max-Age measure melodie memory měření meta MFCC MFCC koeficienty mint Mint 21.3 Mint xFce míry mlt modules moralizace morphologie MOSFET mount moviepy multimedia mysql náběhový proud napěťová ochrana nastavení šablony návod návrh nel Network Error Logging NLP normalizace šedi po resize not Notifications noty NTFS nth-child oblasti oblékání ochrana okruhy přátel OpenVINO IR formát oprava oprava balíčku optočlen org.gnome.desktop.screensaver org.gnome.nm-applet ořezové masky OSHB otázky otázky_jazyky otázky_moralismu_řešení overlay ovladače panely parsování path pdf personifikace photorec php php 4 php 5 php 6 php 7 php 8 phpbb phpBB3 PipeWire pitch plus PN přechody pnp pole Policykit postscript práva profilování program prune průraz přeinstalování překlad přepěťová ochrana přepolování příkazy připojení připojení k síti připojení k wifi pseudokódd pstoedit pulse PulseAudio PWM regulátory pydub python python3 pytorch ramdisk RBE RDSon read reaktance rectifier redakční systém regex regulace vstupního napětí reinstall relyability remount replace restore reverzní geolokace RIGHT JOIN rm robotický hlas role rozvržení disků pro OS linux a data databází řešení samba scan scroll sd karta sdílení sdílení souborů Sec-Fetch-Dest Sec-Fetch-Mode Sec-Fetch-Site Sec-Fetch-User Secure Shell sed Set Cookie show-manual-login show-remote-login shunt schemas schémata schottka signal morphing sink skript skupiny sledovanost sloupce slučování seznamů služby small song sort soubory soundfile spínané zdroje spínání splines split spojování správa diskových zařízení SQL ssh stabilizace napětí stahování stíny stream stream redirect string strojové učení stropové učení subprocess.call supplicant svg syntax systemctl systemd-logind T5 tabulka tabulky Tangentové úsečky tar témata tepelná ztráta terminologie test text-shadow themes thermal runaway time timestamp tkinter tr transformace transistor transition transpose tranzistor tranzistory TS ttf tuple tvorba otázek TVS typografie ubuntu účiník udiskd udisks unconfined underrun unity-greeter update usb usermod uživatelé va charakteristika vala věda vektorová grafika Vgs video virtual devices vocoder Vth vyhledávání vyhledávání soborů výkon vynechání adresářů vytvoření playlistu vývoj webovka while wpa wpa_supplicant wrapovací funkce x xandr xapp-watt xargs -I xed xed-common xfdesktop xml xmp XOR Xorg Xorg Thumbnails xrandr závislosti zdánlivý výkon zdroj zenerka zenerovo napětí zip zip archiv zkratky zpomalení zpracování textu zrychlení zvuk Žalmy