diff --git a/twitter/api.py b/twitter/api.py
index 94ec354..d41a648 100644
--- a/twitter/api.py
+++ b/twitter/api.py
@@ -1026,6 +1026,7 @@ class Api(object):
             parameters['attachment_url'] = attachment_url
 
         if media:
+            chunked_types = ['video/mp4', 'video/quicktime', 'image/gif']
             media_ids = []
             if isinstance(media, int):
                 media_ids.append(media)
@@ -1041,9 +1042,8 @@ class Api(object):
                     _, _, file_size, media_type = parse_media_file(media_file)
                     if media_type == 'image/gif' or media_type == 'video/mp4':
                         raise TwitterError(
-                            'You cannot post more than 1 GIF or 1 video in a '
-                            'single status.')
-                    if file_size > self.chunk_size:
+                            'You cannot post more than 1 GIF or 1 video in a single status.')
+                    if file_size > self.chunk_size or media_type in chunked_types:
                         media_id = self.UploadMediaChunked(
                             media=media_file,
                             additional_owners=media_additional_owners,
@@ -1055,13 +1055,11 @@ class Api(object):
                             media_category=media_category)
                     media_ids.append(media_id)
             else:
-                _, _, file_size, _ = parse_media_file(media)
-                if file_size > self.chunk_size:
-                    media_ids.append(
-                        self.UploadMediaChunked(media, media_additional_owners))
+                _, _, file_size, media_type = parse_media_file(media)
+                if file_size > self.chunk_size or media_type in chunked_types:
+                    media_ids.append(self.UploadMediaChunked(media, media_additional_owners))
                 else:
-                    media_ids.append(
-                        self.UploadMediaSimple(media, media_additional_owners))
+                    media_ids.append(self.UploadMediaSimple(media, media_additional_owners))
             parameters['media_ids'] = ','.join([str(mid) for mid in media_ids])
 
         if latitude is not None and longitude is not None:
@@ -1263,7 +1261,7 @@ class Api(object):
 
         try:
             media_fp.close()
-        except:
+        except Exception as e:
             pass
 
         return True
diff --git a/twitter/twitter_utils.py b/twitter/twitter_utils.py
index 0b2af5b..66ce8b2 100644
--- a/twitter/twitter_utils.py
+++ b/twitter/twitter_utils.py
@@ -223,8 +223,8 @@ def parse_media_file(passed_media):
     # Otherwise, if a file object was passed in the first place,
     # create the standard reference to media_file (i.e., rename it to fp).
     else:
-        if passed_media.mode != 'rb':
-            raise TwitterError({'message': 'File mode must be "rb".'})
+        if passed_media.mode not in ['rb', 'rb+', 'w+b']:
+            raise TwitterError('File mode must be "rb" or "rb+"')
         filename = os.path.basename(passed_media.name)
         data_file = passed_media
 
@@ -233,7 +233,7 @@ def parse_media_file(passed_media):
 
     try:
         data_file.seek(0)
-    except:
+    except Exception as e:
         pass
 
     media_type = mimetypes.guess_type(os.path.basename(filename))[0]

Issue with PostUpdate and <1MB mp4 media files
When trying post an update using the following code:
```python
api = twitter.Api(options)
api.VerifyCredentials()
api.PostUpdate('My status', media='/my/local/file.mp4')
```
Twitter would respond with the error 'media type unrecognized'.  The call worked sometimes but not always but I was finally able to narrow down the issue to the size of the mp4 file. While searching for the error message I found this http://stackoverflow.com/a/32250580.  According to the author if the upload is a video file (mp4) it must always be uploaded via the chunked upload API endpoint.  I was unable to verify this in the Twitter API docs (like here: https://dev.twitter.com/rest/media/uploading-media.html) but once I added a smaller chunk_size to my init (chunk_size=1024*16) all PostUpdate calls worked as expected. This (to me) is a dirty fix but it works for me and it should work for anyone else with a similar issue.

The question is should the library here be updated to automatically reduce the chunk size when uploading mp4 files?  I am not sure as I was unable to find any other information in the Twitter docs as to this mp4 chunked upload only restriction. But if the linked article is correct there should probably be some logic added into the PostUpdate code that would take into account if the video file is < 1MB in size. 
diff --git a/tests/test_api_30.py b/tests/test_api_30.py
index b966c70..67d7b33 100644
--- a/tests/test_api_30.py
+++ b/tests/test_api_30.py
@@ -2,9 +2,15 @@
 from __future__ import unicode_literals, print_function
 
 import json
+import os
 import re
 import sys
+from tempfile import NamedTemporaryFile
 import unittest
+try:
+    from unittest.mock import patch
+except ImportError:
+    from mock import patch
 import warnings
 
 import twitter
@@ -1713,3 +1719,16 @@ class ApiTest(unittest.TestCase):
         with warnings.catch_warnings(record=True) as w:
             resp = self.api.UpdateBackgroundImage(image='testdata/168NQ.jpg')
             self.assertTrue(issubclass(w[0].category, DeprecationWarning))
