Apparat: Crunching SWF Files Since 2009

Apparat has a great new feature that allows you to create even smaller files. Basic SWF files are compressed using Java’s standard java.util.zip.Deflater class. This is perfectly fine. And I would even go with no compression at all during development.

However when deploying you can spend some extra time compressing your SWF files with the best tools available. 7-Zip is for instance such a tool and achieves a great compression ratio.

If you have the 7z executable on your PATH Apparat will make use of it to achieve the best compression for your SWF files. More configuration options are available here.

This feature is currently only implemented for SWF files and not SWCs. However every tool will make use of it by default. So if you are running Reducer and have no graphics in your SWF files you can still get a better compression.

An example is straight from the sources:

reducer -i as3\Apparat.Tests.AS3\bin\Test07.swf
[i] Apparat -- http://apparat.googlecode.com/
[i] Launching tool: Reducer
[i] Waiting for 7z ...
[i] Compression ratio: 18.224573%
[i] Total bytes: 310
[i] Completed in 547ms.

Note please that this SWF file does not contain any graphical assets and we got still a ratio of 18%. Our main audiotool.swf file is compressed by about 10% — about 200kb — and contains no graphical assets either.

You can download the latest Apparat on Google Code. Please note that you will need Scala 2.8 RC1 as well.

28 Responses to “Apparat: Crunching SWF Files Since 2009”


  • Way to push the envelope, Ebert. :-) I’ll let you know how this affects my TDSI’d project when I get around to recompiling it.

  • Only problem is that TDSI is still Java based and you will not get any benefits there. Still have to implement the Scala version for it.

  • Looks like it will be very useful, but this is the output I get when running on OSX:

    ./reducer -i Main.swf -o MainCompressed.swf
    [i] Apparat — http://apparat.googlecode.com/
    [i] Launching tool: Reducer
    [?] Help:
    -i [file] Input file
    -o [file] Output file (optional)
    -d [float] Strength of deblocking filter (optional)
    -q [float] Quality from 0.0 to 1.0 (optional)
    [i] Completed in 132ms.

    …And it never actually seems to do anything. Using the 2.8RC1 build of scala as instructed. Any ideas as to what I’m doing wrong?

  • Can you please try the following, maybe those shell-scripts are wrong:

    scala -cp apparat.jar apparat.tools.reducer.Reducer -i Main.swf -o MainCompressed.swf

  • That did the trick, cheers!

  • Oh, all the shell scripts are broken, I forgot to add the arguments. I updated the download on the GC site. Should be fine now.

  • Frederik Heyninck

    Hi Joa

    Is the a step by step tutorial on how to install scale and apparat?

    Regards.

  • I’m probably missing something key to scala/java development, but I’m getting this error when running it:

    java.lang.NoClassDefFoundError: scala/collection/TraversableLike
    at apparat.tools.reducer.Reducer$.main(Reducer.scala:17)
    etc etc stack trace…

  • Updated to scala 2.8 nightly. Slightly different issue (the reducer one i guess was because of 2.7)

    jgilbert-mac:apparat jgilbert$ scala -cp apparat.jar apparat.tools.reducer.Reducer -i ScreenSaver.swf -o MainCompressed.swf
    [i] Apparat — http://apparat.googlecode.com/
    [i] Launching tool: Reducer
    [-] scala.collection.immutable.Range.foreach$mVc$sp(Lscala/Function1;)V
    java.lang.NoSuchMethodError: scala.collection.immutable.Range.foreach$mVc$sp(Lscala/Function1;)V

  • at apparat.swf.SwfOutputStream.writeSB(SwfOutputStream.scala:136)
    at apparat.swf.SwfOutputStream.writeUB(SwfOutputStream.scala:144)
    at apparat.swf.SwfOutputStream.writeRECT(SwfOutputStream.scala:86)

  • Cool. We had this in secureSWF a while back. We’ve been using kzip which gave us better results than 7z most of the times:
    http://www.advsys.net/ken/utils.htm (kzip for Windows)
    http://www.jonof.id.au/kenutils (for Linux and OS X)

  • Ammar Mardawi: Sounds good, thanks. I want to add different deflate options.

    Jeffrey Gilbert: Apparat is not compatible with Scala 2.7. I can also not gaurantee that this exact version compatible to the latest nightly. The JAR has been built using 2.8 RC1. In that case you should not get any library exceptions.

  • Had to update to java jdk 1.6 to get the reducer app to work. Didn’t do much on the example file i tried. still want to see if I can get this to work. upgrading java to 1.6 and scala to nightlies did nothing for my attempts.

    tried both commands:

    ./reducer -i ScreenSaver.swf -o Compressed.swf

    then

    scala -cp apparat.jar apparat.tools.reducer.Reducer -i ScreenSaver.swf -o Compressed.swf

  • joa, I’ll try grabbing the RC1 and see if that works. kinda shooting in the dark here ;)

  • Do you have 7-Zip on your path? Apparat outputs a warning if 7z cannot be found.

  • Joa, thanks so much for all of the awesome work!

    Is there a way to easily use Scala from Ant? And is there a Java 7zip library that I can ship with my library (http://code.google.com/p/as3search) to compact files even further? Thanks :)

  • Joa, do I need a special version of 7z on OSX ?

    I have:
    7-Zip (A) 9.04 beta Copyright (c) 1999-2009 Igor Pavlov 2009-05-30
    p7zip Version 9.04 (locale=utf8,Utf16=on,HugeFiles=on,2 CPUs)

    And get:
    scala -cp apparat.jar apparat.tools.reducer.Reducer -Dapparat.7z.path=/opt/local/var/macports/software/p7zip/9.04_0/opt/local/bin/7za -i large.swf -o small.swf
    [i] Apparat — http://apparat.googlecode.com/
    [i] Launching tool: Reducer
    [i] Waiting for 7z …
    [!] 7z failed. Fallback to normal compression.
    [i] Compression ratio: 0.0%
    [i] Total bytes: 0
    [i] Completed in 725ms.

  • The 7-Zip binary should be “7z” and not “7za”.

  • joa, its not its 7za, the p7zip implementation
    p7zip is the command line version of 7-Zip for Unix/Linux

    7za

    7-Zip (A) 9.04 beta Copyright (c) 1999-2009 Igor Pavlov 2009-05-30
    p7zip Version 9.04 (locale=utf8,Utf16=on,HugeFiles=on,2 CPUs)

    Usage: 7za [...] [...]
    []

    a: Add files to archive
    b: Benchmark
    d: Delete files from archive
    e: Extract files from archive (without using directory names)
    l: List contents of archive
    t: Test integrity of archive
    u: Update files to archive
    x: eXtract files with full paths

    -ai[r[-|0]]{@listfile|!wildcard}: Include archives
    -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives
    -bd: Disable percentage indicator
    -i[r[-|0]]{@listfile|!wildcard}: Include filenames
    -m{Parameters}: set compression Method (see the manual)
    -l: don’t store symlinks; store the files/directories they point to
    CAUTION : the scanning stage can never end because of symlinks like ‘..’
    (ex: ln -s .. ldir)
    -o{Directory}: set Output directory
    -p{Password}: set Password
    -r[-|0]: Recurse subdirectories
    (CAUTION: this flag does not do what you think, avoid using it)
    -sfx[{name}]: Create SFX archive
    -si[{name}]: read data from stdin
    -slt: show technical information for l (List) command
    -so: write data to stdout (eg: 7z a dummy -tgzip -so Doc.txt > archive.gz)
    -ssc[-]: set sensitive case mode
    -t{Type}: Set type of archive
    -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options
    -v{Size}[b|k|m|g]: Create volumes
    -w[{path}]: assign Work directory. Empty path means a temporary directory
    -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames
    -y: assume Yes on all queries

  • Yes, 7za is the one I have, so what can I do to make it work on OSX?

  • Will check it once i have a OSX/Ubutu box available. Should work, options are all the same for your version so there must be something else going on.

  • Thanks Joa, and yes it works now, problem was filesize I think. Small swf’s don’t work, bigger files (which have images embedded) do work…

  • I get this error using Scala 2.8.0.RC2_0

    scala.collection.immutable.Range.foreach$mVc$sp(Lscala/Function1;)V
    java.lang.NoSuchMethodError: scala.collection.immutable.Range.foreach$mVc$sp(Lscala/Function1;)V
    at apparat.swf.SwfOutputStream.writeSB(SwfOutputStream.scala:136)
    at apparat.swf.SwfOutputStream.writeUB(SwfOutputStream.scala:144)
    ……

    RC1 is no longer available on scala website. Should I look for RC1 or do you plan on upating your tool to the latest version of scala?

  • Frank: That is very interesting because I choose to pipe small files through std io instead of disk io. In that case I will simply always go with disk io. The limit is 256kb I think.

    seb: I will update the tools with the fix for the 7zip problem using RC2 soon. In the meantime, you could simply checkout the source and use “mvn package” if you cannot wait.

  • Yes it breaks around 256. RC2 and disk io fix, together in an update… sounds great

    Thanks…can’t wait

  • Do we have any resolution to this yet:
    java.lang.NoSuchMethodError: scala.collection.immutable.Range
    [stacktrace]

    Troubles with this and macports scala28 @0.2.8.0.RC2_0

    :(

  • No such file errors? I’m getting errors after having compiled apparat via googlecode wiki, eg : “no such file: apparat.tools.shell.ApparatShell”

    “no such file: apparat.tools.reducer.Reducer”

  • An RC2 build is now available at GoogleCode.

Leave a Reply