Comments (31)
I think there is a misunderstanding about the file size.
The video file can be 2 or 4 GB yes, but the process reading that is the gpmfExtract that is blazing fast, it takes a few seconds.
The gpmfExtract generates a file that is a few MBs in size, in my case it is 2.68 MB.
This 2-3 Mb file is the one that is processed by the gopro-telemetry and that is the culprit for this issue.
Therefore we are testing the gopro-telemetry performance with a 2-3 MB file.
from gopro-telemetry.
Try reading the LRV files instead; they do have the same data but a smaller video resolution (basically a thumbnail). It should lead much faster...
from gopro-telemetry.
Try reading the LRV files instead; they do have the same data but a smaller video resolution (basically a thumbnail). It should lead much faster...
Thanks. Unfortunately that is not a viable option
from gopro-telemetry.
Hi. I don't use the library on a browser, so I don't know if that's slow or not. We can leave this open in case someone else has insights. I wouldn't expect the LRV files to make a difference, as the data stream is the same size, so that should not affect gopro-telemetry, just gpmf-extract
from gopro-telemetry.
Ok, thanks. Apart from this minor issue the library works well, great job!
from gopro-telemetry.
Same issue here. I have MP4 files that are around 4GB in size, and gpmfExtract works quite fast, but goproTelemetry takes ages and eats unholy amounts of memory, so much so that I cannot run it on my local device. I did telemetry extraction myself with a Python implementation and that was basically instant, so I am convinced that there must be some bug/misallocation here - though not sure where.
from gopro-telemetry.
Streaming might be the solution for memory footprint. It would also grant user feedback about progress... For how long it takes... who knows why Python is so fast. The original C code is only about 20% faster; thus, it would not be real to try to fix this...
from gopro-telemetry.
I cannot follow the code really, there are so many nested loops and components that without properly profiling, I doubt we can say anything about it. I don't think I will have time for it, but if I do, will let you know. Overall I highly suspect that this is a bug, since it simply cannot take so long to parse a couple megabytes of data that does not require backtracking. @Akxe are you sure that the original C code is only 20% faster? Are there any benchmarks in the repo?
from gopro-telemetry.
@meakbiyik I am not; a friend of mine who tested my implementation of GoPro telemetry vs original C and he said that the telemetry itself is not that much slower...
But given you are testing 4GB file, the extraction might be a lot slower...
Also, for me, the GMPF-Extract takes about 70% while the telemetry takes only about 30%...
from gopro-telemetry.
I don't think so. It just might be dependent on the file... For me, the extraction is the long process, not the telemetry processing...
from gopro-telemetry.
Hi @forna . Are you able to share the raw data file for analysis?
from gopro-telemetry.
Here is the file, you have to extract it: gpmfExtract.zip
Thanks
from gopro-telemetry.
Thanks for sharing that. Extracting your data to geojson is taking about 1 second on my end, on a very modest mac. Are you able to share a minimal repo to reproduce your exact conditions?
from gopro-telemetry.
OK sure. Do you have any favorite bundler? I am using Svelte that is integrated with Rollup, so I was thinking to use that.
from gopro-telemetry.
Anything that we can test by just running npm install and npm run start
from gopro-telemetry.
I can reproduce the issue with the goproTelemetry chained to the gpmfExtract (so the whole end-to-end process starting with the video file). This is how I do it in my application.
But I wanted to provide the repo with the goproTelemetry only so that the processing starts with the gpmfExtract file.
How have you loaded the binary gpmfExtract file I provided above into goproTelemetry?
I am struggling to convert it into a valid goproTelemetry input.
from gopro-telemetry.
I run this node script:
const goproTelemetry = require(`gopro-telemetry`);
const fs = require('fs');
const rawData = fs.readFileSync('gpmfExtract');
goproTelemetry(
{ rawData },
{ preset: 'geojson', stream: 'GPS', progress: console.log },
telemetry => {
fs.writeFileSync('output_path.json', JSON.stringify(telemetry));
console.log('Telemetry saved as JSON');
}
);
from gopro-telemetry.
Somehow I am not able to load into goproTelemetry the gpmfextract binary file I have provided.
So I have prepared the code with both the gpmf-extract and the gopro-telemetry (that's how my application works anyway).
Also, for troubleshooting purposes I don't think it would be useful if I provided the built SPA since it would have all libs bundled, minified with tree-shaking.
I suggest to use Svelte with Sveltekit so if you modify anything in the libs the project will be rebuilt automatically.
Here are the steps.
Assuming your projects folder is /projects and this new project's name is performance-test:
In /projects run the following command from the terminal (svelte scaffolding)
npm create svelte@latest performance-test
When prompted you can choose:
- Which Svelte app template? Skeleton project
- Add type checking with TypeScript? No
- Select additional options ? Press enter (nothing required)
cd performance-test
npm install
npm install gpmf-extract gopro-telemetry
In src/routes replace the +page.svelte file content with the one I've provided below
Start the dev server:
npm run dev
The application URL will be:
http://localhost:5173/
Select any GoPro video with the size around 1 GB and click Upload to see the goproTelemetry slowness.
The progress can be seen in the browser's console.
+page.svelte:
<script>
import { onMount } from 'svelte'
import { writable } from 'svelte/store'
import gpmfExtract from 'gpmf-extract'
import goproTelemetry from 'gopro-telemetry'
let uploadedFile = writable(null) // Declare uploadedFile as a writable store
onMount(() => {
// Update the uploadedFile store with the reference to the uploadedVideo element
uploadedFile.set(document.getElementById('uploadedFile'))
})
function processVideo() {
if ($uploadedFile.files.length === 0) {
return
}
const videoFile = $uploadedFile.files[0]
// Set the extract options
const gpmfExtractOptions = { browserMode: true, useWorker: false }
gpmfExtractOptions.progress = (percent) => {
console.log('gpmfExtract progress: ' + percent)
}
const goProTelemetryOptions = { preset: 'geojson', stream: 'GPS' }
goProTelemetryOptions.progress = (percent) => {
console.log('goProTelemetry progress: ' + percent)
}
gpmfExtract(videoFile, gpmfExtractOptions).then(gpmfExtractData => {
console.log('gpmfExtract completed')
goproTelemetry(gpmfExtractData, goProTelemetryOptions).then(goproTelemetryData => {
console.log('goproTelemetry completed')
}).catch((error) => {
alert('An error occurred during goproTelemetry processing: ' + error.message)
console.error(error)
})
}).catch((error) => {
alert('An error occurred during gpmfExtract processing: ' + error.message)
console.error(error)
})
}
</script>
<h1>Test goproTelemetry</h1>
<form id="uploadForm" enctype="multipart/form-data">
<input type="file" id="uploadedFile" name="video" accept="video/*" required>
<input type="submit" value="Upload" on:click={() => processVideo()} bind:this={$uploadedFile}>
</form>
from gopro-telemetry.
Hi @forna, Thank you for providing this example. On my end, it sometimes runs fast, sometimes really slow. I haven't really used the library on a browser environment (or used Svelte at all) so I don't know if this is normal. I don't see anything evidently wrong with your implementation, and the same files are parsed almost instantly in a Node environment.
from gopro-telemetry.
That makes sense... The library is heavily using nodeJS APIs that need to be polyfilled for browser... Could you try the older version? The one that was fully supporting of browsers or of the box?
from gopro-telemetry.
The version with full browser support is still the published one. I'm not sure we should keep it that way, but for now, only the Dev branch has been reverted (just the @gmod/binary-parser bits)
from gopro-telemetry.
I did a little profiling to see if it helps in understanding the issue. The result of the profiling is attached here (not sure if the raw file is helpful):
Overall, here are some stuff I noted:
![image](https://private-user-images.githubusercontent.com/23424198/246890152-aa4f8ff2-043f-406a-beb0-4ad4c30b8133.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTcxODUxMDksIm5iZiI6MTcxNzE4NDgwOSwicGF0aCI6Ii8yMzQyNDE5OC8yNDY4OTAxNTItYWE0ZjhmZjItMDQzZi00MDZhLWJlYjAtNGFkNGMzMGI4MTMzLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA1MzElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNTMxVDE5NDY0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWJiZmE1MzFjY2JmMDg4MmIyNmEwNzJiNDlhOTk3MTY3MGIyMzM4NmYyMTdiYjcxNDY0NjYxMGMxYjdlOTZiNGYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.ocL0Hx7XAlx-NeGY12Qb27qq0XDjxoQagebaBEURB-0)
Majority of the time is spent with findLastCC calls, and parseV calls to some extent. Not sure why should findLastCC be triggered so often.
![image](https://private-user-images.githubusercontent.com/23424198/246890649-f15b4df4-7251-459d-bdcc-5de022bf74e9.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTcxODUxMDksIm5iZiI6MTcxNzE4NDgwOSwicGF0aCI6Ii8yMzQyNDE5OC8yNDY4OTA2NDktZjE1YjRkZjQtNzI1MS00NTlkLWJkY2MtNWRlMDIyYmY3NGU5LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA1MzElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNTMxVDE5NDY0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWE1NzE1NTM4ZWVjZjllZDZjMDI5Mjg4MmM4YTYzZDlhMjdjNjNmNWYxZmQ1YzVkY2JjYmIyMDUyYTQ5ZDdmZmImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.OrKgKFUJZV4Hxu_R0ATaldw5HLUNOpNGn9cJ7ztGTvw)
findLastCC calls seem to be mostly triggered by the recursive parseKLV calls. ParseV calls also seem to be exclusively recursive, though in both cases it is just a single recursion.
Overall no obvious culprits, though I notice a lot of nested for/while loops in these functions, as well as array pushes.
from gopro-telemetry.
It may be something related to the Buffer lib polyfill.
Before Svelte I was trying to bundle the libs with browserify, but the Buffer lib was the only one that browserify was not able to handle, so I did not manage to provide the browserify repo.
But it works out of the box with Svelte (I am not sure how).
from gopro-telemetry.
To my knowledge, findLastCC
is responsible for finding the next part of the data... The format goes like this: VVVVDVVVVDVVVVD
where V
is video data and D
is metadata
from gopro-telemetry.
The
It may be something related to the Buffer lib polyfill. Before Svelte I was trying to bundle the libs with browserify, but the Buffer lib was the only one that browserify was not able to handle, so I did not manage to provide the browserify repo. But it works out of the box with Svelte (I am not sure how).
The current version of the library does not require any nodeJS polyfill. The compiler might yell, that it wants them, but they are optional. Rollup will not say anything; Webpack v5 will make a warning, Webpack v4 will bundle polyfills. I don't know the rest
from gopro-telemetry.
It may be something related to the Buffer lib polyfill. Before Svelte I was trying to bundle the libs with browserify, but the Buffer lib was the only one that browserify was not able to handle, so I did not manage to provide the browserify repo. But it works out of the box with Svelte (I am not sure how).
If you are polyfilling and suspect Buffer is problematic, try using the dev branch:
npm i juanirache/gopro-telemetry#dev
from gopro-telemetry.
As Akxe mentioned there is no polyfilling required.
The dev branch has libs not supported by the browser so it's not working.
from gopro-telemetry.
I'm wondering what latest info is on this. I'm trying to shift server work to the client to make is as offline-friendly as possible, and finding that for large files, the processing.. we'll let's say I've been unable to tell if it's crashed or just taking a long time.
for example:
406MB video (4:06 mins @ 1920 * 1080 * 29.97fps)
extracts: instant, (1,645,084 bytes)
process:
0.01 - 0.2 = 30s
0.2 - 0.4 = 5s
0.4 - complete = 16s
2,469 coordinates
5.67GB video (1:12:30 @ 1920 * 1080 * 29.97fps)
extracts: 23.5s, (29,029,180 Bytes)
process:
0.01 - ??? ~ 20 minutes no movement
times are obviously only so accurate as it's running in browser.
my code, running in web worker in browser:
import gpmfExtract from 'gpmf-extract';
import { goProTelemetry } from 'gopro-telemetry';
type FileSendType = { type: 'file'; file: File; videoId: string };
type FileCancelType = { type: 'cancel' };
const cancellationToken = { cancelled: false };
addEventListener(
'message',
(event: MessageEvent<FileSendType | FileCancelType>) => {
switch (event.data.type) {
case 'file': {
// browser has sent message with video file as payload, as well as a video ID so that any info back to the browser is labelled to the right video
const videoId = event.data.videoId;
gpmfExtract(event.data.file, {
browserMode: true,
progress: (extractionProgress) => {
return postMessage({ videoId, extractionProgress });
},
cancellationToken,
})
.then((res) => {
postMessage({ videoId, extractComplete: res });
goProTelemetry(res, {
stream: ['GPS'],
debug: true, // tried playing with this...
raw: true, // this...
tolerant: true, // this...
preset: 'geojson', // ...and this, and didn't notice anything different
progress: (processingProgress) =>
// update user of progress
postMessage({ videoId, processingProgress }),
})
.then((res) => {
postMessage({ videoId, processComplete: res });
})
.catch((e) => {
postMessage({ videoId, error: e.message });
});
if (!res) return;
})
.catch((e) => {
postMessage({ videoId, error: e.message });
});
break;
}
case 'cancel': {
// "cancel" button clicked by user
cancellationToken.cancelled = true;
break;
}
}
}
);
I'm also not getting any kind of errors thrown in browser console.
When I view performance I see a long brown line, which zoomed in, turns out to be a whole lot of garbage collection, not sure that to make of that:
Sorry that's all I really have to help, let me know what else I can do
from gopro-telemetry.
The thing is when running in Node, the extraction and processing combined for the same 5.67GB video takes 30 seconds, while browser side sits idle for at least 20 mins, so something in the browser version is definitely ending prematurely or getting stuck in a loop. By comparison, the 406MB video which takes about 50s in browser is done in less than 2 seconds in Node.
Forgot to point out, this is with:
"gopro-telemetry": "^1.2.3",
"gpmf-extract": "^0.3.1",
I also tried with and without egm96-universal
installed, but that made no difference.
I also just tried the svelte example above (I'm using react/next in my example) and still seeing same results as described by @forna , in his version as with my own.
from gopro-telemetry.
@forna FWIW, I'm noticing a huge speed difference in your svelte example between Firefox vs Chrome/Edge, FF being way slower just to extract, let alone process the telemetry. Are you seeing this and do you think it proved any clues?
from gopro-telemetry.
Hi, unfortunately I am not using goproTelemetry anymore since I was not able to make it work properly in the browser.
I have developed my own script but it only extracts a small subset of the available metadata.
from gopro-telemetry.
Related Issues (20)
- Telemetry Extractor Lite VIRB time bug HOT 2
- Wrong Axis Order HOT 3
- Number of frames in video HOT 2
- Don't understand WrongSpeed option HOT 4
- Using gopro-telemetry in web browser HOT 4
- Typo in samples/examples.js : GPS5Precision is correct option? HOT 1
- [DOUBT] GO PRO Files missing track data after renaming HOT 3
- KML & GPX presets- invalid characters HOT 9
- groupTimes option seems to be broken HOT 4
- Documentation unclear HOT 3
- `setImmediate` is not supported in any browser HOT 2
- Remove egm96 HOT 4
- Error: Error, negative length HOT 1
- Either fix tests for @gmod/binary-parser or fix raw -> parsedData with binary-parser HOT 11
- Duplicate Date Times / Bad Sample Data HOT 4
- buffer.readDoubleBE is not a function at readInt64BEasFloat HOT 12
- CircleCI tests timeout
- Data mismatch while extracting telemetry HOT 1
- MP4 times wrong when first file in series missing
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from gopro-telemetry.