Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FFmpeg Integration - mp4, webm, gif #624

Merged
merged 29 commits into from Jul 29, 2016
Merged

FFmpeg Integration - mp4, webm, gif #624

merged 29 commits into from Jul 29, 2016

Conversation

ghost
Copy link

@ghost ghost commented Jul 11, 2016

Gif and Webm export are working when 1 cpu is used for export. I modified outputsettingspopup to disable other cpus when gif or webm is selected. Obviously it would be better if it could use all, but it is inconsistent right now.

I submitted these both together because the implementation is basically the same(as is the h264 PR). I can split them if you prefer, but anything that doesn't work on one will probably not work on the other. The only difference is ffmpeg options.

I realize that h264 support is being debated due to licensing issues, but these options shouldn't have licensing issues.

The code works but I tagged it WIP because I'm sure there are things I missed. If you could look at it, I would appreciate it.

@ghost ghost added the Enhancement label Jul 11, 2016
@blurymind
Copy link

You are awesome! Thank you so much :D

@blurymind
Copy link

gif import would be amazing too - but its probably a lot of work :)

Still great progress on the ffmpeg front!! We finally have internet friendly output - out of the box

This was referenced Jul 11, 2016
@ghost
Copy link
Author

ghost commented Jul 12, 2016

Added an intermediate conversion to jpg to delete the raw image. Without the jpg coversion, a 5 minute 24fps animation would take 57gb in the process. It would be deleted after the final output, but a failed conversion would eat hard drive space. With the jpeg conversion, it drops to around 1.4gb. That is still freed after the final output, but is a much better figure to be dealing with.

@ghost
Copy link
Author

ghost commented Jul 12, 2016

@blurymind If I made a portable version with this feature, would you test it out and try and break it?
Note: if you change the settings, the sliders go down to their lowest value if you don't change them. I need to figure that out. Right now, dragging it down and back up takes care of it.

@blurymind
Copy link

@turtleTooth of course i will test it. :) if it helps getting it merged

@ideasman42
Copy link
Collaborator

ideasman42 commented Jul 12, 2016

Jpeg will give compression artifacts, especially for solid color. Why not use PNG as an interchange format? (compresses solid color well).

People who export long animations probably would export directly as image files anyway (to allow for partial re-rendering).

@blurymind
Copy link

@turtleTooth its also worth noting that webm supports transparency:
https://developers.google.com/web/updates/2013/07/Alpha-transparency-in-Chrome-video?hl=en

@blurymind
Copy link

blurymind commented Jul 12, 2016

There is no other video format that i know of that also supports having an alpha channel :b its pretty cool. If you use png instead of jpg - you might be able to export the alpha channel too

@blurymind
Copy link

blurymind commented Jul 12, 2016

Google claims that webp has much better quality and compression than png. That is another format worth investigating. There are other formats too - but webp is solid as it is supported by google and already used by the web

@ideasman42
Copy link
Collaborator

PNG is lossless, so not sure what better quality means in that context.

@ideasman42
Copy link
Collaborator

ideasman42 commented Jul 13, 2016

Note that its possible to avoid writing files at all, which avoids many files on disk and time to compress as one format then re-encode into another.

See:

Its possible to set this up for the user without them having to manually run external commends (as is done already for this PR).

@blurymind
Copy link

Ah sorry - i totally overlooked that point. I guess only advantage might be file size.

Note that webp supports both lossless and lossy
https://developers.google.com/speed/webp/gallery2

@blurymind
Copy link

@ideasman42 that does seem better. @turtleTooth was earlier asking for help on the ffmpeg exporter. Blender does use ffmpeg as well and it works great there

@blurymind
Copy link

Aligorith wrote some notes on export with it a couple of years ago

http://aligorith.blogspot.co.uk/2014/01/blender-ffmpeg-notes-on-getting-usable.html?m=1

@ghost
Copy link
Author

ghost commented Jul 13, 2016

@ideasman42 I chose jpg for file size, but I did choose the highest quality. You bring up a good point about compression artifacts. I will try it with png and compare file sizes and see how it turns out.

As for a frameserver, that is probably the best long term solution. However, it looks like it involves creating a network or socket between one program and the other. I have never done anything with networking before and don't feel equipped to take that on just now. It seems like it would be very doable as OT serves up raw frames and I am just saving those. It would be a much more efficient solution. Right now mine saves the raw frame, converts it to jpg (or png), deletes the raw frame to save disk space, converts all jpg (or png) frames to video or gif, and then deletes the jpg files. There are definitely intermediate steps that would be great to get rid of.

Do you have any experience writing a frameserver? Is that something you might be able to help out with?

BTW- thanks for all your great contributions so far to the program. Your technical knowledge is a great asset.

Update: png looks good and the filesize is good.

@ideasman42
Copy link
Collaborator

ideasman42 commented Jul 13, 2016

