Skip to content
This repository was archived by the owner on Jul 7, 2023. It is now read-only.

Commit 2506671

Browse files
mbzCopybara-Service
authored andcommitted
refactoring the gif summary into writers so they can be used more for other purposes.
PiperOrigin-RevId: 211998264
1 parent 4e35349 commit 2506671

File tree

1 file changed

+89
-25
lines changed

1 file changed

+89
-25
lines changed

tensor2tensor/layers/common_video.py

Lines changed: 89 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -292,31 +292,9 @@ def _encode_gif(images, fps):
292292
Raises:
293293
IOError: If the ffmpeg command returns an error.
294294
"""
295-
from subprocess import Popen, PIPE # pylint: disable=g-import-not-at-top,g-multiple-import
296-
ffmpeg = "ffmpeg"
297-
height, width, channels = images[0].shape
298-
cmd = [
299-
ffmpeg, "-y",
300-
"-f", "rawvideo",
301-
"-vcodec", "rawvideo",
302-
"-r", "%.02f" % fps,
303-
"-s", "%dx%d" % (width, height),
304-
"-pix_fmt", {1: "gray", 3: "rgb24"}[channels],
305-
"-i", "-",
306-
"-filter_complex", "[0:v]split[x][z];[z]palettegen[y];[x][y]paletteuse",
307-
"-r", "%.02f" % fps,
308-
"-f", "gif",
309-
"-"
310-
]
311-
proc = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
312-
for image in images:
313-
proc.stdin.write(image.tostring())
314-
out, err = proc.communicate()
315-
if proc.returncode:
316-
err = "\n".join([" ".join(cmd), err.decode("utf8")])
317-
raise IOError(err)
318-
del proc
319-
return out
295+
writer = VideoWriter(fps)
296+
writer.write_multi(images)
297+
return writer.finish()
320298

321299

322300
def py_gif_summary(tag, images, max_outputs, fps):
@@ -521,3 +499,89 @@ def beta_schedule(schedule, global_step, final_beta, decay_start, decay_end):
521499
tf.greater(global_step, decay_end): lambda: final_beta},
522500
default=lambda: increased_value)
523501
return beta
502+
503+
504+
class VideoWriter(object):
505+
"""Helper class for writing videos."""
506+
507+
def __init__(self, fps, file_format="gif"):
508+
self.fps = fps
509+
self.file_format = file_format
510+
self.proc = None
511+
512+
def __init_ffmpeg(self, image_shape):
513+
"""Initializes ffmpeg to write frames."""
514+
from subprocess import Popen, PIPE # pylint: disable=g-import-not-at-top,g-multiple-import
515+
ffmpeg = "ffmpeg"
516+
height, width, channels = image_shape
517+
self.cmd = [
518+
ffmpeg, "-y",
519+
"-f", "rawvideo",
520+
"-vcodec", "rawvideo",
521+
"-r", "%.02f" % self.fps,
522+
"-s", "%dx%d" % (width, height),
523+
"-pix_fmt", {1: "gray", 3: "rgb24"}[channels],
524+
"-i", "-",
525+
"-filter_complex", "[0:v]split[x][z];[z]palettegen[y];[x][y]paletteuse",
526+
"-r", "%.02f" % self.fps,
527+
"-f", self.file_format,
528+
"-"
529+
]
530+
self.proc = Popen(self.cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
531+
532+
def write(self, frame):
533+
if self.proc is None:
534+
self.__init_ffmpeg(frame.shape)
535+
self.proc.stdin.write(frame.tostring())
536+
537+
def write_multi(self, frames):
538+
for frame in frames:
539+
self.write(frame)
540+
541+
def finish(self):
542+
if self.proc is None:
543+
return None
544+
out, err = self.proc.communicate()
545+
if self.proc.returncode:
546+
err = "\n".join([" ".join(self.cmd), err.decode("utf8")])
547+
raise IOError(err)
548+
del self.proc
549+
self.proc = None
550+
return out
551+
552+
def finish_to_file(self, path):
553+
with tf.gfile.open(path) as f:
554+
f.write(self.finish())
555+
556+
def __del__(self):
557+
self.finish()
558+
559+
560+
class BatchVideoWriter(object):
561+
"""Helper class for writing videos in batch."""
562+
563+
def __init__(self, fps, file_format="gif"):
564+
self.fps = fps
565+
self.file_format = file_format
566+
self.writers = None
567+
568+
def write(self, batch_frame):
569+
if self.writers is None:
570+
self.writers = [
571+
VideoWriter(self.fps, self.file_format) for _ in batch_frame]
572+
for i, frame in enumerate(batch_frame):
573+
self.writers[i].write(frame)
574+
575+
def write_multi(self, batch_frames):
576+
for batch_frame in batch_frames:
577+
self.write(batch_frame)
578+
579+
def finish(self):
580+
outs = [w.finish() for w in self.writers]
581+
return outs
582+
583+
def finish_to_files(self, path_template):
584+
for i, writer in enumerate(self.writers):
585+
path = path_template.format(i)
586+
writer.finish_to_file(path)
587+

0 commit comments

Comments
 (0)