diff --git a/xbob/io/file.cpp b/xbob/io/file.cpp
index f551810c724937eb9a1419ffdff2cd3693d375ab..fc38194e21f3aa31922fe1c420cacb60013090aa 100644
--- a/xbob/io/file.cpp
+++ b/xbob/io/file.cpp
@@ -243,15 +243,40 @@ static PyObject* PyBobIoFile_GetSlice (PyBobIoFileObject* self, Py_ssize_t start
   PyObject* retval = PyList_New(length);
   if (!retval) return 0;
 
+  const bob::core::array::typeinfo& info = self->f->type();
+
+  npy_intp shape[NPY_MAXDIMS];
+  for (int k=0; k<info.nd; ++k) shape[k] = info.shape[k];
+
+  int type_num = PyBobIo_AsTypenum(info.dtype);
+  if (type_num == NPY_NOTYPE) return 0; ///< failure
+
   Py_ssize_t counter = 0;
   for (auto i = start; (start<=stop)?i<stop:i>stop; i+=step) {
 
-    PyObject* item = PyBobIoFile_GetIndex(self, i);
+    PyObject* item = PyArray_SimpleNew(info.nd, shape, type_num);
     if (!item) {
       Py_DECREF(retval);
       return 0;
     }
 
+    try {
+      bobskin skin(item, info.dtype);
+      self->f->read(skin, i);
+    }
+    catch (std::exception& e) {
+      if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught std::exception while reading object #%" PY_FORMAT_SIZE_T "d from file `%s': %s", i, self->f->filename().c_str(), e.what());
+      Py_DECREF(retval);
+      Py_DECREF(item);
+      return 0;
+    }
+    catch (...) {
+      if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading object #%" PY_FORMAT_SIZE_T "d from file `%s'", i, self->f->filename().c_str());
+      Py_DECREF(retval);
+      Py_DECREF(item);
+      return 0;
+    }
+
     PyList_SET_ITEM(retval, counter++, item);
 
   }
diff --git a/xbob/io/test/test_file.py b/xbob/io/test/test_file.py
index 6046492e2f66772040da66a5a3927b3b127477c3..77971923059b73a6560bbec44e050efd710bde62 100644
--- a/xbob/io/test/test_file.py
+++ b/xbob/io/test/test_file.py
@@ -24,59 +24,79 @@ def test_peek():
   assert peek_all(f) == (numpy.uint16, (3,3), (3,1))
 
 def test_indexing():
-  
-  f = File(testutils.datafile('matlab_2d.hdf5', __name__), 'r')
+ 
+  fname = testutils.datafile('matlab_2d.hdf5', __name__)
+  f = File(fname, 'r')
   nose.tools.eq_(len(f), 512)
 
-  objs = f[:]
+  objs = load(fname)
   nose.tools.eq_(len(f), len(objs))
-  obj0 = f[0]
-  obj1 = f[1]
 
   # simple indexing
-  assert numpy.allclose(objs[0], obj0)
-  assert numpy.allclose(objs[1], obj1)
-  assert numpy.allclose(f[len(f)-1], f[-1])
-  assert numpy.allclose(f[len(f)-2], f[-2])
+  assert numpy.allclose(f[0], objs[0])
+  assert numpy.allclose(f[1], objs[1])
+  assert numpy.allclose(f[-1], objs[-1])
+  assert numpy.allclose(f[-2], objs[-2])
+
+def test_slicing_0():
+
+  fname = testutils.datafile('matlab_2d.hdf5', __name__)
+  f = File(fname, 'r')
+
+  objs = f[:]
+  for i, k in enumerate(load(fname)):
+    assert numpy.allclose(k, objs[i])
+
+def test_slicing_1():
+
+  fname = testutils.datafile('matlab_2d.hdf5', __name__)
+  f = File(fname, 'r')
 
   # get slice
   s1 = f[3:10:2]
   nose.tools.eq_(len(s1), 4)
-  assert numpy.allclose(s1[0], objs[3])
-  assert numpy.allclose(s1[1], objs[5])
-  assert numpy.allclose(s1[2], objs[7])
-  assert numpy.allclose(s1[3], objs[9])
+  assert numpy.allclose(s1[0], f[3])
+  assert numpy.allclose(s1[1], f[5])
+  assert numpy.allclose(s1[2], f[7])
+  assert numpy.allclose(s1[3], f[9])
+
+def test_slicing_2():
+
+  fname = testutils.datafile('matlab_2d.hdf5', __name__)
+  f = File(fname, 'r')
 
   # get negative slicing
-  s2 = f[-10:-2:3]
-  nose.tools.eq_(len(s2), 3)
-  assert numpy.allclose(s2[0], f[len(f)-10])
-  assert numpy.allclose(s2[1], f[len(f)-7])
-  assert numpy.allclose(s2[2], f[len(f)-4])
+  s = f[-10:-2:3]
+  nose.tools.eq_(len(s), 3)
+  assert numpy.allclose(s[0], f[len(f)-10])
+  assert numpy.allclose(s[1], f[len(f)-7])
+  assert numpy.allclose(s[2], f[len(f)-4])
+
+def test_slicing_3():
+
+  fname = testutils.datafile('matlab_2d.hdf5', __name__)
+  f = File(fname, 'r')
 
   # get negative stepping slice
-  s3 = f[20:10:-3]
-  nose.tools.eq_(len(s3), 4)
-  assert numpy.allclose(s3[0], f[20])
-  assert numpy.allclose(s3[1], f[17])
-  assert numpy.allclose(s3[2], f[14])
-  assert numpy.allclose(s3[3], f[11])
-
-  # get negative indexing and positive stepping slice
-  s4 = f[-20:-10:3]
-  nose.tools.eq_(len(s4), 4)
-  assert numpy.allclose(s4[0], f[len(f)-20])
-  assert numpy.allclose(s4[1], f[len(f)-17])
-  assert numpy.allclose(s4[2], f[len(f)-14])
-  assert numpy.allclose(s4[3], f[len(f)-11])
+  s = f[20:10:-3]
+  nose.tools.eq_(len(s), 4)
+  assert numpy.allclose(s[0], f[20])
+  assert numpy.allclose(s[1], f[17])
+  assert numpy.allclose(s[2], f[14])
+  assert numpy.allclose(s[3], f[11])
+
+def test_slicing_4():
+
+  fname = testutils.datafile('matlab_2d.hdf5', __name__)
+  f = File(fname, 'r')
 
   # get all negative slice
-  s5 = f[-10:-20:-3]
-  nose.tools.eq_(len(s5), 4)
-  assert numpy.allclose(s5[0], f[len(f)-10])
-  assert numpy.allclose(s5[1], f[len(f)-13])
-  assert numpy.allclose(s5[2], f[len(f)-16])
-  assert numpy.allclose(s5[3], f[len(f)-19])
+  s = f[-10:-20:-3]
+  nose.tools.eq_(len(s), 4)
+  assert numpy.allclose(s[0], f[len(f)-10])
+  assert numpy.allclose(s[1], f[len(f)-13])
+  assert numpy.allclose(s[2], f[len(f)-16])
+  assert numpy.allclose(s[3], f[len(f)-19])
 
 @nose.tools.raises(TypeError)
 def test_indexing_type_check():
diff --git a/xbob/io/test/test_video.py b/xbob/io/test/test_video.py
index 323b946ce7a64df4673de7af107534c123925e5e..f13a3cc2ac5288d8687045bdf7d12096a3bfd048 100644
--- a/xbob/io/test/test_video.py
+++ b/xbob/io/test/test_video.py
@@ -100,11 +100,94 @@ def test_video_reader_str():
   assert repr(iv)
   assert str(iv)
 
+@testutils.ffmpeg_found()
+def test_indexing():
+
+  from .. import VideoReader
+  f = VideoReader(INPUT_VIDEO)
+
+  nose.tools.eq_(len(f), 375)
+
+  objs = f[:10]
+  nose.tools.eq_(len(objs), 10)
+  obj0 = f[0]
+  obj1 = f[1]
+
+  # simple indexing
+  assert numpy.allclose(objs[0], obj0)
+  assert numpy.allclose(objs[1], obj1)
+  assert numpy.allclose(f[len(f)-1], f[-1])
+  assert numpy.allclose(f[len(f)-2], f[-2])
+
+@testutils.ffmpeg_found()
+def test_slicing_0():
+
+  from .. import load, VideoReader
+  f = VideoReader(INPUT_VIDEO)
+
+  objs = f[:]
+  for i, k in enumerate(load(INPUT_VIDEO)):
+    assert numpy.allclose(k, objs[i])
+
+@testutils.ffmpeg_found()
+def test_slicing_1():
+
+  from .. import VideoReader
+  f = VideoReader(INPUT_VIDEO)
+
+  s = f[3:10:2]
+  nose.tools.eq_(len(s), 4)
+  assert numpy.allclose(s[0], f[3])
+  assert numpy.allclose(s[1], f[5])
+  assert numpy.allclose(s[2], f[7])
+  assert numpy.allclose(s[3], f[9])
+
+@testutils.ffmpeg_found()
+def test_slicing_2():
+
+  from .. import VideoReader
+  f = VideoReader(INPUT_VIDEO)
+
+  s = f[-10:-2:3]
+  nose.tools.eq_(len(s), 3)
+  assert numpy.allclose(s[0], f[len(f)-10])
+  assert numpy.allclose(s[1], f[len(f)-7])
+  assert numpy.allclose(s[2], f[len(f)-4])
+
+@testutils.ffmpeg_found()
+def test_slicing_3():
+
+  from .. import VideoReader
+  f = VideoReader(INPUT_VIDEO)
+  objs = f.load()
+
+  # get negative stepping slice
+  s = f[20:10:-3]
+  nose.tools.eq_(len(s), 4)
+  assert numpy.allclose(s[0], f[20])
+  assert numpy.allclose(s[1], f[17])
+  assert numpy.allclose(s[2], f[14])
+  assert numpy.allclose(s[3], f[11])
+
+@testutils.ffmpeg_found()
+def test_slicing_4():
+
+  from .. import VideoReader
+  f = VideoReader(INPUT_VIDEO)
+  objs = f[:21]
+
+  # get all negative slice
+  s = f[-10:-20:-3]
+  nose.tools.eq_(len(s), 4)
+  assert numpy.allclose(s[0], f[len(f)-10])
+  assert numpy.allclose(s[1], f[len(f)-13])
+  assert numpy.allclose(s[2], f[len(f)-16])
+  assert numpy.allclose(s[3], f[len(f)-19])
+
+
 @testutils.ffmpeg_found()
 def test_can_use_array_interface():
 
-  # This shows you can use the array interface to read an entire video
-  # sequence in a single shot
   from .. import load, VideoReader
   array = load(INPUT_VIDEO)
   iv = VideoReader(INPUT_VIDEO)
diff --git a/xbob/io/videoreader.cpp b/xbob/io/videoreader.cpp
index fdb2f4462e16662e6a560140c761936adbbc5b5d..8856aadbffc4ce0829dbadedfb8acf13eab91abe 100644
--- a/xbob/io/videoreader.cpp
+++ b/xbob/io/videoreader.cpp
@@ -129,8 +129,8 @@ PyDoc_STRVAR(s_width_str, "width");
 PyDoc_STRVAR(s_width_doc,
 "[int] The width of each frame in the video (a multiple of 2)");
 
-PyObject* PyBobIoVideoReader_Len(PyBobIoVideoReaderObject* self) {
-  return Py_BuildValue("n", self->v->numberOfFrames());
+Py_ssize_t PyBobIoVideoReader_Len(PyBobIoVideoReaderObject* self) {
+  return self->v->numberOfFrames();
 }
 
 PyDoc_STRVAR(s_number_of_frames_str, "number_of_frames");
@@ -412,7 +412,9 @@ static PyMethodDef PyBobIoVideoReader_Methods[] = {
     {0}  /* Sentinel */
 };
 
-static PyObject* PyBobIoVideoReader_GetItem (PyBobIoVideoReaderObject* self, Py_ssize_t i) {
+static PyObject* PyBobIoVideoReader_GetIndex (PyBobIoVideoReaderObject* self, Py_ssize_t i) {
+
+  if (i < 0) i += self->v->numberOfFrames(); ///< adjust for negative indexing
 
   if (i < 0 || i >= self->v->numberOfFrames()) {
     PyErr_Format(PyExc_IndexError, "video frame index out of range - `%s' only contains %" PY_FORMAT_SIZE_T "d frame(s)", self->v->filename().c_str(), self->v->numberOfFrames());
@@ -451,17 +453,10 @@ static PyObject* PyBobIoVideoReader_GetItem (PyBobIoVideoReaderObject* self, Py_
 
 }
 
-static PyObject* PyBobIoVideoReader_GetSlice (PyBobIoVideoReaderObject* self, Py_ssize_t lo, Py_ssize_t hi) {
-
-  if (lo < 0 || lo >= self->v->numberOfFrames()) {
-    PyErr_Format(PyExc_IndexError, "video frame index out of range - `%s' only contains %" PY_FORMAT_SIZE_T "d frame(s)", self->v->filename().c_str(), self->v->numberOfFrames());
-    return 0;
-  }
+static PyObject* PyBobIoVideoReader_GetSlice (PyBobIoVideoReaderObject* self, Py_ssize_t start, Py_ssize_t stop, Py_ssize_t step, Py_ssize_t length) {
 
-  if (hi < 0 || hi >= self->v->numberOfFrames()) {
-    PyErr_Format(PyExc_IndexError, "video frame index out of range - `%s' only contains %" PY_FORMAT_SIZE_T "d frame(s)", self->v->filename().c_str(), self->v->numberOfFrames());
-    return 0;
-  }
+  PyObject* retval = PyList_New(length);
+  if (!retval) return 0;
 
   const bob::core::array::typeinfo& info = self->v->frame_type();
 
@@ -471,55 +466,73 @@ static PyObject* PyBobIoVideoReader_GetSlice (PyBobIoVideoReaderObject* self, Py
   int type_num = PyBobIo_AsTypenum(info.dtype);
   if (type_num == NPY_NOTYPE) return 0; ///< failure
 
-  PyObject* retval = PyList_New(0);
-  if (!retval) return 0;
+  Py_ssize_t counter = 0;
+  Py_ssize_t lo, hi, st;
+  auto it = self->v->begin();
 
-  PyObject* frame = 0;
+  if (start <= stop) lo = start, hi = stop, st = step, it += lo;
+  else lo = stop, hi = start, st = -step, it += lo + (hi-lo)%st;
 
-  try {
-    auto it = self->v->begin();
-    it += lo;
-    for (size_t i=lo; it.parent() && i<hi; ++i) {
-      Check_Interrupt();
-      frame = PyArray_SimpleNew(info.nd, shape, type_num);
-      if (!frame) {
-        Py_DECREF(retval);
-        return 0;
-      }
-      bobskin skin(frame, info.dtype);
+  for (auto i=lo; i<hi; i+=st) {
+
+    PyObject* item = PyArray_SimpleNew(info.nd, shape, type_num);
+    if (!item) {
+      Py_DECREF(retval);
+      return 0;
+    }
+
+    try {
+      bobskin skin(item, info.dtype);
       it.read(skin);
-      int ok = PyList_Append(retval, frame);
-      Py_DECREF(frame);
-      frame = 0;
-      if (ok != 0) {
-        Py_DECREF(retval);
-        return 0;
-      }
+      it += (st-1);
     }
-  }
-  catch (std::exception& e) {
-    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught std::exception while reading slice [%" PY_FORMAT_SIZE_T "d, %" PY_FORMAT_SIZE_T "d[ from file `%s': %s", lo, hi, self->v->filename().c_str(), e.what());
-    Py_XDECREF(frame);
-    Py_DECREF(retval);
-    return 0;
-  }
-  catch (...) {
-    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught std::exception while reading slice [%" PY_FORMAT_SIZE_T "d, %" PY_FORMAT_SIZE_T "d[ from file `%s'", lo, hi, self->v->filename().c_str());
-    Py_XDECREF(frame);
-    Py_DECREF(retval);
-    return 0;
+    catch (std::exception& e) {
+      if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught std::exception while reading frame %" PY_FORMAT_SIZE_T "d from file `%s': %s", i, self->v->filename().c_str(), e.what());
+      Py_DECREF(retval);
+      Py_DECREF(item);
+      return 0;
+    }
+    catch (...) {
+      if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading frame #%" PY_FORMAT_SIZE_T "d from file `%s'", i, self->v->filename().c_str());
+      Py_DECREF(retval);
+      Py_DECREF(item);
+      return 0;
+    }
+
+    PyList_SET_ITEM(retval, counter++, item);
+
   }
 
+  if (st == -step) PyList_Reverse(retval);
+
   return retval;
 
 }
 
-static PySequenceMethods PyBobIoVideoReader_Sequence = {
-    (lenfunc)PyBobIoVideoReader_Len,
-    0, /* concat */
-    0, /* repeat */
-    (ssizeargfunc)PyBobIoVideoReader_GetItem,
-    (ssizessizeargfunc)PyBobIoVideoReader_GetSlice
+static PyObject* PyBobIoVideoReader_GetItem (PyBobIoVideoReaderObject* self, PyObject* item) {
+   if (PyIndex_Check(item)) {
+     Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+     if (i == -1 && PyErr_Occurred()) return 0;
+     return PyBobIoVideoReader_GetIndex(self, i);
+   }
+   if (PySlice_Check(item)) {
+     Py_ssize_t start, stop, step, slicelength;
+     if (PySlice_GetIndicesEx((PySliceObject*)item, self->v->numberOfFrames(), 
+           &start, &stop, &step, &slicelength) < 0) return 0;
+     if (slicelength <= 0) return PyList_New(0);
+     return PyBobIoVideoReader_GetSlice(self, start, stop, step, slicelength);
+   }
+   else {
+     PyErr_Format(PyExc_TypeError, "VideoReader indices must be integers, not %.200s",
+         item->ob_type->tp_name);
+     return 0;
+   }
+}
+
+static PyMappingMethods PyBobIoVideoReader_Mapping = {
+    (lenfunc)PyBobIoVideoReader_Len, //mp_lenght
+    (binaryfunc)PyBobIoVideoReader_GetItem, //mp_subscript
+    0 /* (objobjargproc)PyBobIoVideoReader_SetItem //mp_ass_subscript */
 };
 
 PyTypeObject PyBobIoVideoReader_Type = {
@@ -535,8 +548,8 @@ PyTypeObject PyBobIoVideoReader_Type = {
     0,                                          /*tp_compare*/
     (reprfunc)PyBobIoVideoReader_Repr,          /*tp_repr*/
     0,                                          /*tp_as_number*/
-    &PyBobIoVideoReader_Sequence,               /*tp_as_sequence*/
-    0,                                          /*tp_as_mapping*/
+    0,                                          /*tp_as_sequence*/
+    &PyBobIoVideoReader_Mapping,                /*tp_as_mapping*/
     0,                                          /*tp_hash */
     0,                                          /*tp_call*/
     (reprfunc)PyBobIoVideoReader_Print,         /*tp_str*/