@blurymind, Blender's ffmpeg is built-in, so it wont help with integration in this case (the frameserver can be used with ffmpeg, but its not ffmpeg spesific).

@turtleTooth, I didn't write Blender's frame-server, but reading over the code its quite simple, I've tested using it, it works quite well.

Regrettably I wont be able to help with this task, just giving some hints on alternative ways to do this.

@ghost
Copy link
Author

ghost commented Jul 13, 2016

Thanks for the feedback. It sounds like a good goal to add in the future. In the meantime, this solution seems to work. It is just a little slow.

@yamisama
Copy link

As far as WebP goes, it seems that at least the Mac version of OpenToonz is deployed with the WebP QT plugin dll, so it may be possible to add support through QImage or QMovie without relying on external tools like ffmpeg, but I don't know enough about QT to say for sure. There is also a libqgif.dylib in the plugins folder, no idea if that also supports writing, plus libraries for a few other image file formats.

@blurymind
Copy link

blurymind commented Jul 13, 2016

@yamisama well spotted. It might be advantageous to preserving space .
@turtleTooth considering that it creates a lot of frames -using webp could potentially get the size to 50% -150% less than using png

So 1 gb coud go down to 500 or even 250 mb!

Which would be a huge win.
https://www.andrewmunsell.com/blog/png-vs-webp/

Book cover – Baseline PNG (30.2 KB)
Book cover – Lossless WebP (8.9 KB)

in example case - webp is 1/3 of the size of the png. that is 150% smaller!
So it is quite quite a difference - considering it being lossless and still having transparency! :o

Lets not also forget that webp and webm are practically a brother and a sister. So I would imagine it would work better for webm export.

I believe that if using webp brings down the size so much - not having a frameserver for a while will not be noticeably bad.

@ghost
Copy link
Author

ghost commented Jul 14, 2016

@blurymind I will test it out. It looks very promising and has the added benefit of making webp export already baked in. OT already supports png out, so using webp as the intermediate adds webp as an export format too.

@ghost
Copy link
Author

ghost commented Jul 14, 2016

@yamisama Thank you so much for letting me know about the built in webp. I wasn't able to use it, because the rendering time was too slow (but the file sizes were amazing), but it made me look up saving a QImage which is built into Qt. I'm still learning Qt, but this allowed me to bypass the step of saving the raw image, and then converting to an intermediate format. I can save to PNG directly.

@blurymind I will probably use this method for creating webp exports, but note that the process is slow, However, the file sizes were 1/3 of a jpg at 100% quality and half of a png. - Amazing and great quality. I think slowness is the tradeoff for the filesize.

@ghost
Copy link
Author

ghost commented Jul 26, 2016

Just tested:
type

@ghost
Copy link
Author

ghost commented Jul 26, 2016

The portable version includes ffmpeg and t32bitsrv - you can test it if you want.

@ghost
Copy link
Author

ghost commented Jul 26, 2016

Does the homebrew install of ffmpeg include ffprobe? Import requires ffprobe - I added a check for it today.
Just a thought on why import might have crashed for you.

@kogaki
Copy link
Member

kogaki commented Jul 26, 2016

Yes, ffprobe is bundled with ffmpeg installed with homebrew. Anyway, I will try latest version. Thanks.