+
+    @responses.activate
+    @patch('twitter.api.Api.UploadMediaChunked')
+    def test_UploadSmallVideoUsesChunkedData(self, mocker):
+        responses.add(POST, DEFAULT_URL, body='{}')
+        video = NamedTemporaryFile(suffix='.mp4')
+        video.write(b'10' * 1024)
+        video.seek(0, 0)
+
+        resp = self.api.PostUpdate('test', media=video)
+        assert os.path.getsize(video.name) <= 1024 * 1024
+        assert isinstance(resp, twitter.Status)
+        assert twitter.api.Api.UploadMediaChunked.called

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest pytest-cov
3.9
requirements.txt requirements.testing.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
build==1.2.2.post1
cachetools==5.5.2
certifi==2025.1.31
chardet==5.2.0
charset-normalizer==3.4.1
check-manifest==0.50
codecov==2.1.13
colorama==0.4.6
coverage==7.8.0
coveralls==4.0.1
distlib==0.3.9
docopt==0.6.2
exceptiongroup==1.2.2
filelock==3.18.0
future==1.0.0
idna==3.10
importlib_metadata==8.6.1
iniconfig==2.1.0
mccabe==0.7.0
mock==5.2.0
oauthlib==3.2.2
packaging==24.2
platformdirs==4.3.7
pluggy==1.5.0
pycodestyle==2.13.0
pyproject-api==1.9.0
pyproject_hooks==1.2.0
pytest==8.3.5
pytest-cov==6.0.0
pytest-runner==6.0.1
-e git+https://github.com/bear/python-twitter.git@c28e9fb02680f30c9c56019f6836c2b47fa1d73a#egg=python_twitter
PyYAML==6.0.2
requests==2.32.3
requests-oauthlib==2.0.0
responses==0.25.7
six==1.17.0
tomli==2.2.1
tox==4.25.0
tox-pyenv==1.1.0
typing_extensions==4.13.0
urllib3==2.3.0
virtualenv==20.29.3
zipp==3.21.0

name: python-twitter
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - build==1.2.2.post1
      - cachetools==5.5.2
      - certifi==2025.1.31
      - chardet==5.2.0
      - charset-normalizer==3.4.1
      - check-manifest==0.50
      - codecov==2.1.13
      - colorama==0.4.6
      - coverage==7.8.0
      - coveralls==4.0.1
      - distlib==0.3.9
      - docopt==0.6.2
      - exceptiongroup==1.2.2
      - filelock==3.18.0
      - future==1.0.0
      - idna==3.10
      - importlib-metadata==8.6.1
      - iniconfig==2.1.0
      - mccabe==0.7.0
      - mock==5.2.0
      - oauthlib==3.2.2
      - packaging==24.2
      - platformdirs==4.3.7
      - pluggy==1.5.0
      - pycodestyle==2.13.0
      - pyproject-api==1.9.0
      - pyproject-hooks==1.2.0
      - pytest==8.3.5
      - pytest-cov==6.0.0
      - pytest-runner==6.0.1
      - pyyaml==6.0.2
      - requests==2.32.3
      - requests-oauthlib==2.0.0
      - responses==0.25.7
      - six==1.17.0
      - tomli==2.2.1
      - tox==4.25.0
      - tox-pyenv==1.1.0
      - typing-extensions==4.13.0
      - urllib3==2.3.0
      - virtualenv==20.29.3
      - zipp==3.21.0
prefix: /opt/conda/envs/python-twitter

