{"id":611,"date":"2008-09-26T22:20:52","date_gmt":"2008-09-27T05:20:52","guid":{"rendered":"http:\/\/multimedia.cx\/eggs\/baldur-in-bulk\/"},"modified":"2020-07-25T22:15:44","modified_gmt":"2020-07-26T05:15:44","slug":"baldur-in-bulk","status":"publish","type":"post","link":"https:\/\/multimedia.cx\/eggs\/baldur-in-bulk\/","title":{"rendered":"Baldur In Bulk"},"content":{"rendered":"<p>I got those <a href=\"http:\/\/www.mobygames.com\/game\/baldurs-gate\">Baldur&#8217;s Gate<\/a> videos converted to something more modern. The problem turned out to be in the Interplay MVE demuxer code I wrote long ago for <a href=\"http:\/\/ffmpeg.org\/\">FFmpeg<\/a>. Once upon a time, timestamps in FFmpeg were supposed to be in reference to a 90 kHz clock. Thanks to <a href=\"http:\/\/multimedia.cx\/eggs\/interplay-conversion-again\/#comment-129562\">Pengvado for pointing out<\/a> that my demuxer still made that assumption. Fixing the demuxer seems like a lot of work right now. So at this point in the exercise, I opted to simply hard code 15 fps for the framerate.<\/p>\n<p>So I got that transcoding process underway, finally. And I made an interesting discovery along the way. I have a colleague who has this quote on his office whiteboard:<\/p>\n<p><center><br \/>\n<img decoding=\"async\" src=\"\/eggs\/images\/baldursgate-nietzsche-quote.jpg\" alt=\"Baldur's Gate Nietzsche quote\" \/><br \/>\n<\/center><\/p>\n<p>I can only conclude that said colleague is a huge Baldur&#8217;s Gate fan.<\/p>\n<p><strong>Prerequisites for the transcoding operation (basic Kubuntu 8.04 virtual machine):<\/strong><\/p>\n<ul>\n<li>install the libfaac-dev package<\/li>\n<li>download and manually compile <a href=\"http:\/\/www.tortall.net\/projects\/yasm\/\">YASM<\/a> (required by x264 and the latest YASM packaged by Ubuntu is not bleeding edge enough)<\/li>\n<li>download and compile the latest <a href=\"http:\/\/www.videolan.org\/developers\/x264.html\">x264<\/a> snapshot; configure with &#8211;enable-shared<\/li>\n<li>get the latest SVN of FFmpeg<\/li>\n<li>configure and build FFmpeg with: configure &#8211;enable-gpl &#8211;enable-postproc &#8211;enable-avfilter &#8211;enable-avfilter-lavf &#8211;enable-swscale &#8211;enable-libx264 &#8211;enable-libfaac; I don&#8217;t really know if all the filter options are strictly necessary for this exercise but I&#8217;m used to them by now<\/li>\n<\/ul>\n<p><strong>So my process for transcoding in bulk after installing this software is:<\/strong><\/p>\n<ul>\n<li>use my Python script (parse-bif-graf.py, listed at the end of this post) to split the BIF resource into its constituent MVE files:\n<pre>\r\n$ parse-bif-graf.py MovieCD1.bif\r\nextracting file #0 at offset 132, 29654204 bytes, to 'MovieCD1.bif-0.mve'\r\nextracting file #1 at offset 29654336, 6530954 bytes, to 'MovieCD1.bif-1.mve'\r\n[...]\r\n<\/pre>\n<\/li>\n<li>bulk transcode:\n<pre>\r\nfor mve in `ls *.mve`\r\ndo \r\n  ffmpeg -y -i $mve \\\r\n  -acodec libfaac -ab 128k \\\r\n  -vcodec libx264 -vpre hq -b 500k -bt 500k \\\r\n  `basename $mve .mve`.mp4\r\ndone\r\n[...]\r\n<\/pre>\n<\/li>\n<\/ul>\n<p>The resulting files are highly competitive, size-wise, against the original MVE files. At first, I was monkeying with the bitrate because there were some annoying artifacts in the high motion areas. But then I watched the original videos using ffplay and realized that those artifacts are artifacts in the source material.<\/p>\n<p><!--more--><br \/>\n<strong>parse-bif-graf.py:<\/strong><\/p>\n<p><script src=\"https:\/\/gist.github.com\/multimediamike\/091b3961ec2fcceb56a61d3b3c157a12.js\"><\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I got those Baldur&#8217;s Gate videos converted to something more modern. The problem turned out to be in the Interplay MVE demuxer code I wrote long ago for FFmpeg. Once upon a time, timestamps in FFmpeg were supposed to be in reference to a 90 kHz clock. Thanks to Pengvado for pointing out that my [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[29,55],"tags":[],"class_list":["post-611","post","type-post","status-publish","format-standard","hentry","category-game-hacking","category-python"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/611","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/comments?post=611"}],"version-history":[{"count":3,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/611\/revisions"}],"predecessor-version":[{"id":4581,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/611\/revisions\/4581"}],"wp:attachment":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/media?parent=611"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/categories?post=611"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/tags?post=611"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}