La cola de conversión sigue a los clips cuando se mueven, y «Comparar» en vertical

Los trabajos de la cola apuntaban al clip por su ruta y nadie los avisaba al moverlo: en Línea Gene el plan
llevó «Material Sony» a 00_Grabacion y 138 conversiones fallaron, los 11 verificados no se podían reemplazar y
volver a escanear no los reenganchaba. Ahora se mueven con el clip (plan, Deshacer, renombrar), el convertido
acompaña a su original, al escanear se reenganchan por nombre y peso, antes de convertir se comprueba que el
clip esté, y reemplazar junta antes el convertido con su original. El comparador toma la forma del clip y la
lupa ya no estira el recorte.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Este commit está contenido en:
Labstream
2026-10-14 09:33:12 -05:00
padre e74b8f7ece
commit c91152a3dd
Se han modificado 4 ficheros con 360 adiciones y 16 borrados

Ver fichero

@@ -1091,6 +1091,102 @@ class Convertidor(unittest.TestCase):
fh.write(b"z" * 999) # alguien dejó otro archivo con ese nombre
self.assertTrue(O._salida_ajena(self.trabajo(nuevos[0])))
def test_la_cola_sigue_al_clip(self):
"""Línea Gene, 14-oct-2026: el plan llevó «Material Sony» a 00_Grabacion; 138 conversiones en espera
fallaron buscando cada clip donde ya no estaba, los 11 verificados no se podían reemplazar (y su «_10bit»
se quedó en la carpeta vieja), y volver a escanear no los reenganchaba."""
raiz = cliente("ColaSigue")
nr = os.path.normpath(raiz)
g = "Material Sony/"
a = mk(raiz, g + "20250722_Labstream3796.MP4", 2025, 7, 22, tam=300000)
b = mk(raiz, g + "20250722_Labstream3797.MP4", 2025, 7, 22, tam=300001)
c = mk(raiz, g + "20250731_Labstream4033.MP4", 2025, 7, 31, tam=300002)
d = mk(raiz, g + "20250731_Labstream4034.MP4", 2025, 7, 31, tam=300003)
O.escanear(raiz)
self.leidos(raiz, {os.path.basename(x): {"codec": "h264", "perfil": "High", "kbps": 120000} for x in (a, b, c, d)})
ia, ib, ic = O.encolar([a, b, c], "equilibrado", "420", "rec709", nr)
O.set_trabajo(ib, estado="error", log="falló antes por otra cosa")
# el plan se calcula antes de que c termine de convertirse: su «_10bit» aún no está en el inventario
p = O.Plan(O.raiz_cfg(raiz)).correr()
sc = self.trabajo(ic)["salida"]
with open(sc, "wb") as fh:
fh.write(b"x" * 120000)
O.set_trabajo(ic, estado="verificado", bytes_out=120000)
r = aplicar(raiz, p)
self.assertFalse(os.path.exists(a) or os.path.exists(c))
# 1) los trabajos se fueron con sus clips; el que espera sale junto al clip en su sitio nuevo
ta, tb, tc = (self.trabajo(i) for i in (ia, ib, ic))
for t in (ta, tb, tc):
self.assertTrue(os.path.isfile(t["ruta"]), t)
self.assertIn("00_Grabacion", t["ruta"])
self.assertEqual(ta["salida"], os.path.splitext(ta["ruta"])[0] + "_10bit.mp4")
self.assertEqual((ta["estado"], tb["estado"]), ("pendiente", "error"))
# …y el convertido acompañó a su original, aunque el plan no lo conocía
self.assertEqual(os.path.dirname(tc["salida"]), os.path.dirname(tc["ruta"]))
self.assertTrue(os.path.isfile(tc["salida"]))
self.assertFalse(os.path.exists(sc))
# «Buscar clips» no vuelve a ofrecer lo que ya está en la cola o convertido
cs = {os.path.basename(x["ruta"]): x["en_cola"] for x in O.candidatos(nr, 0, "equilibrado", 0)}
self.assertEqual((cs["20250722_Labstream3796.MP4"], cs["20250731_Labstream4033.MP4"], cs["20250731_Labstream4034.MP4"]),
("pendiente", "verificado", ""))
# 2) Deshacer los devuelve, y la cola vuelve con ellos
O.deshacer(r["lote"])
ta, tc = self.trabajo(ia), self.trabajo(ic)
self.assertEqual((ta["ruta"], tc["ruta"], tc["salida"]), (a, c, sc))
self.assertTrue(os.path.isfile(sc))
self.assertEqual(ta["salida"], os.path.splitext(a)[0] + "_10bit.mp4")
# 3) movidos con el Explorador: justo antes de convertir, el que no está falla diciendo qué hacer…
otra = os.path.join(nr, "Otra carpeta")
os.makedirs(otra)
a2, c2 = os.path.join(otra, os.path.basename(a)), os.path.join(otra, os.path.basename(c))
os.rename(a, a2)
os.rename(c, c2) # el original verificado se va; su convertido, no
self.assertIsNone(O._clip_presente(self.trabajo(ia)))
ta = self.trabajo(ia)
self.assertEqual(ta["estado"], "error")
self.assertIn("Vuelve a escanear", ta["log"])
# …y al volver a escanear se reengancha: vuelve a la cola en su sitio nuevo, sin volver a leer el clip
O.escanear(raiz)
ta, tc = self.trabajo(ia), self.trabajo(ic)
self.assertEqual((ta["ruta"], ta["estado"]), (a2, "pendiente"))
self.assertEqual(ta["salida"], os.path.splitext(a2)[0] + "_10bit.mp4")
self.assertTrue(ta["log"].startswith("el clip se había movido"), ta["log"])
self.assertEqual((tc["ruta"], tc["salida"]), (c2, sc))
con = O.db()
leido = con.execute("SELECT analizado, codec FROM archivos WHERE ruta = ?", (a2,)).fetchone()
con.close()
self.assertEqual(tuple(leido), (1, "h264"))
self.assertEqual(O._clip_presente(self.trabajo(ia))["ruta"], a2)
# 4) un intento fallido que ya se volvió a encolar en el sitio nuevo sobra: se quita
bn = os.path.join(otra, os.path.basename(b))
os.rename(b, bn)
O.escanear(raiz)
self.assertEqual(self.trabajo(ib)["ruta"], bn) # el de b (error) se reenganchó y vuelve a esperar
self.assertEqual(self.trabajo(ib)["estado"], "pendiente")
con = O.db()
with con:
viejo = con.execute("INSERT INTO trabajos (ruta, salida, motor, perfil, chroma, color, kbps, estado, bytes_in, creado, raiz, formato) "
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", (b, b + "_10bit.mp4", "ffmpeg", "equilibrado", "420", "rec709", 21150, "error",
300001, time.time(), nr, "h265_10bit")).lastrowid
con.close()
O.reubicar_trabajos(nr)
con = O.db()
self.assertIsNone(con.execute("SELECT id FROM trabajos WHERE id = ?", (viejo,)).fetchone())
con.close()
# 5) reemplazar con el convertido en otra carpeta: primero se lleva junto al original
r = O.reemplazar([ic])[0]
self.assertTrue(r["ok"], r)
junto = os.path.join(otra, os.path.basename(sc))
self.assertTrue(os.path.isfile(junto))
self.assertFalse(os.path.exists(sc) or os.path.exists(c2))
self.assertTrue(os.path.isfile(os.path.join(nr, R.PAPELERA, "originales", "Otra carpeta", os.path.basename(c2))))
self.assertEqual(self.trabajo(ic)["salida"], junto)
def test_el_codificador_que_toca(self):
fm = O.FORMATOS["h265_10bit"]
t = {"chroma": "420", "perfil": "equilibrado", "kbps": 30000}