@@ -159,6 +162,33 @@ void initImageIo(bool lightVersion) {
TFileType::declare("rgb", TFileType::RASTER_IMAGE);
Tiio::defineWriterProperties("rgb", new Tiio::SgiWriterProperties());

// ffmpeg
if (Ffmpeg::checkFfmpeg()) {
Copy link
Member

@shun-iwasawa shun-iwasawa Jul 26, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a following line before the line 166:
#if !defined(_WIN32) || defined(x64)
and after the line 189, please add #endif

In Ffmpeg::checkFfmpeg() you are checking the value in Preferences, and Preferences tries to see TOONZPROFILES path from registry (in its ctor). This behavior seems to abort t32bitsrv.exe since the TEnv paths are not set in t32bitsrv.exe's main() function.
Adding #if !defined(_WIN32) || defined(x64) is to avoid this problem by skipping Ffmpeg::checkFfmpeg() on running t32bitsrv.exe. This check must be only needed for OpenToonz_1.0.exe.

@ghost
Copy link
Author

ghost commented Jul 26, 2016

I added the check above. @shun-iwasawa Great catch!

I also think I might have figured out the Mac crash on import. I was parsing the ffprobe output and splitting the string using \r as a delimiter. I don't think Mac uses \r - only \n. So the new line is:
tiio_ffpmeg.cpp: 329: QStringList split = sizeResults.split("\n");

@ghost
Copy link
Author

ghost commented Jul 27, 2016

As far as functionality goes, my only wish is to have much more direct control over the quality and size settings. I am used to the level control as seen in professional NLEs, and the dropdowns are somewhat limiting my choice of export settings. An "advanced" button that exposes all of ffmpeg's parameters would be nice to have.

@Rayek I was able to get the sliders working again and actually keep the values when the settings were reopened. So now there is much more granular control over the scale and quality. Once the initial commit is merged I will probably work on an advanced input dialog where users can input their own settings for ffmpeg to run. This would take knowledge of how ffmpeg takes it's commands, but would give the user more control.

@kogaki
Copy link
Member

kogaki commented Jul 27, 2016

Jenkins, build this

@ghost
Copy link
Author

ghost commented Jul 27, 2016

Hoping this works for you. After you test this, I have added the ability to set how long ffmpeg can run before timing out. I will wait to push it until you get a chance to test this.

@kogaki
Copy link
Member

kogaki commented Jul 27, 2016

@turtleTooth I think you don't need to hesitate to push the changes. You can just revert the change if it doesn't work!

@kogaki
Copy link
Member

kogaki commented Jul 27, 2016

Oh sorry, I mean "you don't need to wait to push the changes."

@ghost
Copy link
Author

ghost commented Jul 27, 2016

I think you don't need to hesitate to push the changes. You can just revert the change if it doesn't work!

That works too.

@kogaki
Copy link
Member

kogaki commented Jul 27, 2016

Today's Check

OSX

  • Importing / Exporting works collectly. 🎉

Windows

  • Importing works
  • Exporting almost works, but some frames are dropped with agif format.


QString palette;
QString filters = "fps=" + QString::number(m_frameRate) + ",scale=" +
QString::number(outLx) + ":-1:flags=lanczos";
Copy link
Member

@shun-iwasawa shun-iwasawa Jul 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should remove the "fps" filter here and use "-r" input option instead.

To be more precise, please modify the lines 74-75 to be as follows;
QString filters = "scale=" + QString::number(outLx) + ":-1:flags=lanczos";
...and insert following lines to the line 93;

preIArgs << "-r";
preIArgs << QString::number(m_frameRate);

When I checked your PR, I found some problem: If you set a scene fps to other than 25, some frames are dropped in the output GIF. For example, when you render a scene with 20 frames, the result GIF becomes 19 frames under 24fps (= the default value of OpenToonz) and 11 frames under 12.5fps.
According to the documentation of ffmpeg filters, it says;

fps

Convert the video to specified constant frame rate by duplicating or dropping frames as necessary.

I'm new to ffmpeg so I'm not 100% convinced, but this option may be the cause of this problem.
On the other hand, the "-r" option is documented here as follows:

-r[:stream_specifier] fps (input/output,per-stream)

Set frame rate (Hz value, fraction or abbreviation).

As an input option, ignore any timestamps stored in the file and instead generate timestamps assuming constant frame rate fps.

Here is a comparison of the rendered results. Both results are rendered from the same scene which has 20 frames in length and with 8 fps frame rate. Please note that some frames are dropped from the former result.

  • With "fps" filter (current implementation):
    using_fps_filter_8fps
  • With "-r" input option (my suggestion):
    using_-r_option_8fps

@ghost
Copy link
Author

ghost commented Jul 27, 2016

@kogaki @shun-iwasawa Thank you for the help. I added the change and caught an error where scaling wouldn't happen if a palette wasn't generated. Gif fps now works as expected. Great suggestion.

@kogaki
Copy link
Member

kogaki commented Jul 29, 2016

Jenkins

@kogaki
Copy link
Member

kogaki commented Jul 29, 2016

@turtleTooth I think it's time to be merged because basic I/O feature works. Do you think this is still "WIP" PR ?

@ghost ghost changed the title WIP - FFmpeg Integration - mp4, webm, gif FFmpeg Integration - mp4, webm, gif Jul 29, 2016
@ghost
Copy link
Author

ghost commented Jul 29, 2016

I totally agree. I'm sure things will come up that will need to get fixed, but it's all basically there. I will squash bugs as they come up. Thank you so much for all your help.

@ghost
Copy link
Author

ghost commented Jul 29, 2016

Let's do this!

@kogaki kogaki merged commit 04d8fdc into opentoonz:master Jul 29, 2016
@kogaki
Copy link
Member

kogaki commented Jul 29, 2016

Merged! Thank you for your great contribution and continuous improvements !

@ghost
Copy link
Author

ghost commented Jul 29, 2016

Thank you! Thank you!

@blurymind
Copy link

Thank you @turtleTooth ! This is an epic addition

On 29 Jul 2016 06:59, "turtletooth" notifications@github.com wrote:

Thank you! Thank you!


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#624 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AGMbVT9lUdoRnS3SZHa2Ll_Us3ifDIzyks5qaZbFgaJpZM4JJEaG
.

@ghost ghost mentioned this pull request Jul 30, 2016
@ghost ghost deleted the webm branch August 4, 2016 05:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants