how to access to offline file path to play video? (Developer problem)

how to access to offline file path to play video? (Developer problem)

by sadaf sadafian -
Number of replies: 5
Picture of Plugin developers
hi
this is simplified of my question.
i can access to offline file via :

<ion-button fill="clear" [core-download-file]="{fileurl: '<% urlout %>', timemodified: '1712408908'}" moduleId="64" courseId="3" component="mod_myOwnModule" [attr.aria-label]="'core.download' | translate">

<ion-icon name="cloud-download" slot="icon-only" aria-hidden="true"></ion-icon>

</ion-button>

in my plugin's .mustache,

and i defined urlout in the mobile.php and this code work offline and online . if app is online ,then automatically use online use <% urlout %> and connect to server and if app i offline , then automatically try to show file via according mobile application. for example if my file is cartificate.pdf then open it via appropriate installed app in on my device. but my problem is:

my file is a specific video that i want play in app and don't want open it by other android player. i want simply it play such as mod_file or mod_lable if video was downloaded.

i use this code but only work app is online in .mustache:


<ion-content overflow-scroll="true"> 

<video controls="controls" preload="metadata" webkit-playsinline="webkit-playsinline" class="videoPlayer" id="video">

<source src="<% urlout %>" core-external-content component="mod_danehplayer" type="video/mp4" />

</video>

</ion-content>

how can i play a video that was downloaded in the offline mode? is there any example code? 

please note, my problem is not download a file for offline usage, i want play a video in the app in offline mode such as mod_resource or mod_lable.

Average of ratings: -
In reply to sadaf sadafian

Re: how to access to offline file path to play video? (Developer problem)

by Dani Palou -
Picture of Core developers Picture of Moodle HQ Picture of Peer reviewers Picture of Plugin developers
Hi,

I see you're adding the core-external-content directive to the "source", that directive should try to download the file in the following cases:

  • If the size of the file is less than 20MB and the user is on WiFi, or if the file less than 2MB, it should be downloaded the first time it's rendered.
  • If the file is bigger than that and the user is on WiFi, it should be downloaded in background the first time the user plays it.

Please check that you fulfill any of those conditions.

In the directive core-format-text we apply core-external-content automatically to all media elements, and in case of "source" elements we convert the "src" to "target-src", I guess we found a problem when using "src" directly (probably the video didn't detect the change of URL). So if the video is not downloaded, you can try using [targetSrc]="'<% urlout %>'" instead of src (please notice there are single quotes inside double quotes.

If this still doesn't work, you can try debugging the core-external-content directive to see why it isn't downloading the file. Or you can also try using core-format-text, but that means converting the video HTML to a string so it's better if core-external-content works properly without doing this.

Cheers,

Dani

In reply to Dani Palou

Re: how to access to offline file path to play video? (Developer problem)

by sadaf sadafian -
Picture of Plugin developers
Thanks dani
i use [src]="'<% urlout %>'" and problem solved and i can play video file in offline mode. it seems my problem was use not correct syntax.

Another question if you can please advise me: if we want to make some content of video url (urlout) like decoding then play video but with this condition that decoded video is not saved in the device and only the encrypted file is saved in the device for offline mode what is best practice? i have some js code that can play my encoded video file from moodle server

return [
'templates' => [
[
'id' => 'main',
'html' => $OUTPUT->render_from_template('mod_myownmodule/mobile_view_page', $data),
],
],
'javascript' => "
var secret = 'XXXXXXXXXXXXXXXXXXXX';
var url = 'https://mydomain.com/lms/mod/myownmodule/files/3_64.dp';

async function decryptBuffer(base64Encrypted, keyString) {

const iv = base64Encrypted.slice(0, 16);
const encryptedText = base64Encrypted.slice(16);
const encodedKey = new TextEncoder().encode(keyString);
const hashBuffer = await crypto.subtle.digest('SHA-256', encodedKey);
const key = await crypto.subtle.importKey('raw', hashBuffer, { name: 'AES-CBC' }, false, ['decrypt']);
const decryptedBuffer = await crypto.subtle.decrypt({ name: 'AES-CBC', iv }, key, encryptedText);

return decryptedBuffer;
}
async function decryptText(base64Encrypted, keyString) {
const decryptedText = new TextDecoder().decode(decryptBuffer(base64Encrypted, keyString));

return decryptedText;
}
async function downloadAndDecrypt(url, keyString) {
try {
// alert(1);
const response = await fetch(url);
// alert(2);
if (!response.ok) throw new Error('Network response was not ok. ' + response.status);
// alert(3);
const encryptedText = await response.arrayBuffer(); // Directly wait for the text
// alert(4);

const decryptedBuffer = await decryptBuffer(encryptedText, keyString);
// alert(5);



const textContent = new TextDecoder().decode(decryptedBuffer)
const mainBufferContent = decryptedBuffer.slice(textContent.search(':') + 1)

const blob = new Blob([mainBufferContent], { type: 'video/mp4' });

const videoURL = URL.createObjectURL(blob);
// alert(videoURL);
const video = document.getElementById('myvideo')
video.src = videoURL

return decryptedBuffer
} catch (error) {
alert('Error:' + error);
}
}
downloadAndDecrypt(url, secret);


",
'otherdata' => '',
'files' => array(
(
$offlinefile

)
)
];

by above code i can play an encoded video from my server in the application, but i want it can play in offline mode too and i am confused how to do that. is it need create my own directive or can use :
https://moodledev.io/general/app/development/plugins-development-guide#js-functions-visible-in-the-templates
or what need to do?
thank you
In reply to Dani Palou

Re: how to access to offline file path to play video? (Developer problem)

by sadaf sadafian -
Picture of Plugin developers
simplified of my need:
how to access to read or write to local file in the android via JS that loaded from 'javascript' => .... in the moodle mobile app?
In reply to sadaf sadafian

Re: how to access to offline file path to play video? (Developer problem)

by Dani Palou -
Picture of Core developers Picture of Moodle HQ Picture of Peer reviewers Picture of Plugin developers
Hi sadaf,

one possible solution could be to use a URL in the app that downloads the decoded file already, so the file stored in the app wouldn't need to be decoded. But maybe you don't want to do that for security/privacy reasons.

The first thing you need is the local path of the file, and you can obtain it using the CoreFilepoolProvider service in the Javascript code returned along with the template, in your classes/output/mobile.php. For example, you can use:

const url = 'THE URL OF THE FILE'; // If you don't have this URL in JS code, you can pass it to JS using otherdata and this.CONTENT_OTHERDATA.
const path = await this.CoreFilepoolProvider.getFilePathByUrl(this.CoreSitesProvider.getCurrentSiteId(), url);
With this code you will have the path of the file. Please notice that the file needs to be downloaded, if the file isn't downloaded you should either use the online URL or you can force downloading the file using

this.CoreFilepoolProvider.downloadUrl(this.CoreSitesProvider.getCurrentSiteId(), url)
This function will download the file if needed, and then return the path.

Once you have the path, you can read the file. Maybe the fetch function will work for local files too, but we usually use:

this.CoreFileProvider.readFile(path, format);
Where format is 0 for text, 1 for data URL, 2 for binary string and 3 for array buffer. Looking at your code, I guess you want to use format=3.

I hope this helps.

Cheers,
Dani
Average of ratings: Useful (1)
In reply to Dani Palou

Re: how to access to offline file path to play video? (Developer problem)

by sadaf sadafian -
Picture of Plugin developers
Hi Dani
worked
thanks a lot ♥🌹