diff --git a/DIDLLite.py b/DIDLLite.py
index b029f55..e5e64ab 100644
--- a/DIDLLite.py
+++ b/DIDLLite.py
@@ -82,7 +82,11 @@ class Object(object):
 			SubElement(root, 'dc:creator').text = self.creator
 
 		if self.res is not None:
-			root.append(self.res.toElement())
+			try:
+				for res in iter(self.res):
+					root.append(res.toElement())
+			except TypeError:
+				root.append(self.res.toElement())
 
 		if self.writeStatus is not None:
 			SubElement(root, 'upnp:writeStatus').text = self.writeStatus
diff --git a/FSStorage.py b/FSStorage.py
index 48abd9a..817cb88 100644
--- a/FSStorage.py
+++ b/FSStorage.py
@@ -4,6 +4,8 @@
 # $Id$
 #
 
+ffmpeg_path = '/Users/jgurney/src/ffmpeg/ffmpeg'
+
 import FileDIDL
 import errno
 import itertools
@@ -12,8 +14,10 @@ import sets
 import stat
 
 from DIDLLite import StorageFolder, Item, VideoItem, AudioItem, TextItem, ImageItem, Resource
-from twisted.web import static
+from twisted.web import resource, server, static
 from twisted.python import log
+from twisted.internet import abstract, interfaces, process, protocol, reactor
+from zope.interface import implements
 
 __all__ = [ 'registerklassfun', 'FSObject', 'FSItem', 'FSVideoItem',
 		'FSAudioItem', 'FSTextItem', 'FSImageItem', 'mimetoklass',
@@ -69,13 +73,105 @@ class FSObject(object):
 		return '<%s.%s: path: %s>' % (self.__class__.__module__,
 		    self.__class__.__name__, self.FSpath)
 
+class NullConsumer(file, abstract.FileDescriptor):
+	implements(interfaces.IConsumer)
+
+	def __init__(self):
+		file.__init__(self, '/dev/null', 'w')
+		abstract.FileDescriptor.__init__(self)
+
+	def write(self, data):
+		pass
+
+class DynamTransfer(protocol.ProcessProtocol):
+	def __init__(self, path, mods, request):
+		self.path = path
+		self.mods = mods
+		self.request = request
+
+	def outReceived(self, data):
+		self.request.write(data)
+
+	def outConnectionLost(self):
+		if self.request:
+			self.request.unregisterProducer()
+			self.request.finish()
+			self.request = None
+
+	def errReceived(self, data):
+		pass
+		#log.msg(data)
+
+	def stopProducing(self):
+		if self.request:
+			self.request.unregisterProducer()
+			self.request.finish()
+
+		if self.proc:
+			self.proc.loseConnection()
+			self.proc.signalProcess('INT')
+
+		self.request = None
+		self.proc = None
+
+	pauseProducing = lambda x: x.proc.pauseProducing()
+	resumeProducing = lambda x: x.proc.resumeProducing()
+
+	def render(self):
+		mods = self.mods
+		path = self.path
+		request = self.request
+
+		vcodec = mods[0]
+		if mods[0] not in ('xvid', 'mpeg2', ):
+			vcodec = 'xvid'
+
+		mimetype = { 'xvid': 'video/avi', 'mpeg2': 'video/mpeg', }
+		request.setHeader('content-type', mimetype[vcodec])
+		if request.method == 'HEAD':
+			return ''
+
+		optdict = {
+			'xvid':	[ '-vcodec', 'xvid',
+				  #'-mv4', '-gmc', '-g', '240',
+				  '-f', 'avi', ],
+			'mpeg2': [ '-vcodec', 'mpeg2video', #'-g', '60',
+				   '-f', 'mpeg', ],
+			}
+		audio = [ '-acodec', 'mp3', '-ab', '192', ]
+		args = [ 'ffmpeg', '-i', path, '-b', '8000',
+		    #'-sc_threshold', '500000', '-b_strategy', '1', '-max_b_frames', '6',
+			] + optdict[vcodec] + audio + [ '-', ]
+		#log.msg(*args)
+		self.proc = process.Process(reactor, ffmpeg_path, args,
+		    None, None, self)
+		self.proc.closeStdin()
+		request.registerProducer(self, 1)
+
+		return server.NOT_DONE_YET
+
+class DynamicTrans(resource.Resource):
+	isLeaf = True
+
+	def __init__(self, path, notrans):
+		self.path = path
+		self.notrans = notrans
+
+	def render(self, request):
+		if request.postpath:
+			# Translation request
+			return DynamTransfer(self.path, request.postpath, request).render()
+		else:
+			return self.notrans.render(request)
+
 class FSItem(FSObject, Item):
 	def __init__(self, *args, **kwargs):
 		FSObject.__init__(self, kwargs['path'])
 		del kwargs['path']
 		mimetype = kwargs['mimetype']
 		del kwargs['mimetype']
-		kwargs['content'] = static.File(self.FSpath)
+		kwargs['content'] = DynamicTrans(self.FSpath,
+		    static.File(self.FSpath, mimetype))
 		Item.__init__(self, *args, **kwargs)
 		self.url = '%s/%s' % (self.cd.urlbase, self.id)
 		self.mimetype = mimetype
@@ -83,6 +179,9 @@ class FSItem(FSObject, Item):
 	def doUpdate(self):
 		self.res = Resource(self.url, 'http-get:*:%s:*' % self.mimetype)
 		self.res.size = os.path.getsize(self.FSpath)
+		self.res = [ self.res ]
+		self.res.append(Resource(self.url + '/mpeg2', 'http-get:*:%s:*' % 'video/mpeg'))
+		self.res.append(Resource(self.url + '/xvid', 'http-get:*:%s:*' % 'video/avi'))
 		Item.doUpdate(self)
 
 def defFS(path, fobj):
diff --git a/README b/README
index 0417103..6cc5c58 100644
--- a/README
+++ b/README
@@ -25,10 +25,17 @@ Good Luck!
 John-Mark Gurney <gurney_j@resnet.uoregon.edu>
 
 Ideas for future improvements:
+	Figure out how to rearchitect ContentDirectoryControl so I don't
+	  need to use doRecall.  This may be helped by not necessarily
+	  figuring out all the children of a member just to fetch it.
+	  childCount isn't a required attribute.
 	Autodetect IP address.
 	Support sorting by other attributes.
 
 v0.x:
+	Add support for multiple res elements and automatic transcoding
+	  to either avi/xvid or mpeg2 using ffmpeg.
+	Look inside DVDs and handle titles and chapters.
 	Empty dirs w/ no content would disappear, and cause a short
 	  response to BrowseDirectChildren.  The DSM-520 askes for one
 	  more than displayed, and uses the existant of the extra item