tests/test_api_30.py::ApiTest::test_UploadSmallVideoUsesChunkedData
tests/test_api_30.py::ApiTest::testApiRaisesAuthErrors tests/test_api_30.py::ApiTest::testApiSetUp tests/test_api_30.py::ApiTest::testCreateBlock tests/test_api_30.py::ApiTest::testCreateFavorite tests/test_api_30.py::ApiTest::testCreateList tests/test_api_30.py::ApiTest::testCreateListsMember tests/test_api_30.py::ApiTest::testCreateListsMemberMultiple tests/test_api_30.py::ApiTest::testCreateMute tests/test_api_30.py::ApiTest::testCreateSubscription tests/test_api_30.py::ApiTest::testDestroyBlock tests/test_api_30.py::ApiTest::testDestroyDirectMessage tests/test_api_30.py::ApiTest::testDestroyFavorite tests/test_api_30.py::ApiTest::testDestroyList tests/test_api_30.py::ApiTest::testDestroyListsMember tests/test_api_30.py::ApiTest::testDestroyListsMemberMultiple tests/test_api_30.py::ApiTest::testDestroyMute tests/test_api_30.py::ApiTest::testDestroyStatus tests/test_api_30.py::ApiTest::testDestroySubscription tests/test_api_30.py::ApiTest::testFriendsErrorChecking tests/test_api_30.py::ApiTest::testGetBlocks tests/test_api_30.py::ApiTest::testGetBlocksIDs tests/test_api_30.py::ApiTest::testGetBlocksIDsPaged tests/test_api_30.py::ApiTest::testGetBlocksPaged tests/test_api_30.py::ApiTest::testGetDirectMessages tests/test_api_30.py::ApiTest::testGetFavorites tests/test_api_30.py::ApiTest::testGetFollowerIDsPaged tests/test_api_30.py::ApiTest::testGetFollowers tests/test_api_30.py::ApiTest::testGetFollowersIDs tests/test_api_30.py::ApiTest::testGetFollowersPaged tests/test_api_30.py::ApiTest::testGetFriendIDs tests/test_api_30.py::ApiTest::testGetFriendIDsPaged tests/test_api_30.py::ApiTest::testGetFriends tests/test_api_30.py::ApiTest::testGetFriendsAdditionalParams tests/test_api_30.py::ApiTest::testGetFriendsPaged tests/test_api_30.py::ApiTest::testGetFriendsPagedUID tests/test_api_30.py::ApiTest::testGetFriendsWithLimit tests/test_api_30.py::ApiTest::testGetHelpConfiguration tests/test_api_30.py::ApiTest::testGetHomeTimeline tests/test_api_30.py::ApiTest::testGetHomeTimelineWithExclusions tests/test_api_30.py::ApiTest::testGetListMembers tests/test_api_30.py::ApiTest::testGetListMembersPaged tests/test_api_30.py::ApiTest::testGetListTimeline tests/test_api_30.py::ApiTest::testGetLists tests/test_api_30.py::ApiTest::testGetListsList tests/test_api_30.py::ApiTest::testGetMemberships tests/test_api_30.py::ApiTest::testGetMentions tests/test_api_30.py::ApiTest::testGetMutes tests/test_api_30.py::ApiTest::testGetMutesIDs tests/test_api_30.py::ApiTest::testGetRetweeters tests/test_api_30.py::ApiTest::testGetRetweets tests/test_api_30.py::ApiTest::testGetRetweetsCount tests/test_api_30.py::ApiTest::testGetSeachRawQuery tests/test_api_30.py::ApiTest::testGetSearch tests/test_api_30.py::ApiTest::testGetSearchGeocode tests/test_api_30.py::ApiTest::testGetSentDirectMessages tests/test_api_30.py::ApiTest::testGetShortUrlLength tests/test_api_30.py::ApiTest::testGetStatus tests/test_api_30.py::ApiTest::testGetStatusExtraParams tests/test_api_30.py::ApiTest::testGetStatusOembed tests/test_api_30.py::ApiTest::testGetStatusWithExtAltText tests/test_api_30.py::ApiTest::testGetSubscriptions tests/test_api_30.py::ApiTest::testGetSubscriptionsSN tests/test_api_30.py::ApiTest::testGetTrendsCurrent tests/test_api_30.py::ApiTest::testGetUser tests/test_api_30.py::ApiTest::testGetUserSuggestion tests/test_api_30.py::ApiTest::testGetUserSuggestionCategories tests/test_api_30.py::ApiTest::testGetUserTimeSinceMax tests/test_api_30.py::ApiTest::testGetUserTimelineByScreenName tests/test_api_30.py::ApiTest::testGetUserTimelineByUserID tests/test_api_30.py::ApiTest::testGetUserTimelineCount tests/test_api_30.py::ApiTest::testGetUsersSearch tests/test_api_30.py::ApiTest::testLookupFriendship tests/test_api_30.py::ApiTest::testLookupFriendshipBlockMute tests/test_api_30.py::ApiTest::testLookupFriendshipMute tests/test_api_30.py::ApiTest::testMuteBlockParamsAndErrors tests/test_api_30.py::ApiTest::testPostDirectMessage tests/test_api_30.py::ApiTest::testPostMediaMetadata tests/test_api_30.py::ApiTest::testPostUpdate tests/test_api_30.py::ApiTest::testPostUpdateExtraParams tests/test_api_30.py::ApiTest::testPostUpdateWithMedia tests/test_api_30.py::ApiTest::testPostUploadMediaChunkedAppend tests/test_api_30.py::ApiTest::testPostUploadMediaChunkedAppendNonASCIIFilename tests/test_api_30.py::ApiTest::testPostUploadMediaChunkedFinalize tests/test_api_30.py::ApiTest::testPostUploadMediaChunkedInit tests/test_api_30.py::ApiTest::testSetAndClearCredentials tests/test_api_30.py::ApiTest::testShowFriendship tests/test_api_30.py::ApiTest::testShowSubscription tests/test_api_30.py::ApiTest::testUpdateBanner tests/test_api_30.py::ApiTest::testUpdateBanner400Error tests/test_api_30.py::ApiTest::testUpdateBanner422Error tests/test_api_30.py::ApiTest::testUsersLookup tests/test_api_30.py::ApiTest::testVerifyCredentials tests/test_api_30.py::ApiTest::testVerifyCredentialsIncludeEmail tests/test_api_30.py::ApiTest::test_UpdateBackgroundImage_deprecation
twitter/api.py twitter/twitter_utils.py
twitter/api.py twitter/twitter_utils.py