<p>First, a nitpick: you don't want to compute hashes on the <em>encoded</em> frame data before or while writing. You're testing the fidelity of the  lossless encoding so you need to compare the <em>decoded</em> frame of the x264 encode with the corresponding PNG.</p>

<p>So, first here's how to do what you specifically asked for.</p>

<p>Use the tee pseudo-muxer</p>

<pre><code>ffmpeg -framerate 30 -start_number 0 -i "%IMAGES_DIRECTORY%\%%03d.png" ^
-filter_complex "[0]{some filter here}[otherOut]" ^
-map 0 -c:v libx264rgb -qp 0 -pix_fmt rgb24 -f tee "%IMAGES_DIRECTORY%\lossless.avi|[f=avi]pipe:" ^
-map 0 -f framehash -hash SHA512 "%IMAGES_DIRECTORY%\original.hashes" ^
-map [otherOut] {some other encoding} someOtherFile.idc | ffmpeg -f avi -i - -f framehash -hash SHA512 %IMAGES_DIRECTORY%\decoded.hashes" 
</code></pre>

<hr>

<p>If your end goal is to check the fidelity of the lossless encoding, use</p>

<pre><code>ffmpeg -framerate 30 -start_number 0 -i "%IMAGES_DIRECTORY%\%%03d.png" ^
-filter_complex "[0]{some filter here}[otherOut]" ^
-map 0 -c:v libx264rgb -qp 0 -pix_fmt rgb24 "%IMAGES_DIRECTORY%\lossless.avi" ^
-map [otherOut] {some other encoding} someOtherFile.idc
</code></pre>

<p>and then</p>

<pre><code>ffmpeg -framerate 30 -start_number 0 -i "%IMAGES_DIRECTORY%\%%03d.png" -i lossless.avi ^
-filter_complex "ssim" -f null -
</code></pre>

<p>If the result is lossless, the readout will say</p>

<pre><code>SSIM R:1.000000 (inf) G:1.000000 (inf) B:1.000000 (inf) All:1.000000 (inf)
</code></pre>

CC BY-SA 3.0
2016-09-09T19:37:00.460Z
This answer made so many different things click for me (`hash` doesn't use raw input, `-map 0` instead of `split`, and that's what a tee is for).  Thanks!  But it doesn't avoid the problem of reading lossless.avi off of the disk to decode/compare it.  In fact, you are also reading the original images off of the disk twice to compare them to the decoded image.
Mutant Platypus
CC BY-SA 3.0
2016-09-09T20:01:32.187Z
Is there no way to take encoded packets and fork them to a muxer and a decoder in the same FFMPEG instance?
Mutant Platypus
CC BY-SA 3.0
2016-09-09T20:16:34.583Z
No. Encoding occurs after decoding (and filtering), so that provision isn't there. Looks like you are concerned about disk I/O. What you could do is pipe lossless avi to another ffmpeg instance which computes hashes.
Gyan
CC BY-SA 3.0
2016-09-10T06:42:43.393Z
I've edited my first command, so that the AVI output is simultaneously piped to another ffmpeg instance which then computes hashes on the *decoded* frames.
Gyan
CC BY-SA 3.0
2016-09-12T14:40:43.713Z
And here I was looking up how to split outputs on the Windows command line.  (To send the `lossless.avi` to a file and a pipe.  Ugh.)  This much better, thanks!  The only issue was the output filename in the `tee` needed to be surrounded in single quotes.  Also, I'm not sure that I like SSIM, as it is much more computationally complex than a hash and the output is subject to rounding errors.  I'll do a quick performance comparison, but the ideal solution is to just do a bit-for-bit comparison as both streams are flowing through memory... but a hash is close enough.
Mutant Platypus
CC BY-SA 3.0
2016-09-09T17:52:37.677Z
2016-09-10T06:41:33.990Z
2016-09-10T06:41:33.990Z
Gyan
<p>I am experimenting with losslessly compressing some raw video.  How can I perform a frame hash on the encoded output <em>before or while</em> writing it to the file system?  I want to make an <code>original.hashes</code> and a <code>compressed.hashes</code>.  (I will compare them with another tool later.)</p>

<pre><code>ffmpeg -r 30 -start_number 0 -i "%IMAGES_DIRECTORY%\%%03d.png" ^
-filter_complex "split=3 [copyHash] [copyLossless] [otherIn]; [otherIn] {some filter here} [otherOut]" ^
-map [copyLossless] -c:v libx264rgb -qp 0 -pix_fmt rgb24 "%IMAGES_DIRECTORY%\lossless.avi" ^
-map [copyHash] -f framehash -hash SHA512 "%IMAGES_DIRECTORY%\original.hashes" ^
-map [otherOut] {some other encoding} someOtherFile.idc

ffmpeg -start_number 0 -i "%IMAGES_DIRECTORY%\lossless.avi" -pix_fmt rgb24 -f framehash -hash SHA512  "%IMAGES_DIRECTORY%\decoded.hashes"

