Passed
Push — develop ( da884c...389d86 )
by Andrew
04:32
created

src/controllers/DefaultController.php (1 issue)

1
<?php
2
/**
3
 * Transcoder plugin for Craft CMS 3.x
4
 *
5
 * Transcode videos to various formats, and provide thumbnails of the video
6
 *
7
 * @link      https://nystudio107.com
8
 * @copyright Copyright (c) 2017 nystudio107
9
 */
10
11
namespace nystudio107\transcoder\controllers;
12
13
use nystudio107\transcoder\Transcoder;
14
15
use Craft;
16
use craft\web\Controller;
17
use craft\helpers\Json;
18
19
/**
20
 * @author    nystudio107
21
 * @package   Transcode
22
 * @since     1.0.0
23
 */
24
class DefaultController extends Controller
25
{
26
27
    // Protected Properties
28
    // =========================================================================
29
30
    /**
31
     * @var    bool|array Allows anonymous access to this controller's actions.
32
     *         The actions must be in 'kebab-case'
33
     * @access protected
34
     */
35
    protected $allowAnonymous = [
36
        'download-file',
37
        'progress',
38
    ];
39
40
    // Public Methods
41
    // =========================================================================
42
43
    /**
44
     * @inheritDoc
45
     */
0 ignored issues
show
Missing @return tag in function comment
Loading history...
46
    public function beforeAction($action)
47
    {
48
        if (!Transcoder::$settings->enableDownloadFileEndpoint) {
49
            $this->allowAnonymous = false;
50
        }
51
52
        return parent::beforeAction($action);
53
    }
54
55
    /**
56
     * Force the download of a given $url.  We do it this way to prevent people
57
     * from downloading things that are outside of the server root.
58
     *
59
     * @param $url
60
     *
61
     * @throws \yii\base\ExitException
62
     */
63
    public function actionDownloadFile($url)
64
    {
65
        $filePath = parse_url($url, PHP_URL_PATH);
66
        $filePath = $_SERVER['DOCUMENT_ROOT'].$filePath;
67
        Craft::$app->getResponse()->sendFile(
68
            $filePath,
69
            null,
70
            ['inline' => false]
71
        );
72
        Craft::$app->end();
73
    }
74
75
    /**
76
     * Return a JSON-encoded array providing the progress of the transcoding:
77
     *
78
     * 'filename' => the name of the file
79
     * 'duration' => the duration of the video/audio stream
80
     * 'time' => the time of the current encoding
81
     * 'progress' => a percentage indicating how much of the encoding is done
82
     *
83
     * @param $filename
84
     *
85
     * @return mixed
86
     */
87
    public function actionProgress($filename)
88
    {
89
        $result = [];
90
        $progressFile = sys_get_temp_dir().DIRECTORY_SEPARATOR.$filename.'.progress';
91
        if (file_exists($progressFile)) {
92
            $content = @file_get_contents($progressFile);
93
            if ($content) {
94
                // get duration of source
95
                preg_match('/Duration: (.*?), start:/', $content, $matches);
96
                if (\count($matches) > 0) {
97
                    $rawDuration = $matches[1];
98
99
                    // rawDuration is in 00:00:00.00 format. This converts it to seconds.
100
                    $ar = array_reverse(explode(':', $rawDuration));
101
                    $duration = (float)$ar[0];
102
                    if (!empty($ar[1])) {
103
                        $duration += (int)$ar[1] * 60;
104
                    }
105
                    if (!empty($ar[2])) {
106
                        $duration += (int)$ar[2] * 60 * 60;
107
                    }
108
                } else {
109
                    $duration = 'unknown'; // with GIF as input, duration is unknown
110
                }
111
112
                // Get the time in the file that is already encoded
113
                preg_match_all('/time=(.*?) bitrate/', $content, $matches);
114
                $rawTime = array_pop($matches);
115
116
                // this is needed if there is more than one match
117
                if (\is_array($rawTime)) {
118
                    $rawTime = array_pop($rawTime);
119
                }
120
121
                //rawTime is in 00:00:00.00 format. This converts it to seconds.
122
                $ar = array_reverse(explode(':', $rawTime));
123
                $time = (float)$ar[0];
124
                if (!empty($ar[1])) {
125
                    $time += (int)$ar[1] * 60;
126
                }
127
                if (!empty($ar[2])) {
128
                    $time += (int)$ar[2] * 60 * 60;
129
                }
130
131
                //calculate the progress
132
                if ($duration !== 'unknown') {
133
                    $progress = round(($time / $duration) * 100);
134
                } else {
135
                    $progress = 'unknown';
136
                }
137
138
                // return results
139
                if ($progress !== 'unknown' && $progress < 100) {
140
                    $result = [
141
                        'filename' => $filename,
142
                        'duration' => $duration,
143
                        'time' => $time,
144
                        'progress' => $progress,
145
                    ];
146
                } elseif ($progress === 'unknown') {
147
                    $result = [
148
                        'filename' => $filename,
149
                        'duration' => 'unknown',
150
                        'time' => $time,
151
                        'progress' => 'unknown',
152
                        'message' => 'encoding GIF, can\'t determine duration',
153
                    ];
154
                }
155
            }
156
        }
157
158
        return Json::encode($result);
159
    }
160
}
161