PluginProbe
Tutor LMS – eLearning and online course solution / 3.9.2
Tutor LMS – eLearning and online course solution v3.9.2
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 All 191 releases
tutor / classes / Video_Stream.php

Video_Stream.php in Tutor LMS – eLearning and online course solution 3.9.2, at classes/Video_Stream.php

219 lines 3.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Video Stream
4 *
5 * @package Tutor\VideoStream
6 * @author Themeum <support@themeum.com>
7 * @link https://themeum.com
8 * @since 1.0.0
9 */
10
11 namespace TUTOR;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17
18 /**
19 * Class Video_Stream
20 *
21 * @since 1.0.0
22 */
23 class Video_Stream {
24
25 /**
26 * Path
27 *
28 * @since 1.0.0
29 *
30 * @var string
31 */
32 private $path = '';
33
34 /**
35 * Stream
36 *
37 * @since 1.0.0
38 *
39 * @var string
40 */
41 private $stream = '';
42
43 /**
44 * Buffer time
45 *
46 * @since 1.0.0
47 *
48 * @var string
49 */
50 private $buffer = 102400;
51
52 /**
53 * Start
54 *
55 * @since 1.0.0
56 *
57 * @var int
58 */
59 private $start = -1;
60
61 /**
62 * End
63 *
64 * @since 1.0.0
65 *
66 * @var int
67 */
68 private $end = -1;
69
70 /**
71 * Size
72 *
73 * @since 1.0.0
74 *
75 * @var int
76 */
77 private $size = 0;
78
79 /**
80 * Video format
81 *
82 * @since 1.0.0
83 *
84 * @var string
85 */
86 private $video_format;
87
88 /**
89 * Resolve dependencies
90 *
91 * @since 1.0.0
92 *
93 * @param string $file_path file path.
94 */
95 public function __construct( $file_path ) {
96 $this->video_format = apply_filters(
97 'tutor_video_types',
98 array(
99 'mp4' => 'video/mp4',
100 'webm' => 'video/webm',
101 'ogg' => 'video/ogg',
102 )
103 );
104 $this->path = $file_path;
105 }
106
107 /**
108 * Open stream
109 *
110 * @since 1.0.0
111 *
112 * @return void
113 */
114 private function open() {
115 $this->stream = fopen( $this->path, 'rb' );
116 if ( ! ( $this->stream ) ) {
117 die( 'Could not open stream for reading' );
118 }
119 }
120
121 /**
122 * Set proper header to serve the video content
123 *
124 * @since 1.0.0
125 *
126 * @return void
127 */
128 private function set_header() {
129 ob_get_clean();
130
131 header( 'Content-Type: ' . $this->video_format[ strtolower( pathinfo( $this->path, PATHINFO_EXTENSION ) ) ] );
132 header( 'Cache-Control: max-age=2592000, public' );
133 header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', tutor_time() + 2592000 ) . ' GMT' );
134 header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', @filemtime( $this->path ) ) . ' GMT' );
135 $this->start = 0;
136 $this->size = filesize( $this->path );
137 $this->end = $this->size - 1;
138 header( 'Accept-Ranges: 0-' . $this->end );
139
140 if ( isset( $_SERVER['HTTP_RANGE'] ) ) {
141 $c_end = $this->end;
142 list(, $range) = explode( '=', sanitize_text_field( wp_unslash( $_SERVER['HTTP_RANGE'] ) ), 2 );
143
144 if ( '-' == $range ) {
145 $c_start = $this->size - substr( $range, 1 );
146 } else {
147 $range = explode( '-', $range );
148 $c_start = $range[0];
149
150 $c_end = ( isset( $range[1] ) && is_numeric( $range[1] ) ) ? $range[1] : $c_end;
151 }
152 $c_end = ( $c_end > $this->end ) ? $this->end : $c_end;
153 if ( $c_start > $c_end || $c_start > $this->size - 1 || $c_end >= $this->size ) {
154 header( 'HTTP/1.1 416 Requested Range Not Satisfiable' );
155 header( "Content-Range: bytes $this->start-$this->end/$this->size" );
156 exit;
157 }
158 $this->start = $c_start;
159 $this->end = $c_end;
160 $length = $this->end - $this->start + 1;
161 header( 'HTTP/1.1 206 Partial Content' );
162 header( 'Content-Length: ' . $length );
163 header( "Content-Range: bytes $this->start-$this->end/" . $this->size );
164 header( 'Accept-Ranges: bytes' );
165 } else {
166 header( 'Content-Length: ' . $this->size );
167 }
168
169 }
170
171 /**
172 * Close currently opened stream
173 *
174 * @since 1.0.0
175 *
176 * @return void
177 */
178 private function end() {
179 fclose( $this->stream );
180 exit;
181 }
182
183 /**
184 * Perform the streaming of calculated range
185 *
186 * @since 1.0.0
187 *
188 * @return void
189 */
190 private function stream() {
191 $i = $this->start;
192 set_time_limit( 0 );
193 while ( ! feof( $this->stream ) && $i <= $this->end ) {
194 $bytes_to_read = $this->buffer;
195 if ( ( $i + $bytes_to_read ) > $this->end ) {
196 $bytes_to_read = $this->end - $i + 1;
197 }
198 $data = @stream_get_contents( $this->stream, $bytes_to_read, $i );
199 echo wp_kses_post( $data );
200 flush();
201 $i += $bytes_to_read;
202 }
203 }
204
205 /**
206 * Start streaming tutor video content
207 *
208 * @since 1.0.0
209 *
210 * @return void
211 */
212 public function start() {
213 $this->open();
214 $this->set_header();
215 $this->stream();
216 $this->end();
217 }
218 }
219