comp original.hashes decoded.hashes
</code></pre>

<p>So above, I would like to avoid the second call to ffmpeg.  Like if I could split the <code>lossless.avi</code> output of the first call to two new streams:  One to the file system and one to a demuxer feeding the hash muxer.</p>

<ffmpeg>
FFMPEG Calculate Hash After Encoding Before Writing
Mutant Platypus
# FFMPEG Calculate Hash After Encoding Before Writing

(Asked by: username_0 on 2016-09-09)

I am experimenting with losslessly compressing some raw video.  How can I perform a frame hash on the encoded output before or while writing it to the file system?  I want to make an original.hashes and a compressed.hashes.  (I will compare them with another tool later.)
ffmpeg -r 30 -start_number 0 -i "%IMAGES_DIRECTORY%\%%03d.png" ^
-filter_complex "split=3 [copyHash] [copyLossless] [otherIn]; [otherIn] {some filter here} [otherOut]" ^
-map [copyLossless] -c:v libx264rgb -qp 0 -pix_fmt rgb24 "%IMAGES_DIRECTORY%\lossless.avi" ^
-map [copyHash] -f framehash -hash SHA512 "%IMAGES_DIRECTORY%\original.hashes" ^
-map [otherOut] {some other encoding} someOtherFile.idc

ffmpeg -start_number 0 -i "%IMAGES_DIRECTORY%\lossless.avi" -pix_fmt rgb24 -f framehash -hash SHA512  "%IMAGES_DIRECTORY%\decoded.hashes"

comp original.hashes decoded.hashes

So above, I would like to avoid the second call to ffmpeg.  Like if I could split the lossless.avi output of the first call to two new streams:  One to the file system and one to a demuxer feeding the hash muxer.

**Tags:** ffmpeg


---

## 1 answers

### Answer by username_1 on 2016-09-09. Score: 0 | Accepted answer

First, a nitpick: you don't want to compute hashes on the encoded frame data before or while writing. You're testing the fidelity of the  lossless encoding so you need to compare the decoded frame of the x264 encode with the corresponding PNG.
So, first here's how to do what you specifically asked for.
Use the tee pseudo-muxer
ffmpeg -framerate 30 -start_number 0 -i "%IMAGES_DIRECTORY%\%%03d.png" ^
-filter_complex "[0]{some filter here}[otherOut]" ^
-map 0 -c:v libx264rgb -qp 0 -pix_fmt rgb24 -f tee "%IMAGES_DIRECTORY%\lossless.avi|[f=avi]pipe:" ^
-map 0 -f framehash -hash SHA512 "%IMAGES_DIRECTORY%\original.hashes" ^
-map [otherOut] {some other encoding} someOtherFile.idc | ffmpeg -f avi -i - -f framehash -hash SHA512 %IMAGES_DIRECTORY%\decoded.hashes" 


If your end goal is to check the fidelity of the lossless encoding, use
ffmpeg -framerate 30 -start_number 0 -i "%IMAGES_DIRECTORY%\%%03d.png" ^
-filter_complex "[0]{some filter here}[otherOut]" ^
-map 0 -c:v libx264rgb -qp 0 -pix_fmt rgb24 "%IMAGES_DIRECTORY%\lossless.avi" ^
-map [otherOut] {some other encoding} someOtherFile.idc

and then
ffmpeg -framerate 30 -start_number 0 -i "%IMAGES_DIRECTORY%\%%03d.png" -i lossless.avi ^
-filter_complex "ssim" -f null -

If the result is lossless, the readout will say
SSIM R:1.000000 (inf) G:1.000000 (inf) B:1.000000 (inf) All:1.000000 (inf)

> **Comments:**
> **username_0**: This answer made so many different things click for me (`hash` doesn't use raw input, `-map 0` instead of `split`, and that's what a tee is for).  Thanks!  But it doesn't avoid the problem of reading lossless.avi off of the disk to decode/compare it.  In fact, you are also reading the original images off of the disk twice to compare them to the decoded image.  
> **username_0**: Is there no way to take encoded packets and fork them to a muxer and a decoder in the same FFMPEG instance?  
> **username_1**: No. Encoding occurs after decoding (and filtering), so that provision isn't there. Looks like you are concerned about disk I/O. What you could do is pipe lossless avi to another ffmpeg instance which computes hashes.  
> **username_1**: I've edited my first command, so that the AVI output is simultaneously piped to another ffmpeg instance which then computes hashes on the *decoded* frames.  
> **username_0**: And here I was looking up how to split outputs on the Windows command line.  (To send the `lossless.avi` to a file and a pipe.  Ugh.)  This much better, thanks!  The only issue was the output filename in the `tee` needed to be surrounded in single quotes.  Also, I'm not sure that I like SSIM, as it is much more computationally complex than a hash and the output is subject to rounding errors.  I'll do a quick performance comparison, but the ideal solution is to just do a bit-for-bit comparison as both streams are flowing through memory... but a hash is close enough.  

---

