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:
@@ -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}
|
||||
|
||||
Referencia en una nueva incidencia
Block a user