As explained by Ryan in this comment, the CURLOPT_TIMEOUT causes transfers to abort after the three minute mark. I initially thought CURLOPT_TIMEOUT concerns transfer inactivity timeouts, but as the documentation explains, that isn't the case:
Pass a long as parameter containing timeout - the maximum time in seconds that you allow the entire transfer operation to take
As explained by Ryan in this comment, the CURLOPT_TIMEOUT causes transfers to abort after the three minute mark. I initially thought CURLOPT_TIMEOUT concerns transfer inactivity timeouts, but as the documentation explains, that isn't the case: