Introducción
Un paquete de escucha debe contener todos los fragmentos solicitados. Si una conversión falla, una carpeta parcial no debe parecer un paquete terminado. Mejorarás un script Bash para preparar los archivos de forma privada, detenerse honestamente ante errores y publicar solo cuando todas las conversiones tengan éxito.
Este laboratorio comienza con sus propias grabaciones, una copia de práctica dañada y un paquete anterior independiente. No utiliza archivos del laboratorio anterior. Completa primero «Convierte un fragmento de audio en un lote» o conoce sus comillas, opciones de FFmpeg, funciones, arrays y estados de salida nativos. También usarás trap de Bash para limpiar únicamente el directorio temporal que pertenece al script.
Mantén privadas las conversiones incompletas
En este paso, harás que una conversión fallida no deje ningún lote publicado y mantenga intacto el trabajo anterior.
Empieza en Workspace, preparado para nombres UTF-8. Vuelve aquí con cd si falta una ruta relativa.
cd /home/labex/project/audio-studio
ls input library archive/previous
input contiene copias de práctica de tres grabaciones. library contiene los originales intactos permitidos. archive/previous es un paquete anterior que debes conservar, y notes.txt y scratch-other pertenecen a otro trabajo. Solo cambia tus scripts, las copias de práctica y los directorios nuevos de experimentos o salida. Las entradas admitidas son archivos regulares no ocultos directamente en el directorio de entrada, con extensión .wav en minúsculas: PCM mono de 16 bits con signo a 22050 Hz y al menos cinco segundos de duración.
Lee el script inicial con cat. Su exit 0 anuncia éxito incluso tras un fallo de conversión, y su mkdir prematuro deja visible un paquete incompleto.
cat batch.sh
La siguiente prueba encuentra intencionadamente una grabación dañada. Espera un error de FFmpeg terminado en Invalid data found when processing input. Es un fallo de formato de archivo, no la ausencia de un comando ni un problema de red.
bash batch.sh input trial-pack 3
printf 'Starter exit: %s\n' "$?"
Dice engañosamente Starter exit: 0. ls trial-pack solo muestra las conversiones que tuvieron éxito; la mera carpeta no demuestra que esté completa.
ls trial-pack
Elimina únicamente esta prueba desechable con nombre concreto. rm -r elimina recursivamente un directorio y su contenido; -- termina el análisis de opciones. Este comando no toca el paquete anterior, los originales ni el trabajo ajeno.
rm -r -- trial-pack
El contrato mejorado usa un directorio de salida nuevo en cada ejecución. Se rechazan archivos, directorios y enlaces simbólicos existentes, incluso enlaces cuyo destino no existe. El padre de la salida debe existir y la salida debe estar fuera de la entrada. No se admite un escritor concurrente; esta protección trata los fallos de conversión, no una transacción resistente a caídas o cortes de energía.
Un directorio de preparación guarda las conversiones antes de publicarlas. mktemp -d crea un directorio privado con nombre único, sustituyendo el sufijo XXXXXX. Se sitúa junto a la salida final para que el último movimiento permanezca en el mismo sistema de archivos. trap '...' EXIT ejecuta la limpieza cuando el script termina. Las comillas simples aplazan la expansión de $stage hasta esa limpieza. rm -rf -- "$stage" elimina exactamente ese directorio propio; nunca lo sustituyas por un comodín como /tmp/* o .preview.*.
Las otras operaciones de rutas explicitan el contrato. $(command) captura texto y || exit 2 detiene la ejecución si falla. realpath -m normaliza un destino que todavía no existe y dirname obtiene su padre. La prueba de prefijo case "$output/" rechaza una salida dentro del directorio de entrada. Entrecomillar el prefijo conserva sus caracteres literales, mientras que el * final coincide con un sufijo. mv -T mueve la preparación al nombre exacto del nuevo directorio, en lugar de anidarla dentro de otro. La comprobación previa de existencia no es un bloqueo de concurrencia.
Sustituye batch.sh por la versión mejorada completa. El array, la extracción del nombre, las comillas y los argumentos de FFmpeg funcionan como en el primer laboratorio guiado.
cat > batch.sh <<'BASH'
#!/usr/bin/env bash
if [ "$#" -ne 3 ]; then printf 'Usage: batch.sh INPUT OUTPUT SECONDS\n' >&2; exit 2; fi
case "$3" in 1|2|3|4|5) seconds=$3 ;; *) printf 'Use 1 to 5 seconds\n' >&2; exit 2 ;; esac
if [ ! -d "$1" ]; then printf 'Input directory missing\n' >&2; exit 2; fi
if [ -e "$2" ] || [ -L "$2" ]; then printf 'Output already exists\n' >&2; exit 2; fi
input=$(realpath -- "$1") || exit 2
output=$(realpath -m -- "$2") || exit 2
parent=$(dirname -- "$output")
if [ ! -d "$parent" ]; then printf 'Output parent missing\n' >&2; exit 2; fi
case "$output/" in "$input/"*) printf 'Output must be outside input\n' >&2; exit 2 ;; esac
shopt -s nullglob
files=("$input"/*.wav)
if [ "${#files[@]}" -eq 0 ]; then printf 'No WAV inputs\n' >&2; exit 1; fi
stage=$(mktemp -d "$parent/.preview.XXXXXX") || exit 1
trap 'rm -rf -- "$stage"' EXIT
for source in "${files[@]}"; do
name=${source##*/}
if ! ffmpeg -nostdin -v error -i "$source" -t "$seconds" -c:a pcm_s16le "$stage/$name"; then
printf 'Could not convert: %s\n' "$name" >&2
exit 1
fi
done
if ! mv -T -- "$stage" "$output"; then exit 1; fi
printf 'Published %s previews\n' "${#files[@]}"
BASH
Prueba otra vez las mismas entradas de práctica dañadas. Este fallo es intencional; todavía no las repares.
bash batch.sh input previews 3
printf 'Protected batch exit: %s\n' "$?"
Debes obtener Could not convert: zz Evening.wav y Protected batch exit: 1. La rama explícita detiene el lote. previews no debe existir y el directorio temporal ya debe haberse eliminado.
ls -a incluye nombres ocultos, de modo que permite buscar directorios de preparación .preview. que hayan quedado. Debe seguir mostrando scratch-other, cuyo contenido debe permanecer intacto.
ls -a
Ejecuta la comprobación del paso. Prueba tu script sin modificarlo en directorios desechables; no repara las entradas de práctica ni genera tu paquete real.
Restaura la copia de práctica y publica el lote
En este paso, diagnosticarás la grabación fallida, restaurarás únicamente su copia de práctica permitida y usarás el script para publicar un paquete completo.
Empieza en Workspace. FFmpeg puede inspeccionar una grabación sin producir otro archivo multimedia: -f null - selecciona una salida nula que descarta las muestras decodificadas. Una decodificación correcta confirma audio legible; un archivo dañado devuelve un valor distinto de cero. Solo lo usaremos con la copia de práctica concreta del curso.
ffmpeg -nostdin -v error -i "input/zz Evening.wav" -f null -
printf 'Decode exit: %s\n' "$?"
Espera un error de formato y un estado distinto de cero. El archivo intacto del mismo nombre está en library. cp -- copia ese original sobre la copia dañada; ambas rutas entre comillas identifican el archivo exacto. No modifiques la biblioteca.
cp -- "library/zz Evening.wav" "input/zz Evening.wav"
ffmpeg -nostdin -v error -i "input/zz Evening.wav" -f null -
printf 'Decode exit: %s\n' "$?"
Ahora debes obtener cero. Si escribes mal el nombre, consulta ls library y corrígelo; no necesitas reiniciar el entorno. Ejecuta el lote completo con la entrada restaurada.
bash batch.sh input previews 3
Debes ver Published 3 previews. Cambia a Listening Room y recarga. Reproduce cada fragmento bajo Your listening pack, desplázate dentro de ellos y descarga uno. Cada fragmento debe durar tres segundos y comenzar con la grabación correspondiente. Esta página solo lee previews; borrar o dañar un fragmento no puede hacer que reproduzca silenciosamente un original de la biblioteca. Vuelve a Workspace.
Por último, vuelve a intentar usar la salida existente. Este rechazo deliberado protege el paquete completo.
bash batch.sh input previews 3
printf 'Existing output exit: %s\n' "$?"
Debes obtener Output already exists y un estado distinto de cero. Conserva esa salida. Para crear otro paquete más adelante, usa un nombre nuevo y una duración de uno a cinco segundos, con el directorio padre ya presente. Las grabaciones originales, el paquete anterior, las notas y el directorio ajeno deben seguir intactos.
Resumen
Separaste preparación y publicación, devolviste los fallos honestamente y usaste un trap EXIT para limpiar un único directorio propio. Diagnosticaste y restauraste una grabación de práctica dañada y publicaste un paquete completo reproducible sin cambiar el trabajo anterior. El desafío aplica las mismas herramientas a otra colección.



